vuex

vuex 基本使用

1. 安裝 vuex

npm i vuex 

2. 在vue項目下的src目錄下創(chuàng)建一個 store 目錄,并在里面創(chuàng)建一個 index.js 文件

image-20200530220930581.png

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)提供兩種方式展示
    1. 直接在模板寫 $store.state.***
    2. 先引入 mapState 并在計算屬性當(dāng)中寫上 ...mapState([ 'count', 'myname’ ])
    3. 單引號里面寫的是 你要展示的數(shù)據(jù) 可以通過 逗號隔開 寫上多個
    4. 之后可以在模板當(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 里面的方法 有兩種方式

    1. this.$store.commit('increment',{num:1});// 提交到倉庫中的 increment 里面進(jìn)行數(shù)據(jù)修改, {num:1} 作為參數(shù)傳入進(jìn)去

    2. 第二種通過 mapMutations 不同與 mapState 和 mapGetters 這兩種是在計算屬性中書寫出來, mapMutations 必須寫在方法當(dāng)中 也就是 methods 里面比如

    3. ...... 
      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 里面的方法 有兩種方式

    1. this.$store.dispatch('handleLogin')
      
    2. 也可以通過 引入 mapActions

    3. 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('登錄');
          }
          */
      
      ......
      
  1. // 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜜托,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嫂沉,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蓬抄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)夯到,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門嚷缭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耍贾,你說我怎么就攤上這事阅爽。” “怎么了荐开?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵优床,是天一觀的道長。 經(jīng)常有香客問我誓焦,道長胆敞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任杂伟,我火速辦了婚禮移层,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赫粥。我一直安慰自己观话,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布越平。 她就那樣靜靜地躺著频蛔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秦叛。 梳的紋絲不亂的頭發(fā)上晦溪,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機(jī)與錄音挣跋,去河邊找鬼三圆。 笑死,一個胖子當(dāng)著我的面吹牛避咆,可吹牛的內(nèi)容都是我干的舟肉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼查库,長吁一口氣:“原來是場噩夢啊……” “哼路媚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起樊销,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤整慎,失蹤者是張志新(化名)和其女友劉穎适荣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體院领,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年够吩,在試婚紗的時候發(fā)現(xiàn)自己被綠了比然。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡周循,死狀恐怖强法,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情湾笛,我是刑警寧澤饮怯,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站嚎研,受9級特大地震影響蓖墅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜临扮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一论矾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杆勇,春花似錦贪壳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至钻注,卻和暖如春蚂且,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背幅恋。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工膘掰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佳遣。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓识埋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親零渐。 傳聞我的和親對象是個殘疾皇子窒舟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355