uniapp中vuex的應(yīng)用使用步驟
一、vuex是什么?
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
按照自己理解來說就是公共數(shù)據(jù)管理模塊。如果應(yīng)用中數(shù)據(jù)量比較大的可以應(yīng)用,不是很大的建議用緩存即可。
二、使用步驟
使用準(zhǔn)備在項(xiàng)目中新建store目錄,在該目錄下新建index.js文件
1.引入
由于uniapp中內(nèi)置了vuex,只需要規(guī)范引入即可:
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);//vue的插件機(jī)制
//Vuex.Store 構(gòu)造器選項(xiàng)
const store = new Vuex.Store({
state:{//存放狀態(tài)
"username":"foo",
"age":18
}
})
export default store
// 頁面路徑:main.js
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.prototype.$store = store
App.mpType = 'app'
// 把 store 對(duì)象提供給 “store” 選項(xiàng),這可以把 store 的實(shí)例注入所有的子組件
const app = new Vue({
store,
...App
})
app.$mount()
2.state屬性,主要功能為存儲(chǔ)數(shù)據(jù)
第一種方法:通過屬性訪問,需要在根節(jié)點(diǎn)注入 store 。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<text>用戶名:{{username}}</text>
</view>
</template>
<script>
import store from '@/store/index.js';//需要引入store
export default {
data() {
return {}
},
computed: {
username() {
return store.state.username
}
}
}
</script>
第二種方法:在組件中使用,通過 this.$store 訪問到 state 里的數(shù)據(jù)。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<text>用戶名:{{username}}</text>
</view>
</template>
<script>
export default {
data() {
return {}
},
computed: {
username() {
return this.$store.state.username
}
}
}
</script>
進(jìn)階方法:通過 mapState 輔助函數(shù)獲取。當(dāng)一個(gè)組件需要獲取多個(gè)狀態(tài)的時(shí)候,將這些狀態(tài)都聲明為計(jì)算屬性會(huì)有些重復(fù)和冗余。 為了解決這個(gè)問題,我們可以使用 mapState 輔助函數(shù) 幫助我們生成計(jì)算屬性,讓你少按幾次鍵,(說白了就是簡(jiǎn)寫,不用一個(gè)一個(gè)去聲明了,避免臃腫)
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>用戶名:{{username}}</view>
<view>年齡:{{age}}</view>
</view>
</template>
<script>
import { mapState } from 'vuex'//引入mapState
export default {
data() {
return {}
},
computed: mapState({
// 從state中拿到數(shù)據(jù) 箭頭函數(shù)可使代碼更簡(jiǎn)練(就是簡(jiǎn)寫)
username: state => state.username,
age: state => state.age,
})
}
</script>
3. Getter屬性,主要功能為計(jì)算篩選數(shù)據(jù)
可以認(rèn)為是 store 的計(jì)算屬性,對(duì) state 的加工,是派生出來的數(shù)據(jù)。 就像 computed 計(jì)算屬性一樣,getter 返回的值會(huì)根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生改變才會(huì)被重新計(jì)算。(重點(diǎn),響應(yīng)式數(shù)據(jù)的應(yīng)用)
可以在多組件中共享 getter 函數(shù),這樣做還可以提高運(yùn)行效率。
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
todos: [{
id: 1,
text: '我是內(nèi)容一',
done: true
},
{
id: 2,
text: '我是內(nèi)容二',
done: false
}
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
export default store
Getter屬性接收傳遞參數(shù),主要為:state, 如果在模塊中定義則為模塊的局部狀態(tài)。getters, 等同于 store.getters。
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
todos: [{
id: 1,
text: '我是內(nèi)容一',
done: true
},
{
id: 2,
text: '我是內(nèi)容二',
done: false
}
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
//state :可以訪問數(shù)據(jù)
//getters:訪問其他函數(shù),等同于 store.getters
return getters.doneTodos.length
},
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
})
export default store
應(yīng)用Getter屬性方法一:通過屬性訪問,Getter 會(huì)暴露為 store.getters 對(duì)象,你可以以屬性的形式訪問這些值。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view v-for="(item,index) in todos">
<view>{{item.id}}</view>
<view>{{item.text}}</view>
<view>{{item.done}}</view>
</view>
</view>
</template>
<script>
import store from '@/store/index.js'//需要引入store
export default {
computed: {
todos() {
return store.getters.doneTodos
}
}
}
</script>
應(yīng)用Getter屬性方法二:通過 this.$store 訪問。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view v-for="(item,index) in todos">
<view>{{item.id}}</view>
<view>{{item.text}}</view>
<view>{{item.done}}</view>
</view>
</view>
</template>
<script>
export default {
computed: {
todos() {
return this.$store.getters.doneTodos
}
}
}
</script>
應(yīng)用Getter屬性方法三:你也可以通過讓 getter 返回一個(gè)函數(shù),來實(shí)現(xiàn)給 getter 傳參。在你對(duì) store 里的數(shù)組進(jìn)行查詢時(shí)非常有用。注意,getter 在通過方法訪問時(shí),每次都會(huì)去進(jìn)行調(diào)用,而不會(huì)緩存結(jié)果。(一次調(diào)用,一次請(qǐng)求,沒有依賴關(guān)系)
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view v-for="(item,index) in todos">
<view>{{item}}</view>
</view>
</view>
</template>
<script>
export default {
computed: {
todos() {
return this.$store.getters.getTodoById(2)
}
}
}
</script>
應(yīng)用Getter屬性方法進(jìn)階(簡(jiǎn)寫):通過 mapGetters 輔助函數(shù)訪問。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>{{doneTodosCount}}</view>
</view>
</template>
<script>
import {mapGetters} from 'vuex' //引入mapGetters
export default {
computed: {
// 使用對(duì)象展開運(yùn)算符將 getter 混入 computed 對(duì)象中
...mapGetters([
'doneTodos',
'doneTodosCount',
// ...
])
}
}
</script>
4. Mutation屬性,Vuex中store數(shù)據(jù)改變的唯一地方(數(shù)據(jù)必須同步)
通俗的理解,mutations 里面裝著改變數(shù)據(jù)的方法集合,處理數(shù)據(jù)邏輯的方法全部放在 mutations 里,使數(shù)據(jù)和視圖分離。Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù):
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
add(state) {
// 變更狀態(tài)
state.count += 2
}
}
})
export default store
你不能直接調(diào)用一個(gè) mutation handler。這個(gè)選項(xiàng)更像是事件注冊(cè):“當(dāng)觸發(fā)一個(gè)類型為 add 的 mutation 時(shí),調(diào)用此函數(shù)”,要喚醒一個(gè) mutation handler,你需要以相應(yīng)的 type 調(diào)用 store.commit 方法。
注意:store.commit 調(diào)用 mutation(需要在根節(jié)點(diǎn)注入 store)。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>數(shù)量:{{count}}</view>
<button @click="addCount">增加</button>
</view>
</template>
<script>
import store from '@/store/index.js'
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
addCount() {
store.commit('add')
}
}
}
</script>
mutation中的函數(shù)接收參數(shù):你可以向 store.commit 傳入額外的參數(shù),即 mutation 的 載荷(payload):
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
//傳遞數(shù)值
add(state, n) {
state.count += n
}
//傳遞對(duì)象類型
add(state, payload) {
state.count += payload.amount
}
}
})
export default store
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>數(shù)量:{{count }}</view>
<button @click="addCount">增加</button>
</view>
</template>
<script>
import store from '@/store/index.js'
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
//傳遞數(shù)值
addCount() {
store.commit('add', 5)//每次累加 5
}
//傳遞對(duì)象
addCount () {//把載荷和type分開提交
store.commit('add', { amount: 10 })
}
}
}
</script>
應(yīng)用Getter屬性方法二:通過 this.$store 訪問。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view v-for="(item,index) in todos">
<view>{{item.id}}</view>
<view>{{item.text}}</view>
<view>{{item.done}}</view>
</view>
</view>
</template>
<script>
export default {
computed: {
todos() {
return this.$store.getters.doneTodos
}
}
}
</script>
應(yīng)用mutation屬性方法進(jìn)階(簡(jiǎn)寫):通過 mapMutations輔助函數(shù)訪問。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>數(shù)量:{{count}}</view>
<button @click="add">增加</button>
</view>
</template>
<script>
import { mapMutations } from 'vuex'//引入mapMutations
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
...mapMutations(['add'])//對(duì)象展開運(yùn)算符直接拿到add
}
}
</script>
5. Action屬性:
action 提交的是 mutation,通過 mutation 來改變 state,而不是直接變更狀態(tài),action 可以包含任意異步操作。
// 頁面路徑:store/index.js
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 1
},
mutations:{
add(state) {
// 變更狀態(tài)
state.count += 2
}
},
actions:{
addCountAction (context) {
context.commit('add')
}
}
})
export default store
action 函數(shù)接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象,因此你可以調(diào)用 context.commit 提交一個(gè) mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters。
actions 通過 store.dispatch 方法觸發(fā):
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>數(shù)量:{{count}}</view>
<button @click="add">增加</button>
</view>
</template>
<script>
import store from '@/store/index.js';
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
add () {
store.dispatch('addCountAction')
}
}
}
</script>
actions 支持以載荷形式分發(fā):
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 1
},
mutations:{
add(state, payload) {
state.count += payload.amount
}
},
actions:{
addCountAction (context , payload) {
context.commit('add',payload)
}
}
})
export default store
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>數(shù)量:{{count }}</view>
<button @click="add">增加</button>
</view>
</template>
<script>
import store from '@/store/index.js';
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
add () {
// 以載荷形式分發(fā)
store.dispatch('addCountAction', {amount: 10})
}
add () {
// 以對(duì)象形式分發(fā)
store.dispatch({
type: 'addCountAction',
amount: 5
})
}
}
}
</script>
actions的異步:
// 頁面路徑:store/index.js
//調(diào)用mutations的方法來改變數(shù)據(jù)(同步、異步)
actions:{
//異步調(diào)用
actionA({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('add',5)
resolve()
}, 2000)
})
}
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {commit('someOtherMutation')
})
async actionA ({ commit }) {commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
}
}
應(yīng)用Actions屬性方法進(jìn)階(簡(jiǎn)寫):通過 mapActions輔助函數(shù)訪問。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view>
<view>數(shù)量:{{count }}</view>
<button @click="addCountAction">增加</button>
</view>
</template>
<script>
import { mapActions } from 'vuex'
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
...mapActions([
'addCountAction',
// 將 `this.addCountAction()` 映射為 `this.$store.dispatch('addCountAction')`
])
}
}
</script>
6. Module結(jié)構(gòu)。
由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就有可能變得相當(dāng)臃腫。為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:
1.在 store 文件夾下新建 modules 文件夾,并在下面新建 moduleA.js 和 moduleB.js 文件用來存放 vuex 的 modules 模塊。
├── components # 組件文件夾
└── myButton
└── myButton.vue # myButton組件
├── pages
└── index
└── index.vue # index頁面
├── static
├── store
├── index.js # 我們組裝模塊并導(dǎo)出 store 的地方
└── modules # 模塊文件夾
├── moduleA.js # 模塊moduleA
└── moduleB.js # 模塊moduleB
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
2.在 main.js 文件中引入 store。
// 頁面路徑:main.js
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.prototype.$store = store
// 把 store 對(duì)象提供給 “store” 選項(xiàng),這可以把 store 的實(shí)例注入所有的子組件
const app = new Vue({
store,
...App
})
app.$mount()
3.在項(xiàng)目根目錄下,新建 store 文件夾,并在下面新建 index.js 文件,作為模塊入口,引入各子模塊。
// 頁面路徑:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from '@/store/modules/moduleA'
import moduleB from '@/store/modules/moduleB'
Vue.use(Vuex)
export default new Vuex.Store({
modules:{
moduleA,moduleB
}
})
4.子模塊 moduleA 頁面內(nèi)容。
// 子模塊moduleA路徑:store/modules/moduleA.js
export default {
state: {
text:"我是moduleA模塊下state.text的值"
},
getters: {
},
mutations: {
},
actions: {
}
}
5.子模塊 moduleB 頁面內(nèi)容。
// 子模塊moduleB路徑:store/modules/moduleB.js
export default {
state: {
timestamp: 1608820295//初始時(shí)間戳
},
getters: {
timeString(state) {//時(shí)間戳轉(zhuǎn)換后的時(shí)間
var date = new Date(state.timestamp);
var year = date.getFullYear();
var mon = date.getMonth()+1;
var day = date.getDate();
var hours = date.getHours();
var minu = date.getMinutes();
var sec = date.getSeconds();
var trMon = mon<10 ? '0'+mon : mon
var trDay = day<10 ? '0'+day : day
return year+'-'+trMon+'-'+trDay+" "+hours+":"+minu+":"+sec;
}
},
mutations: {
updateTime(state){//更新當(dāng)前時(shí)間戳
state.timestamp = Date.now()
}
},
actions: {
}
}
6.在頁面中引用組件 myButton ,并通過 mapState 讀取 state 中的初始數(shù)據(jù)。
<!-- 頁面路徑:pages/index/index.vue -->
<template>
<view class="content">
<view>{{text}}</view>
<view>時(shí)間戳:{{timestamp}}</view>
<view>當(dāng)前時(shí)間:{{timeString}}</view>
<myButton></myButton>
</view>
</template>
<script>
import {mapState,mapGetters} from 'vuex'
export default {
computed: {
...mapState({
text: state => state.moduleA.text,
timestamp: state => state.moduleB.timestamp
}),
...mapGetters([
'timeString'
])
}
}
</script>
7.在組件 myButton中,通過 mutations 操作刷新當(dāng)前時(shí)間。
<!-- 組件路徑:components/myButton/myButton.vue -->
<template>
<view>
<button type="default" @click="updateTime">刷新當(dāng)前時(shí)間</button>
</view>
</template>
<script>
import {mapMutations} from 'vuex'
export default {
data() {
return {}
},
methods: {
...mapMutations(['updateTime'])
}
}
</script>
總結(jié)
vue是單向數(shù)據(jù)流,子組件不能直接修改父組件的數(shù)據(jù),而通過vuex狀態(tài)管理實(shí)現(xiàn):把組件的共享狀態(tài)抽取出來,以一個(gè)全局單例模式管理。在這種模式下,我們的組件樹構(gòu)成了一個(gè)巨大的“視圖”,不管在樹的哪個(gè)位置,任何組件都能獲取狀態(tài)或者觸發(fā)行為!
vuex的整體結(jié)構(gòu)并不復(fù)雜,知識(shí)規(guī)范比較繁瑣,自己多試幾遍就好了。
到此這篇關(guān)于uniapp中vuex應(yīng)用使用的文章就介紹到這了,更多相關(guān)uniapp中vuex應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于JavaScript實(shí)現(xiàn)圖片點(diǎn)擊彈出窗口而不是保存
這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)圖片點(diǎn)擊彈出窗口而不是保存的相關(guān)資料,需要的朋友可以參考下2016-02-02
js實(shí)現(xiàn)省級(jí)聯(lián)動(dòng)(數(shù)據(jù)結(jié)構(gòu)優(yōu)化)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)省級(jí)聯(lián)動(dòng),數(shù)據(jù)結(jié)構(gòu)優(yōu)化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
javascript解決小數(shù)的加減乘除精度丟失的方案
這篇文章主要介紹了javascript解決小數(shù)的加減乘除精度丟失的方案的相關(guān)資料以及JavaScript中關(guān)于丟失數(shù)字精度的問題的探討,非常的詳細(xì),需要的朋友可以參考下2016-05-05
動(dòng)態(tài)JavaScript所造成一些你不知道的危害
這篇文章給大家整理了動(dòng)態(tài)JavaScript所造成的一些大家可能不知道的危害,文章介紹的很詳細(xì),有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-09-09
JS實(shí)現(xiàn)超簡(jiǎn)單的鼠標(biāo)拖動(dòng)效果
這篇文章主要介紹了JS實(shí)現(xiàn)超簡(jiǎn)單的鼠標(biāo)拖動(dòng)效果,涉及JavaScript響應(yīng)鼠標(biāo)事件動(dòng)態(tài)操作頁面元素的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11

