vuex 基本使用
1. 安裝 vuex
npm i vuex
2. 在vue項目下的src目錄下創(chuàng)建一個 store 目錄,并在里面創(chuàng)建一個 index.js 文件
3. 在 index.js 中 書寫關(guān)于倉庫的代碼
// index.js
// 引入 vue
import Vue from 'vue';
//引入 vuex
import Vuex from 'vuex'
// 1. 安裝插件 在 vue 中使用Vue
Vue.use(Vuex);
// 2. 創(chuàng)建對象
const store = new Vuex.Store({
state: {
myname: '',
count: 100,
list: [{
name: "ming",
score: 40
},
{
name: "gang",
score: 50
},
{
name: "lan",
score: 60
},
{
name: "mei",
score: 70
},
{
name: "tian",
score: 80
},
{
name: "bai",
score: 90
},
],
},
mutations: {
// 方法
// 這里通過是通過 action 里面的 asyncSaveName 方法觸發(fā)的次方法
// 因?yàn)?action 里面的方法不能修改 state 里面的數(shù)據(jù),只能通過 mutations 里面的方
// 法來修改.
saveName(state,n){
// console.log('從action 傳過來的數(shù)據(jù)', n, state);
// 通過
state.myname = n.username;
},
increment() {
// console.log(arguments);
this.state.count++;
},
decrement() {
this.state.count--;
},
add(state,n){
state.stus.push(n);
},
},
//相當(dāng)于vue的 computed 計算屬性
getters: {
// 這里是吧上面的 list 數(shù)組當(dāng)中成績小于60分的數(shù)據(jù)過濾出來
faileNum(state){
return (function(){
// console.log(arguments);
return state.list.filter(item => item.score < 60)
})();
}
},
actions: {
//在組件當(dāng)中調(diào)用登錄接口,如果登錄成功那么觸發(fā)這個方法,把用戶名保存到state當(dāng)中
// 的 myname
asyncSaveName(context,n){
// console.log('登錄成功action被調(diào)用', context,n);
//這里面不能直接修改 state 中的數(shù)據(jù) 需要提交 mutations 在 mutations 當(dāng)中的方法
// 修改 saveName 為 mutations 里面的方法
context.commit('saveName',n)
}
},
modules: {},
})
// 3. 導(dǎo)出store對象
export default store;
// index.js
// store 里面包含 5個模塊
const store = new Vuex.Store({
// state 存放數(shù)據(jù)的地方
state:{},
//相當(dāng)于vue的 computed 計算屬性
getters:{},
// 如果要修改倉庫里面的數(shù)據(jù) 也就是修改 state 里面的數(shù)據(jù)需要提交 mutations 來修改
// 并且 mutations 里面不能有異步操作
mutations:{],
//actions 是做異步操作的地方 發(fā)送請求之類的異步操作都要在 actions 里面做
// 并且在 actions 里面 也必須提交 mutations
actions:{},
// 如果項目非常大,所有組件數(shù)據(jù)放到一起管理,非常不方便,并且容易混淆
// 通過 modules 把倉庫分成 多個模塊 不同組件的值,保證到不同模塊當(dāng)中
// 在把模塊注入到根倉庫中 方便管理
modules:{}
})
4. 在頁面中展示 vuex 里面的數(shù)據(jù)
- 目前倉庫有以下數(shù)據(jù)
state: {
myname: '',
count: 100,
list: [{
name: "ming",
- 現(xiàn)在把 state 里面的 count 展示到頁面上
- vue 官網(wǎng)提供兩種方式展示
- 直接在模板寫 $store.state.***
- 先引入 mapState 并在計算屬性當(dāng)中寫上 ...mapState([ 'count', 'myname’ ])
- 單引號里面寫的是 你要展示的數(shù)據(jù) 可以通過 逗號隔開 寫上多個
- 之后可以在模板當(dāng)中直接 寫 count 就能展示數(shù)據(jù)了
// store.vue
<template>
<div>
<h1>{{name}}</h1>
<div>
<!-- <button @click="add" >+</button> -->
<p> 使用 $store.state.count 展示數(shù)據(jù) {{$store.state.count}}</p> <!--100-->
<p> 使用...mapState(['count'])展示數(shù)據(jù) {{count}}</p> <!--100-->
<!-- <button @click="sub" >+</button> -->
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data() {
return {
name:'Store'
}
},
computed: {
...mapState(['count'])
},
methods: {
add(){
this.$store.commit('increment');
}
},
}
</script>
5. 下面介紹 state, getters, mutations, actions 在頁面中的一些用法
5.1 state 上面已經(jīng)說過就不記錄了
5.2 getters
getters相當(dāng)于vue 里面的計算屬性 computed.
比如我們往倉庫中存放了一個 學(xué)生成績對象數(shù)據(jù)如:
const store = new Vuex.Store({ ...... state:{ ...... list: [{name:'小米',score:50 }, {name:'小明 ',score:70 }, {name:'小王 ',score:60 }, {name:'小李 ',score:90 } ] ...... })
現(xiàn)在 頁面上要展示 倉庫數(shù)據(jù)中 學(xué)生成績小于60分的數(shù)據(jù) 我們可以這樣寫
const store = new Vuex.Store({ ...... getters: {//返回成績低于60的數(shù)據(jù) filterScore(state){ return state.list.filter( item => item.score < 60 ) } }, ...... })
在頁面當(dāng)中展示
引入 mapGetters 可以使我們少寫代碼 import {mapState ,mapGetters} from 'vuex';
在計算屬性中寫 ...mapGetters(['filterScore']) 中括號寫 要展示到 模板上的 數(shù)據(jù)
// store.vue <template> <div> <h1>{{name}}</h1> <div> <!-- <button @click="add" >+</button> --> <p> 使用 $store.state.count 展示數(shù)據(jù) {{$store.state.count}}</p> <p> 使用...mapState(['count'])展示數(shù)據(jù) {{count}}</p> <!-- --> <!-- <button @click="sub" >+</button> --> <hr> <p> getters: </p> <p>在計算屬性中使用...mapGetters(['filterScore'])展示:</p> <p> {{filterScore}} </p> <p> 直接通過$store.getters.getters展示: </p> <p>{{$store.getters.filterScore}}</p> </div> </div> </template> <script> import {mapState ,mapGetters} from 'vuex'; import { log } from 'util' export default { data() { return { name:'Store' } }, created(){ console.log(this.$store); }, computed: { ...mapState(['count']), ...mapGetters(['filterScore']) }, methods: { add(){ this.$store.commit('increment'); } }, } </script>
5.3 mutations 不能做異步操作
mutations 是修改倉庫數(shù)據(jù)的地方 在里面定義方法 通過觸發(fā)里面的方法來修改倉庫數(shù)據(jù)
倉庫里面有 count:100 的數(shù)據(jù),現(xiàn)在我們做一個簡單的計數(shù)器
首先在 mutations 里面寫好要操作的方法
const store = new Vuex.Store({ ...... state:{ ...... count:100, ...... }, mutations:{ // 定義加法方法 方法里面可以接受2個參數(shù)(state,options) // options 通常作為一個對象傳入進(jìn)此方法 // state 為當(dāng)前倉庫數(shù)據(jù) // { num } 是es6結(jié)構(gòu)寫法 傳過來的對象中包含 num ,那么可以用此方法結(jié)構(gòu)出來 increment(state,{num}) { state.count += num; }, decrement(state, {num}) { state.count += num; }, } ...... })
在模板中使用出來
定義兩個 方法 sub(), add(),
改變倉庫中的數(shù)據(jù)就是提交 mutations
-
觸發(fā) mutations 里面的方法 有兩種方式
this.$store.commit('increment',{num:1});// 提交到倉庫中的 increment 里面進(jìn)行數(shù)據(jù)修改, {num:1} 作為參數(shù)傳入進(jìn)去
第二種通過 mapMutations 不同與 mapState 和 mapGetters 這兩種是在計算屬性中書寫出來, mapMutations 必須寫在方法當(dāng)中 也就是 methods 里面比如
...... methods: { // 這樣寫好之后可以直接在 模板中使用 //比如 @cliick='increment({num:1})' /* <button @click="sub" >-</button> {{count}} <button @click="increment({num:1})" >+</button> */ // 也可以在方法當(dāng)中使用 /* add(){ // this.increment({num:123}) }, */ ...mapMutations(['increment']), add(){ // this.increment({num:123}) }, ......
//store.vue <template> <div> <h1>{{name}}</h1> <div> <!-- <button @click="add" >+</button> --> <p> 使用 $store.state.count 展示數(shù)據(jù) {{$store.state.count}}</p> <p> 使用...mapState(['count'])展示數(shù)據(jù) {{count}}</p> <!-- --> <!-- <button @click="sub" >+</button> --> <hr> <p> getters: </p> <p>在計算屬性中使用...mapGetters(['filterScore'])展示:</p> <p> {{filterScore}} </p> <p> 直接通過$store.getters.getters展示: </p> <p>{{$store.getters.filterScore}}</p> <hr> <p>mutations </p> <button @click="sub" >-</button> {{count}} <button @click="add" >+</button> <!-- <button @click="increment({num:1})" >+</button> --> </div> </div> </template> <script> import {mapState ,mapGetters,mapMutations} from 'vuex'; import { log } from 'util' export default { data() { return { name:'Store' } }, created(){ console.log(this.$store); }, computed: { ...mapState(['count']), ...mapGetters(['filterScore']) }, methods: { ...mapMutations(['increment']), add(){ // this.increment({num:123}) this.$store.commit('increment',{num:1}); }, sub(){ this.$store.commit('decrement',{num:-1}); } }, } </script>
5.4 action 可以做異步
在倉庫中書寫 action 代碼
我們通過 發(fā)送一個登錄請求來改變 testname 的名字
// index.js ...... // 因?yàn)橐l(fā)送請求,所以倉庫中引入 axios import axios from '../utils/axios' const store = new Vuex.Store({ ...... state:{ ...... testname:'測試名字', ...... }, mutations:{ // actions 里面提交并觸發(fā)此方法 修改倉庫數(shù)據(jù) changeName(state, {user}) { state.testname = user; } }, actions:{ async handleLogin({commit},{user,pwd}){ let url = '/login'; let a1 = await axios.post(url,{username:user,password:pwd}); // a1.status === 'ok' 表示登錄成功 可以修改用戶名 if (a1.status === 'ok'){ // 我們把倉庫中的 testname 改成用戶登錄的用戶名 // actin 里面可以做異步操作,但是不能直接修改倉庫數(shù)據(jù) // 必須提交到 mutations 里面去修改 commit('changeName',{user}); } } } ...... })
-
觸發(fā) action 里面的方法 有兩種方式
this.$store.dispatch('handleLogin')
也可以通過 引入 mapActions
import {mapActions} from 'vuex'; ...... methods: { ...mapActions(['handleLogin']), // 這樣寫好之后可以直接在 模板中使用 //比如 @click="handleLogin({user,pwd})" /* <button @click="handleLogin({user,pwd})" > 登錄 </button> */ // 也可以在方法當(dāng)中使用 /* <!-- <button @click="login" > 登錄 </button> --> login(){ this.$store.dispatch('handleLogin', {user:this.user,pwd:this.pwd}); console.log('登錄'); } */ ......
// store.vue <template> <div> <h1>{{name}}</h1> <div> <!-- <button @click="add" >+</button> --> <p> 使用 $store.state.count 展示數(shù)據(jù) {{$store.state.count}}</p> <p> 使用...mapState(['count'])展示數(shù)據(jù) {{count}}</p> <!-- --> <!-- <button @click="sub" >+</button> --> <hr> <p> getters: </p> <p>在計算屬性中使用...mapGetters(['filterScore'])展示:</p> <p> {{filterScore}} </p> <p> 直接通過$store.getters.getters展示: </p> <p>{{$store.getters.filterScore}}</p> <hr> <p>mutations </p> <button @click="sub" >-</button> {{count}} <button @click="add" >+</button> <!-- <button @click="increment({num:1})" >+</button> --> <hr> <p>mapActions</p> <p> 名字:{{testname}} </p> <input type="text" v-model="user" placeholder="輸入用戶名" > <br><br> <input type="password" v-model="pwd" placeholder="輸入密碼" > <br><br> <button @click="handleLogin({user,pwd})" > 登錄 </button> <!-- <button @click="login" > 登錄 </button> --> </div> </div> </template> <script> import {mapState ,mapGetters,mapMutations,mapActions} from 'vuex'; import { log } from 'util' export default { data() { return { name:'Store', user:'', pwd:'' } }, created(){ // console.log(this.$store); }, computed: { ...mapState(['count','testname']), ...mapGetters(['filterScore']) }, methods: { ...mapMutations(['increment']), ...mapActions(['handleLogin']), add(){ // this.increment({num:123}) this.$store.commit('increment',{num:1}); }, sub(){ this.$store.commit('decrement',{num:-1}); }, login(){ this.$store.dispatch('handleLogin',{user:this.user,pwd:this.pwd}) console.log('登錄'); } }, } </script>
官網(wǎng)說明
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')` // `mapActions` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 將 `this.add()` 映射為 `this.$store.dispatch('increment')` }) } }
gitee 項目地址 : git clone https://gitee.com/lil-kz/vuecli4.git