Nuxt使用Vuex解讀
Nuxt使用vuex
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
基礎(chǔ)知識(shí)這里不再重述,學(xué)習(xí)的話請(qǐng)自行到官網(wǎng)學(xué)習(xí)https://vuex.vuejs.org/zh/
文檔最后有具體使用的實(shí)例,不想看基礎(chǔ)的就直接下調(diào)頁(yè)面~
這里主要簡(jiǎn)單講一講Nuxt里怎么使用vuex,
Nuxt.js 內(nèi)置引用了vuex
模塊,所以不需要額外安裝。
Nuxt.js 會(huì)嘗試找到應(yīng)用根目錄下的store
目錄,如果該目錄存在,它將做以下的事情:
- 引用
vuex
模塊 - 將
vuex
模塊 加到 vendors 構(gòu)建配置中去 - 設(shè)置
Vue
根實(shí)例的store
配置項(xiàng)
Nuxt.js 支持兩種使用store
的方式,你可以擇一使用:
- 普通方式:
store/index.js
返回一個(gè) Vuex.Store 實(shí)例 - 模塊方式:
store
目錄下的每個(gè).js
文件會(huì)被轉(zhuǎn)換成為狀態(tài)樹指定命名的子模塊 (當(dāng)然,index
是根模塊)
普通方式
使用普通方式的狀態(tài)樹,需要添加store/index.js
文件,并對(duì)外暴露一個(gè) Vuex.Store 實(shí)例:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = () => new Vuex.Store({ state: { counter: 0 }, mutations: { increment (state) { state.counter++ } } }) export default store
現(xiàn)在我們可以在組件里面通過this.$store
來使用狀態(tài)樹
<template> <button @click="$store.commit('increment')">{{ $store.state.counter }}</button> </template>
模塊方式
狀態(tài)樹還可以拆分成為模塊,store
目錄下的每個(gè).js
文件會(huì)被轉(zhuǎn)換成為狀態(tài)樹指定命名的子模塊
使用狀態(tài)樹模塊化的方式,store/index.js
不需要返回 Vuex.Store 實(shí)例,而應(yīng)該直接將state
、mutations
和actions
暴露出來:
export const state = () => ({ counter: 0 }) export const mutations = { increment (state) { state.counter++ } }
其他的模塊文件也需要采用類似的方式,如store/todos.js
文件:
export const state = () => ({ list: [] }) export const mutations = { add (state, text) { state.list.push({ text: text, done: false }) }, remove (state, { todo }) { state.list.splice(state.list.indexOf(todo), 1) }, toggle (state, todo) { todo.done = !todo.done } }
在頁(yè)面組件pages/todos.vue
, 可以像下面這樣使用todos
模塊:
<template> <ul> <li v-for="todo in todos"> <input type="checkbox" :checked="todo.done" @change="toggle(todo)"> <span :class="{ done: todo.done }">{{ todo.text }}</span> </li> <li><input placeholder="What needs to be done?" @keyup.enter="addTodo"></li> </ul> </template> <script> import { mapMutations } from 'vuex' export default { computed: { todos () { return this.$store.state.todos.list } }, methods: { addTodo (e) { this.$store.commit('todos/add', e.target.value) e.target.value = '' }, ...mapMutations({ toggle: 'todos/toggle' }) } } </script> <style> .done { text-decoration: line-through; } </style>
模塊方法也適用于頂級(jí)定義,而無需在store
目錄中實(shí)現(xiàn)子目錄
state 示例,您需要?jiǎng)?chuàng)建一個(gè)文件store/state.js
并添加以下內(nèi)容:
export default () => ({ counter: 0 })
并且相應(yīng)的 mutations 在文件store/mutations.js
中:
export default { increment (state) { state.counter++ } }
模塊文件
您可以將模塊文件分解為單獨(dú)的文件:state.js
,actions.js
,mutations.js
和getters.js
。
如果您使用index.js
來維護(hù)state
,getters
,actions
和mutations
,同時(shí)具有單個(gè)單獨(dú)的操作文件,那么仍然可以正確識(shí)別該文件。
項(xiàng)目結(jié)構(gòu)
vuex 并不限制你的代碼結(jié)構(gòu)。但是,它規(guī)定了一些需要遵守的規(guī)則:
- 應(yīng)用層級(jí)的狀態(tài)應(yīng)該集中到單個(gè) store 對(duì)象中。
- 提交 mutation 是更改狀態(tài)的唯一方法,并且這個(gè)過程是同步的。
- 異步邏輯都應(yīng)該封裝到 action 里面。
只要你遵守以上規(guī)則,如何組織代碼隨你便。如果你的 store 文件太大,只需將 action、mutation 和 getter 分割到單獨(dú)的文件。
對(duì)于大型應(yīng)用,我們會(huì)希望把 Vuex 相關(guān)代碼分割到模塊中。
下面是項(xiàng)目結(jié)構(gòu)示例
├── index.html ├── main.js ├── api │ └── ... # 抽取出API請(qǐng)求 ├── components │ ├── App.vue │ └── ... └── store ├── index.js # 我們組裝模塊并導(dǎo)出 store 的地方 ├── actions.js # 根級(jí)別的 action ├── mutations.js # 根級(jí)別的 mutation └── modules ├── cart.js # 購(gòu)物車模塊 └── products.js # 產(chǎn)品模塊
下面用是實(shí)例說一下怎么使用
一、在Nuxt項(xiàng)目的store目錄下新建一個(gè)index.js文件
這樣項(xiàng)目就啟用了vuex
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = () => new Vuex.Store({ state: { counter: 0 }, mutations: { increment (state) { state.counter++ } } }) export default store
一般這個(gè)文件我們只作為vuex的入口文件,不在這里面寫業(yè)務(wù)代碼,其他的功能寫在其他的vuex文件中,在index中導(dǎo)入一下即可
二、在store文件夾里再新建一個(gè)filter.js文件
在index.js中引入一下,這個(gè)文件來寫我們的業(yè)務(wù)代碼
filter.js文件
const state = ({ value: 'Hello World', list: [1, 2, 3, 4, 5] }); const getters = { include: (state) => (val) => { return state.list.indexOf(val) > -1; } } ; const mutations = { SET_VALUE(state, value) { state.value = value; } }; const actions = { async getInfo({state, commit}, val) { commit('SET_VALUE', val); } }; export default { namespaced: true, state, getters, actions, mutations };
這個(gè)文件中輸出時(shí)候的namespaced屬性,如果為true時(shí),使用這個(gè)文件的方法時(shí),需要標(biāo)注namespace,不寫或?yàn)閒alse時(shí),則可以直接使用,這里建議使用namespaced,因?yàn)榇笮晚?xiàng)目可能有很多復(fù)雜的業(yè)務(wù),可能命名沖突,使用namespaced可以把方法區(qū)分開,避免很多問題
index.js文件
import Vue from 'vue'; import Vuex from 'vuex'; import filter from './filter'; Vue.use(Vuex); const store = () => new Vuex.Store({ state: { }, mutations: { }, modules: { filter } }); export default store
在index.js文件中import一下我們的filter.js文件,然后在modules中引入即可使用
三、在vue文件中使用vuex
index.vue
<template> <section class="p-10"> <h1> {{ value }} </h1> <h1> {{ result }} </h1> <el-button type="danger" @click="change">點(diǎn)擊</el-button> </section> </template> <script> import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'; export default { data() { return { result: false }; }, computed: { ...mapGetters('filter', [ 'include' ]), ...mapState({ value: state => state.filter.value }) }, methods: { ...mapMutations('filter', [ 'SET_VALUE' ]), ...mapActions('filter', [ 'getInfo' ]), change() { // this.result = this.include(1); // this.getInfo('你好'); // this.SET_VALUE('HELLO'); } }, mounted() { }, beforeDestroy() { } }; </script>
1.在vue文件中,首先通過import { mapState, mapMutations, mapActions, mapGetters } from 'vuex' 來引入我們需要的模塊,按需引用,只需要引入本頁(yè)面用到的模塊即可
2.mapGetters和mapState需要在頁(yè)面的計(jì)算屬性computed中引入,mapMutations和mapActions需要在methods中引入,此時(shí)要注意模塊的命名空間,如果vuex文件導(dǎo)出時(shí)標(biāo)注了namespaced,我們使用時(shí)也需要寫出才可以找到,反之則不需要
3.首先是mapState,使用mapState時(shí),我有兩種方法來取,兩種方式都可以,這個(gè)方法是從store中取出這個(gè)變量,然后顯示在此頁(yè)面上,store變動(dòng)的話,此頁(yè)面也會(huì)跟著動(dòng)態(tài)改變
...mapState({ value: state => state.filter.value })
...mapState('filter', { value: state => state.value })
4.mapGetters類似于store的計(jì)算屬性,我們可以通過mapGetters的方法在store里進(jìn)行計(jì)算,然后返回我們需要的結(jié)果即可
上面例子就是點(diǎn)擊按鈕的時(shí)候傳了一個(gè)數(shù)字到store里,然后判斷store里的list是否包含這個(gè)數(shù)字,然后返回結(jié)果到頁(yè)面,頁(yè)面根據(jù)返回值重新刷新數(shù)據(jù)
5.MapMutation是更改store中狀態(tài)的唯一方法,Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的事件類型 (type)和 一個(gè)回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù)
上面的例子是點(diǎn)擊按鈕時(shí),直接通過mutation 的方法修改了store里的數(shù)據(jù),然后把數(shù)據(jù)同步到頁(yè)面
6.mapAction類似于mutation, 但是Action提交的是mutation,而不是直接變更狀態(tài),Action可以包含任意異步操作,我們一般把異步獲取數(shù)據(jù)的方法都放在這里,然后在回調(diào)函數(shù)里使用mutation里的方法把異步獲取的數(shù)據(jù)保存在store里,然后把store里的數(shù)據(jù)傳到頁(yè)面
上面的例子是點(diǎn)擊按鈕時(shí)調(diào)用了action里的異步方法,然后在方法的回調(diào)函數(shù)里修改了store的數(shù)據(jù),一般這里是把請(qǐng)求的結(jié)果進(jìn)行保存,這里是省略了請(qǐng)求API方法
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue項(xiàng)目結(jié)構(gòu)目錄超詳細(xì)介紹
這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目結(jié)構(gòu)目錄超詳細(xì)介紹的相關(guān)資料,Vue項(xiàng)目目錄結(jié)構(gòu)是指在開發(fā)Vue項(xiàng)目時(shí),為了更好地組織和管理代碼,將不同的文件按照一定的規(guī)則和層次結(jié)構(gòu)進(jìn)行分類和存放的方式,需要的朋友可以參考下2023-12-12vue 綁定對(duì)象,數(shù)組之?dāng)?shù)據(jù)無法動(dòng)態(tài)渲染案例詳解
這篇文章主要介紹了vue 綁定對(duì)象,數(shù)組之?dāng)?shù)據(jù)無法動(dòng)態(tài)渲染案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09Vue——解決報(bào)錯(cuò) Computed property "****" was assigned to but it ha
這篇文章主要介紹了Vue——解決報(bào)錯(cuò) Computed property "****" was assigned to but it has no setter.的方法,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12vue3和vue2掛載實(shí)例到全局(自定義消息提示框組件方式)
這篇文章主要介紹了vue3和vue2掛載實(shí)例到全局(自定義消息提示框組件方式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04vant中的Cascader級(jí)聯(lián)選擇異步加載地區(qū)數(shù)據(jù)方式
這篇文章主要介紹了vant中的Cascader級(jí)聯(lián)選擇異步加載地區(qū)數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07vue使用keep-alive實(shí)現(xiàn)組件切換時(shí)保存原組件數(shù)據(jù)方法
這篇文章主要介紹了vue使用keep-alive實(shí)現(xiàn)組件切換時(shí)保存原組件數(shù)據(jù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10