【Vue】Re20 VueX 第一部分(共享数据,Getters)
一、概述
专门为VueJS应用程序开发的状态管理模式
集中式存储管理应用的所有组件的状态,按照相应的规则保证状态以一种可预测的方式发生变化
VueX也集成到了官方调试工具devtools extension中
状态共享问题:
类似JavaWeb中的Session,每一个资源共同需要的变量
二、案例演示
首先需要安装VueX,CLI2的安装是没有提供VueX的
npm install vuex --save
App.vue
<template> <div id="app"> <h3>{{message}}</h3> <p> <button @click="$store.state.count --"> - </button> <span>{{$store.state.count}}</span> <button @click="$store.state.count ++"> + </button> </p> <vuex-comp></vuex-comp> </div> </template> <!-- Actions行为 + View视图 + State状态 --> <script> import VueXComp from "./components/VueX"; export default { name: 'App', data () { return { message : 'sss', // count : 0 } }, components : { vuexComp : VueXComp }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
VueX.vue
<template> <div> <h3>VueX Component</h3> <p>{{$store.state.count}}</p> </div> </template> <script> export default { name: "VueX" } </script> <style scoped> </style>
store目录的Index.js
import Vue from 'vue'; import VueX from 'vuex'; /* 安装VueX */ Vue.use(VueX); const store = new VueX.Store({ state : { /* 状态保存,存放所有组件共享的对象 */ count : 0 }, mutations : { }, actions : { }, modules : { } }); export default store;
main.js引入VueX的初始化:
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import Store from './store'; Vue.config.productionTip = false // Vue.use(VueX); /* eslint-disable no-new */ new Vue({ el: '#app', router, store : Store, components: { App }, template: '<App/>' })
两个组件是共用store中的state属性的count
变量引用依靠$store
$store.state.定义的属性
但是官方不推荐使用上面这样的直接引用获取
因为在devtools的调试插件中可以发现这样的问题:
在界面中的点击,共享的count数据更新了,但是在调试插件中的vuex属性状态栏中,
数据是没有发生变化的。
使用mutations实现,并且可以被devtools跟踪
至少使用先使用mutations调用,如果还有请求的操作,那还需要actions中调用
store/index.js
import Vue from 'vue'; import VueX from 'vuex'; /* 安装VueX */ Vue.use(VueX); const store = new VueX.Store({ state : { /* 状态保存,存放所有组件共享的对象 */ count : 0 }, mutations : { /* */ increment (state) { state.count ++ }, decrement (state) { state.count -- } }, actions : { }, modules : { } }); export default store;
首页App.vue
<template> <div id="app"> <h3>{{message}}</h3> <p> <!-- <button @click="$store.state.count --"> - </button>--> <button @click="aaa"> - </button> <span>{{$store.state.count}}</span> <button @click="bbb"> + </button> <!-- <button @click="$store.state.count ++"> + </button>--> </p> <vuex-comp></vuex-comp> </div> </template> <!-- Actions行为 + View视图 + State状态 --> <script> import VueXComp from "./components/VueX"; export default { name: 'App', data () { return { message : 'sss', // count : 0 } }, methods : { aaa () { this.$store.commit('decrement'); }, bbb () { this.$store.commit('increment'); } }, components : { vuexComp : VueXComp }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
修改预览的效果可以跟踪Mutations的方法执行
但是state变量不知道为什么对不上值:
三、使用Getters计算复杂的需求
现在Store中多了一组学生信息,需求是获取某一属性的某一范围的所有学生信息
例如年龄大于20或者小于20
store/index.js
import Vue from 'vue'; import VueX from 'vuex'; /* 安装VueX */ Vue.use(VueX); const store = new VueX.Store({ state : { /* 状态保存,存放所有组件共享的对象 */ count : 0, str : 'sss', students : [ { id : 110, name : '学生110', age : 28, gender : true, }, { id : 111, name : '学生111', age : 18, gender : true, }, { id : 112, name : '学生112', age : 38, gender : false, }, { id : 113, name : '学生113', age : 14, gender : true, }, { id : 114, name : '学生114', age : 44, gender : false, }, { id : 115, name : '学生115', age : 10, gender : true, }, ] }, mutations : { /* */ increment (state) { state.count ++ }, decrement (state) { state.count -- }, }, actions : { }, modules : { }, getters : { getStringJoin (state) { return state.str + 'saa'; }, getCount (state) { return state.count; }, large20Age (state) { return state.students.filter(student => student.age > 20); } } }); export default store;
App.vue
<template> <div id="app"> <h3>{{message}}</h3> <p> <!-- <button @click="$store.state.count --"> - </button>--> <button @click="aaa"> - </button> <!--<span>{{$store.state.count}}</span>--> <strong>{{$store.getters.getCount}}</strong> <button @click="bbb"> + </button> <!-- <button @click="$store.state.count ++"> + </button>--> </p> <ul> <!-- 使用store的getters属性调用 --> <li v-for="student in $store.getters.large20Age"> {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}} </li> </ul> <ul> <!-- 使用当前组件computed属性调用 --> <li v-for="student in largeThan20Age"> {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}} </li> </ul> <p> {{$store.getters.getStringJoin}} </p> <vuex-comp></vuex-comp> </div> </template> <!-- Actions行为 + View视图 + State状态 --> <script> import VueXComp from "./components/VueX"; export default { name: 'App', data () { return { message : 'sss', // count : 0 } }, methods : { aaa () { this.$store.commit('decrement'); }, bbb () { this.$store.commit('increment'); } }, computed : { // largeThan20Age () { // return this.$store.state.students.filter(student => { // return student.age >= 20; // }); // } largeThan20Age () { return this.$store.state.students.filter(student => student.age >= 20); } }, components : { vuexComp : VueXComp }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
getters属性支持内嵌式调用,提高了其他getters方法的可重用性
getters : { getStringJoin (state) { return state.str + 'saa'; }, getCount (state) { return state.count; }, large20Age (state) { return state.students.filter(student => student.age > 20); }, large20AgeLength (state, getters) { return getters.large20Age.length; } }
年龄限制条件交给参数决定,更灵活的需求:
getters方法无法自定义我们希望的参数【已经固定了参数格式,第一state、第二getters】
解决方案是先返回一个函数,在这个函数的形参就可以获取了,然后里面再写需求逻辑
largeAgeBy (state) { return age => { return state.students.filter(student => student.age > age); } }
App.vue调用
<template> <div id="app"> <h3>{{message}}</h3> <p> <!-- <button @click="$store.state.count --"> - </button>--> <button @click="aaa"> - </button> <!--<span>{{$store.state.count}}</span>--> <strong>{{$store.getters.getCount}}</strong> <button @click="bbb"> + </button> <!-- <button @click="$store.state.count ++"> + </button>--> </p> <ul> <!-- 使用store的getters属性调用 --> <li v-for="student in $store.getters.large20Age"> {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}} </li> </ul> <ul> <!-- 使用当前组件computed属性调用 --> <li v-for="student in largeThan20Age"> {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}} </li> </ul> <p>{{$store.getters.large20AgeLength}}</p> <p> {{$store.getters.getStringJoin}} </p> <ul> <li v-for="student in $store.getters.largeAgeBy(0)"> {{student.id}} {{student.name}} {{student.age}} {{student.gender}} </li> </ul> <vuex-comp></vuex-comp> </div> </template> <!-- Actions行为 + View视图 + State状态 --> <script> import VueXComp from "./components/VueX"; export default { name: 'App', data () { return { message : 'sss', // count : 0 } }, methods : { aaa () { this.$store.commit('decrement'); }, bbb () { this.$store.commit('increment'); } }, computed : { // largeThan20Age () { // return this.$store.state.students.filter(student => { // return student.age >= 20; // }); // } largeThan20Age () { return this.$store.state.students.filter(student => student.age >= 20); } }, components : { vuexComp : VueXComp }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>