组件之间的通讯:vuex状态管理,state,getters,mutations,actons的简单使用(一)
之前的文章中讲过,组件之间的通讯我们可以用$children、$parent、$refs、props、data。。。
但问题来了,假如项目特别大,组件之间的通讯可能会变得十分复杂。。。
这个时候了我们就用vuex进行组件通讯 。
至于什么是vuex,简单的说就是一个状态管理器,它管理着我们所有想要它管理的状态,这也就意味某一状态一经变化,其他使用到这个状态的其他组件中数据也会变化
还是一如既往的我不安装,vue-cli开发环境
使用vuex先要引入vuex,创建一个vues.Store();
vuex.Store({
state:{},//状态数据集
getters:{},//公共状态数据集
mutations:{},//主要用于改变状态
actions:{} //是可以解决异步问题
})
1)组件中访问状态数据(this.$store.state.状态名),如果你的状态较少,我们可以直接配合vue的计算属性computed使用
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="../lib/vue.js"> </script> <script src="../lib/vuex.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in unregisteredUsers">{{item.name}}</li> </ul> <app-registration></app-registration> <app-registrations></app-registrations> </div> </body> </html> <script> const ch1 = { template: `<div> <span>这是第一个子组件</span> <p>---------------------------------</p> <div class="row" v-for="item in users"> <p>{{item.name}}</p> <button @click="registerUser(item)">registerUser</button> </div> </div>`, // props:{用了vuex就不需要使用props // registration:Array // }, computed: { users() { return this.$store.state.users.filter(user => { return !user.registred; }); } }, methods: { registerUser(user) { user.registered = true; const date = new Date; this.$store.state.registrations.push({ userId: user.id, name: user.name, date: date.getMonth() + '/' + date.getDay() }); } } }; const ch2 = { template: `<div> <span>这是第2个子组件</span> <p></p> </div>`, // props:{ // users:Array // }, // }; const store = new Vuex.Store({ state: { //填充用于管理状态的共享变量 registrations: [], users: [ { id: 1, name: 'Max', registered: false }, { id: 2, name: 'Anna', registered: false }, { id: 3, name: 'Chris', registered: false }, { id: 4, name: 'Sven', registered: false } ] } }) //Vue.use(Vuex); var myvue = new Vue({ el: '#app', store, computed: { unregisteredUsers() { // return this.$store.state.users.filter((user) => { // return !user.registered; // }); return this.$store.state.registrations; } }, components: { appRegistration: ch1, appRegistrations: ch2 } }); </script>
2)getters 主要用于对多出使用的数据做集中处理
访问方式:this.$store.getters.状态名;
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="../lib/vue.js"> </script> <script src="../lib/vuex.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in unregisteredUsers">{{item.name}}</li> </ul> <app-registration></app-registration> <app-registrations></app-registrations> </div> </body> </html> <script> const ch1 = { template: `<div> <span>这是第一个子组件</span> <p>---------------------------------</p> <div class="row" v-for="item in users"> <p>{{item.name}}</p> <button @click="registerUser(item)">registerUser</button> </div> </div>`, // props:{用了vuex就不需要使用props // registration:Array // }, computed: { users() { return this.$store.state.users.filter(user => { return !user.registred; }); } }, methods: { registerUser(user) { user.registered = true; const date = new Date; this.$store.state.registrations.push({ userId: user.id, name: user.name, date: date.getMonth() + '/' + date.getDay() }); } } }; const ch2 = { template: `<div> <span>这是第2个子组件</span> <p>--------没注册的用沪------------</p> <ul> <li v-for="item in unregistration">{{item.name}}</li> </ul> </div>`, computed:{ unregistration(){ return this.$store.getters.unregisterdUsers; } } }; const store = new Vuex.Store({ state: { //填充用于管理状态的共享变量 registrations: [], users: [ { id: 1, name: 'Max', registered: false }, { id: 2, name: 'Anna', registered: false }, { id: 3, name: 'Chris', registered: false }, { id: 4, name: 'Sven', registered: false } ] }, getters:{ unregisterdUsers(state){ return state.users.filter(user=>{ return !user.registered; }); }, registeredUser(state){ return state.user.filter(user=>{ return user.registered; }); }, totalregisteration(state){ return state.registrations.length; } } }) //Vue.use(Vuex); var myvue = new Vue({ el: '#app', store, computed: { unregisteredUsers() { return this.$store.state.users.filter((user) => { return !user.registered; }); return this.$store.state.registrations; } }, components: { appRegistration: ch1, appRegistrations: ch2 } }); </script>
3)如果组件想要改变vuex中状态值,我们需要借助于mutations了、
首先组件自己得定义一个方法,使用this.$store.commit({type:'addNum',n:n,m:m });触发这个方法,其中n、m是参数
然后要在mutations中定义这个addNum方法
mutations:{//mutations中的函数第一个参数是state
addNum(state,ob){
state.count+=ob.n;
}
},
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="../lib/vue.js"></script> <script src="../lib/vuex.js"></script> </head> <body> <p> mutation的作用就是,是的子组件可以请求 修改store中state的数据 </p> <div id="app"> <p>我是父组件中的实例:{{parentdata}}</p> <first-child></first-child> </div> </body> </html> <script> //定义一个子组件 const ch1={ template:` <div> <p>你可以进行数据操作,改变store中state的数据:{{varity}}</p> <button @click="add(varity)"> 点击试试</button> </div> `, computed:{ varity(){ return this.$store.state.count; } }, methods:{ add:function(n){//子组件通过其自己的方法,直接commit,触发mutations中的方法进而改变状态 //方式一: this.$store.commit({ type:'addNum', n:n }); //方式e二: //this.$store.commit('addNum',{n:n}); } } }; var store=new Vuex.Store({ state:{ count:1, users:[{name:'han',age:23},{name:'tom',age:22},{name:'jarry',age:33}], }, getters:{ }, mutations:{//mutations中的函数第一个参数是state addNum(state,ob){ state.count+=ob.n; } }, }); var myvue=new Vue({ el:"#app", store, components:{ firstChild:ch1, }, computed:{ parentdata(){ return this.$store.state.count; } } }); </script>
4)actions 用于解决多个函数执行的异步问题 ,
本质上也是改变状态嘛,我们使用mutations貌似就可以改变状态了,但是不能解决异步的问题,居然mutations能改变状态,那我们在他的基础上加点什么东西是不是就能 解决异步的问题呢?没错就是actions,
methods----------------------------------------$store.dispatch------------------------------->actions------------------------------->mutations
[解决异步问题,就是在mutations上多了个ations这个步骤,这样解释只是为了大家更好的接受而已,不一定正确]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="../lib/vue.js"></script> <script src="../lib/vuex.js"></script> </head> <body> <p>关于action: 官方说的是为了解决异步的问题, 因为mutations中可能有多个无方法接口,同步执行会大大的降低效率,因此我们急切需要一种方法,及action</p> <div id="app"> <first-child></first-child> </div> </body> </html> <script> const ch1={ template:` <div> <p>这是我的第一个组件</p> <p> <button @click="adds(num)">通过action进行操作</button>: <span>{{num}}</span></p> <p> <button @click="add(num)">通过mutations进行操作</button>:<span>{{num}}</span></p> </div> `, methods:{ adds:function(n){ //this.$store.dispatch('addCount',n);\n this.$store.dispatch({type:'addCount',n:n}); }, add:function(n){ //this.$store.commit('addNum',n); this.$store.commit({ type:'addNum', n:n }); } }, computed:{ num(){ return this.$store.state.smalldata; } } }; // const ch2={ // template:` // <div> // <p>这是我的第二个组件</p> // <span>{{}}</span> // </div> // `, // // }; // const store=new Vuex.Store({ state:{ smalldata:1, }, getters:{}, mutations:{ addNum(state,obj){ state.smalldata+=obj.n; } }, actions:{ // addCount(co,n){ // co.commit('addNum',n); // }, addCount({commit},obj){ commit('addNum',obj); } }, }); const myvue=new Vue({ el:'#app', store, components:{ firstChild:ch1, //secondChild:ch2, } }); </script>