我是一个刚刚学习 vuex 的小白,这两天主要连着官网和资料还有项目里的 vuex 在学习,在这里记下自己学习的一些总结,一方面是我自己的学习提升,也希望对你有所帮助。首先我们来理解下为什么要用 vuex?我们先来捋下父子组件和非父子组件之间的通信。父子组件:先来定义下有 parent.vue 和 childOne.vue 和 childTwo.vue1. 属性传值
//parent.vue 里可以写(写的都是部分代码)
<child-one :params=”params”></child-one>
//childOne.vue 里用 props 接收
// 只有开发原型系统能接收
props:[‘params’],
// 稍微好点的写法(我在项目里就这样写的)
props:{
params: Object
}
// 更好的写法
props:{
params: {
type: Object,
required: true, // 必填的字符串
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return {message: ‘hello’}
}
// 自定义校验这个值必须匹配下列字符串中的一个
validator: function(value){
return[
‘name’
‘sex’
”
…
‘error’
].indexOf(value) !== -1
}
}
}
// 这里扩散了一点 props 越看越多 要详细看的请去看官网 //https://cn.vuejs.org/v2/guide/components-props.html
2.$refs 不止传参哦
//parent.vue 里面
<template>
<child-one ref=”child1″></child-one>
<script>
this.$child1.clickChildOne() // 调用 child1 的 clickChildOne 方法 传参有时候觉得超方便 设置子组件的样式也超方便 安利, 哈哈
3.$parent.$parent.$parent(请你一定要找对层级 ‘_’)
// 主要是子组件给父级组件传参数或者调用父组件的方法
childOne.vue 里
<script>
methods: {
// 调用父级的方法 getParentDeta()
clickHandleDeta() {
// 几个 parent 通过自己的层级找吧..
this.$parent.$parent.$parent.getParentDeta()
}
}
非父子组件传值 1. 通过共同的父级来一级一级的传上去然后再传下来(就不写代码了)2. 集中式的事件中间件就是 Bus,来处理 这里详细说下
//app.js
var createBus = {
install(Vue,options) {
Vue.prototype.$bus = vue
}
}
Vue.use(createBus)
//childOne.vue 里
<script>
methods: {
getDeta() {
this.$bus.$emit(‘todoSth’, params); //emit 触发 params 是传递的参数
}
}
//childTwo.vue 里
<script>
mounted: {
this.$bus.$on(‘todoSth’, params); //on 接收
}
vuex 它就是可以用在大中型项目(当然你想用那个地方都能用)用全局单例模式管理来管理多个组件公共的数据或者方法。
// 一个貌似四肢健全的 vuex(有 state、getters、actions、mutations、module)
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit(‘increment’)
}
}
})
下面我们按顺序一一来介绍和学习 state 用来数据共享数据存储 mutation 用来注册改变数据状态 getters 用来对共享数据进行过滤操作 action 解决异步改变共享数据 mutations1. 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation2.Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。而调用或者说唤醒 mutations 就必须用 store.commit
store.commit(‘increment’)
你可以向 store.commit 传入额外的参数, 字段或者对象都行的。在大多数情况下,参数应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读。
store.commit(‘increment’, {
amount: 10
})
但是 mutations 是同步执行的,就是说 mutations 中的方法是不分组件的 , 假如你在 hello1.js 文件中的定义了 add 方法 , 在其他文件中的一个 add 方法 , 那么 $store.commit(‘add’) 会执行所有的 add 方法! 这个时候就是 actions 出现的时候了。actions 多个 state 的操作, 使用 mutations 会来触发会比较好维护 , 那么需要执行多个 mutations 就需要用 action 了。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit(‘increment’)
}
}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,就是说 context.commit 可以提交一个 mutation,可以调用 context.state 和 context.getters 来获取 state 和 getters。使用 $store.dispatch(‘switch_dialog’) 来触发 action 中的 increment 方法还记得 mutation 必须同步执行这个限制么?Action 就不受约束!我们可以在 action 内部执行异步操作:
actions: {
incrementAsync ({commit}) {
setTimeout(() => {
commit(‘increment’)
}, 1000)
}
}
Actions 参数也可以是对象啥的
// 以载荷形式分发
store.dispatch(‘incrementAsync’, {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: ‘incrementAsync’,
amount: 10
})
很多时候 , $store.state.dialog.show、$store.dispatch(‘switch_dialog’) 这种写法又长又臭 , 很不方便。使用 mapState、mapGetters、mapActions 就不会这么复杂了。
<template>
<el-dialog>{{count}}</el-dialog>
</template>
<script>
import {mapState} from ‘vuex’;
export default {
computed:{
// 这里的三点叫做 : 扩展运算符
…mapState({
count:state => state.dialog.count
}),
}
}
</script>
相当于
<template>
<el-dialog>{{count}}</el-dialog>
</template>
<script>
import {mapState} from ‘vuex’;
export default {
computed:{
count(){
return this.$store.state.dialog.count;
}
}
}
</script>
mapGetters、mapActions 和 mapState 类似,mapGetters 一般也写在 computed 中 ,mapActions 一般写在 methods 中。