前言
本文从大概会包括以下几个内容
- 常用的组件通讯方式
- 多组件之间共享(数据)的解决方案——Vuex
组件通讯方式
- 父组件给子组件传值:通过props传值
<!--父组件 parentComponent.vue-->
<div>
<child-component title="hello"></child-component>
</div>
<script>
import { childComponent } from './childComponent'
export default {
components:{
childComponent
}
}
</script>
<!--子组件 childComponent.vue-->
<div>{{ title }}</div>
<script>
export default {
props: ['title']
}
</script>
- 子传父亲:
$event/$on
<!--子组件中发布一个事件-->
<button v-on:click="$emit('enlargeText', 0.1)"> Enlarge text </button>
<!--父组件监听这个自定义事件-->
<blog-post v-on:enlargeText="hFontSize += $event"></blog-post>
- 非父子组件:Event Bus
// eventbus.js
export default new Vue()
// 用$emit发布事件
bus.$emit('自定义事件名称', 数据);
// 用$on订阅事件
bus.$on('自定义事件名称', data => {
// 执行操作
})
- 父直接访问子组件:通过 ref 获取子组件
ref 有两个作用:
- 如果你把它作用到普通 HTML 标签上,则获取到的是 DOM
- 如果你把它作用到组件标签上,则获取到的是组件实例
$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组 件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs 。
多组件之间共享(数据)的解决方案——Vuex
当我们遇到以下问题的时候,上面的通讯方式就不太适用了
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
建议符合这种场景的业务使用 Vuex 来进行数据管理,例如非常典型的场景:购物车。
Vuex回顾
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件 的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调 试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调 试功能。
- Vuex是专门为Vue.js设计的状态管理库
- 它采用集中式的方式存储需要共享的数据
- 从使用的角度,他就是JavaScript库
- 他的作用是进行状态管理,解决复杂组件通讯,数据共享
Vuex核心概念
上面演示了vuex整个工作流程。
- state是管理的全局状态,把状态绑定到了组件,渲染到用户界面,展示给用户
- 用户可以跟视图交互,可以通过dispatch下发到actions
- actions 可以进行异步操作,异步操作结束后,通过commit 提交到mutation,记录状态的更改
- mutation必须是同步的,所有状态的更改都要通过mutation,我们可以通过它记录所有状态的变化
Vuex中几个核心概念
- Store: 仓库,是使用vuex的核心,每一个应用仅有一个Store,Store是一个容器,包含应用中的大部分状态,我们不能直接改变Store中的状态,要提交mutation的方式改变状态
- State: 状态, 保存在Store中,因为Store是唯一的,所以State也是唯一的,称为单一状态树,但是所有状态都保存在State中的话会让程序难以维护,可以通过后续的模块解决该问题,这里面的状态是响应式的
- Getter: 计算属性,方便从一个属性派生出其他的值,内部可以对计算的结果进行缓存,只有当依赖状态重新改变,才会重新计算
- Mutation:状态的变化必须通过mutation完成
- Action:action可以进行异步操作
- Mudule: 模块,可以将Store分割成模块,每个模块拥有自己的state/mutaion/action/getter
vuex 使用示例
- store仓库
export default {
state: {
user: {
name: 'xiaomao', age: 18,
sex: '男'
}
},
mutations: {
SET_USER_NAME(state,name):{
state.user.name = name
}
},
actions: {
changeUserNameAction ({commit},name) {
commit('SET_USER_NAME', name)
}
}
}
- State
/**------------1. 接收数组参数 ---------------*/
// 该方法是 vuex 提供的,所以使用前要先导入 import { mapState } from 'vuex'
// mapState 返回名称为 count 和 msg 的计算属性 // 在模板中直接使用 count 和 msg
computed: {
...mapState(['user'])
}
/**------------2. 接收对象参数 ---------------*/
computed: {
...mapState({
user: state => state.user
})
}
- Getter
import { mapGetter } from 'vuex'
computed: {
...mapGetter(['reverseMsg']),
// 改名,在模板中使用 reverse
...mapGetter({
reverse: 'reverseMsg'
})
}
- Mutation
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['increate']), // 传对象解决重名的问题
...mapMutations({
increateMut: 'increate'
})
}
- Action
// Action 提交的是mutation,而不是直接变更状态
// Action 可以包含任何异步操作
import { mapActions } from 'vuex'
methods: {
...mapActions(['increate']), // 传对象解决重名的问题
...mapActions({
increateAction: 'increate'
})
}
- Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、 mutation、action、getter、甚至是嵌套子模块。