【Vue】Re19 VueX 第一部分(共享資料,Getters)
阿新 • • 發佈:2020-11-02
一、概述
專門為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>