Vuex

1.Vuex概述

2.Vuex基本使用

3.使用Vuex完成todo案例

1.Vuex概述

Vuex是實現(xiàn)組件全局狀態(tài)(數(shù)據(jù))管理的一種機制,可以方便的實現(xiàn)組件之間的數(shù)據(jù)共享

使用Vuex管理數(shù)據(jù)的好處:
A.能夠在vuex中集中管理共享的數(shù)據(jù),便于開發(fā)和后期進行維護
B.能夠高效的實現(xiàn)組件之間的數(shù)據(jù)共享,提高開發(fā)效率
C.存儲在vuex中的數(shù)據(jù)是響應式的,當數(shù)據(jù)發(fā)生改變時,頁面中的數(shù)據(jù)也會同步更新

2.Vuex的基本使用

創(chuàng)建帶有vuex的vue項目,打開終端,輸入命令:vue ui
當項目儀表盤打開之后,我們點擊頁面左上角的項目管理下拉列表,再點擊Vue項目管理器
點擊創(chuàng)建項目,如下圖所示
第一步,設置項目名稱和包管理器



第二步,設置手動配置項目


第三步,設置功能項




第四步,創(chuàng)建項目


3.使用Vuex完成計數(shù)器案例

打開剛剛創(chuàng)建的vuex項目,找到src目錄中的App.vue組件,將代碼重新編寫如下:

<template>
  <div>
    <my-addition></my-addition>

    <p>----------------------------------------</p>

    <my-subtraction></my-subtraction>
  </div>
</template>

<script>
import Addition from './components/Addition.vue'
import Subtraction from './components/Subtraction.vue'

export default {
  data() {
    return {}
  },
  components: {
    'my-subtraction': Subtraction,
    'my-addition': Addition
  }
}
</script>

<style>
</style>

在components文件夾中創(chuàng)建Addition.vue組件,代碼如下:

<template>
    <div>
        <h3>當前最新的count值為:</h3>
        <button>+1</button>
    </div>
</template>

<script>
export default {
  data() {
    return {}
  }
}
</script>

<style>
</style>

在components文件夾中創(chuàng)建Subtraction.vue組件,代碼如下:

<template>
    <div>
        <h3>當前最新的count值為:</h3>
        <button>-1</button>
    </div>
</template>

<script>
export default {
  data() {
    return {}
  }
}
</script>

<style>
</style>

最后在項目根目錄(與src平級)中創(chuàng)建 .prettierrc 文件,編寫代碼如下:

{
    "semi":false,
    "singleQuote":true
}

4.Vuex中的核心特性

A.State

State提供唯一的公共數(shù)據(jù)源,所有共享的數(shù)據(jù)都要統(tǒng)一放到Store中的State中存儲
例如,打開項目中的store.js文件,在State對象中可以添加我們要共享的數(shù)據(jù),如:count:0

在組件中訪問State的方式:
1).this.$store.state.全局數(shù)據(jù)名稱  如:this.$store.state.count
2).先按需導入mapState函數(shù): import { mapState } from 'vuex'
然后數(shù)據(jù)映射為計算屬性: computed:{ ...mapState(['全局數(shù)據(jù)名稱']) }

B.Mutation

Mutation用于修改變更$store中的數(shù)據(jù)
使用方式:
打開store.js文件,在mutations中添加代碼如下

mutations: {
    add(state,step){
      //第一個形參永遠都是state也就是$state對象
      //第二個形參是調(diào)用add時傳遞的參數(shù)
      state.count+=step;
    }
  }

然后在Addition.vue中給按鈕添加事件代碼如下:

<button @click="Add">+1</button>

methods:{
  Add(){
    //使用commit函數(shù)調(diào)用mutations中的對應函數(shù),
    //第一個參數(shù)就是我們要調(diào)用的mutations中的函數(shù)名
    //第二個參數(shù)就是傳遞給add函數(shù)的參數(shù)
    this.$store.commit('add',10)
  }
}

使用mutations的第二種方式:
import { mapMutations } from 'vuex'

methods:{
...mapMutations(['add'])
}
如下:

import { mapState,mapMutations } from 'vuex'

export default {
  data() {
    return {}
  },
  methods:{
      //獲得mapMutations映射的sub函數(shù)
      ...mapMutations(['sub']),
      //當點擊按鈕時觸發(fā)Sub函數(shù)
      Sub(){
          //調(diào)用sub函數(shù)完成對數(shù)據(jù)的操作
          this.sub(10);
      }
  },
  computed:{
      ...mapState(['count'])
      
  }
}

C.Action

在mutations中不能編寫異步的代碼,會導致vue調(diào)試器的顯示出錯。
在vuex中我們可以使用Action來執(zhí)行異步操作。
操作步驟如下:
打開store.js文件,修改Action,如下:

actions: {
  addAsync(context,step){
    setTimeout(()=>{
      context.commit('add',step);
    },2000)
  }
}

然后在Addition.vue中給按鈕添加事件代碼如下:

<button @click="AddAsync">...+1</button>

methods:{
  AddAsync(){
    this.$store.dispatch('addAsync',5)
  }
}

第二種方式:
import { mapActions } from 'vuex'

methods:{
...mapMutations(['subAsync'])
}
如下:

import { mapState,mapMutations,mapActions } from 'vuex'

export default {
  data() {
    return {}
  },
  methods:{
      //獲得mapMutations映射的sub函數(shù)
      ...mapMutations(['sub']),
      //當點擊按鈕時觸發(fā)Sub函數(shù)
      Sub(){
          //調(diào)用sub函數(shù)完成對數(shù)據(jù)的操作
          this.sub(10);
      },
      //獲得mapActions映射的addAsync函數(shù)
      ...mapActions(['subAsync']),
      asyncSub(){
          this.subAsync(5);
      }
  },
  computed:{
      ...mapState(['count'])
      
  }
}

D.Getter

Getter用于對Store中的數(shù)據(jù)進行加工處理形成新的數(shù)據(jù)
它只會包裝Store中保存的數(shù)據(jù),并不會修改Store中保存的數(shù)據(jù),當Store中的數(shù)據(jù)發(fā)生變化時,Getter生成的內(nèi)容也會隨之變化
打開store.js文件,添加getters,如下:

export default new Vuex.Store({
  .......
  getters:{
    //添加了一個showNum的屬性
    showNum : state =>{
      return '最新的count值為:'+state.count;
    }
  }
})

然后打開Addition.vue中,添加插值表達式使用getters
<h3>{{$store.getters.showNum}}</h3>

或者也可以在Addition.vue中,導入mapGetters,并將之映射為計算屬性
import { mapGetters } from 'vuex'
computed:{
...mapGetters(['showNum'])
}

5.vuex案例

A.初始化案例

首先使用vue ui初始化一個使用vuex的案例
然后打開public文件夾,創(chuàng)建一個list.json文件,文件代碼如下:

[
    {
        "id": 0,
        "info": "Racing car sprays burning fuel into crowd.",
        "done": false
    },
    {
        "id": 1,
        "info": "Japanese princess to wed commoner.",
        "done": false
    },
    {
        "id": 2,
        "info": "Australian walks 100km after outback crash.",
        "done": false
    },
    {
        "id": 3,
        "info": "Man charged over missing wedding girl.",
        "done": false
    },
    {
        "id": 4,
        "info": "Los Angeles battles huge wildfires.",
        "done": false
    }
]

再接著,打開main.js,添加store.js的引入,如下:

import Vue from 'vue'
import App from './App.vue'
import store from './store.js'

// 1. 導入 ant-design-vue 組件庫
import Antd from 'ant-design-vue'
// 2. 導入組件庫的樣式表
import 'ant-design-vue/dist/antd.css'

Vue.config.productionTip = false
// 3. 安裝組件庫
Vue.use(Antd)

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

再接著打開store.js,添加axios請求json文件獲取數(shù)據(jù)的代碼,如下:

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //所有任務列表
    list: [],
    //文本輸入框中的值
    inputValue: 'AAA'
  },
  mutations: {
    initList(state, list) {
      state.list = list
    },
    setInputValue(state,value){
      state.inputValue = value
    }
  },
  actions: {
    getList(context) {
      axios.get('/list.json').then(({ data }) => {
        console.log(data);
        context.commit('initList', data)
      })
    }
  }
})

最后,代開App.vue文件,將store中的數(shù)據(jù)獲取并展示:

<template>
  <div id="app">
    <a-input placeholder="請輸入任務" class="my_ipt" :value="inputValue" @change="handleInputChange" />
    <a-button type="primary">添加事項</a-button>

    <a-list bordered :dataSource="list" class="dt_list">
      <a-list-item slot="renderItem" slot-scope="item">
        <!-- 復選框 -->
        <a-checkbox :checked="item.done">{{item.info}}</a-checkbox>
        <!-- 刪除鏈接 -->
        <a slot="actions">刪除</a>
      </a-list-item>

      <!-- footer區(qū)域 -->
      <div slot="footer" class="footer">
        <!-- 未完成的任務個數(shù) -->
        <span>0條剩余</span>
        <!-- 操作按鈕 -->
        <a-button-group>
          <a-button type="primary">全部</a-button>
          <a-button>未完成</a-button>
          <a-button>已完成</a-button>
        </a-button-group>
        <!-- 把已經(jīng)完成的任務清空 -->
        <a>清除已完成</a>
      </div>
    </a-list>
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
  name: 'app',
  data() {
    return {
      // list:[]
    }
  },
  created(){
    // console.log(this.$store);
    this.$store.dispatch('getList')
  },
  methods:{
    handleInputChange(e){
      // console.log(e.target.value)
      this.$store.commit('setInputValue',e.target.value)
    }
  },
  computed:{
    ...mapState(['list','inputValue'])
  }
}
</script>

<style scoped>
#app {
  padding: 10px;
}

.my_ipt {
  width: 500px;
  margin-right: 10px;
}

.dt_list {
  width: 500px;
  margin-top: 10px;
}

.footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>

B.完成添加事項

首先,打開App.vue文件,給“添加事項”按鈕綁定點擊事件,編寫處理函數(shù)

//綁定事件
<a-button type="primary" @click="addItemToList">添加事項</a-button>

//編寫事件處理函數(shù)
methods:{
    ......
    addItemToList(){
      //向列表中新增事項
      if(this.inputValue.trim().length <= 0){
        return this.$message.warning('文本框內(nèi)容不能為空')
      }

      this.$store.commit('addItem')
    }
  }

然后打開store.js編寫addItem

export default new Vuex.Store({
  state: {
    //所有任務列表
    list: [],
    //文本輸入框中的值
    inputValue: 'AAA',
    //下一個id
    nextId:5
  },
  mutations: {
    ........
    //添加列表項
    addItem(state){
      const obj = {
        id :state.nextId,
        info: state.inputValue.trim(),
        done:false
      }
      //將創(chuàng)建好的事項添加到數(shù)組list中
      state.list.push(obj)
      //將nextId值自增
      state.nextId++
      state.inputValue = ''
    }
  }
  ......
})

C.完成刪除事項

首先,打開App.vue文件,給“刪除”按鈕綁定點擊事件,編寫處理函數(shù)

//綁定事件
<a slot="actions" @click="removeItemById(item.id)">刪除</a>

//編寫事件處理函數(shù)
methods:{
    ......
    removeItemById(id){
      //根據(jù)id刪除事項
      this.$store.commit('removeItem',id)
    }
  }

然后打開store.js編寫addItem

export default new Vuex.Store({
  ......
  mutations: {
    ........
    removeItem(state,id){
      //根據(jù)id刪除事項數(shù)據(jù)
      const index = state.list.findIndex( x => x.id === id )
      // console.log(index);
      if(index != -1) state.list.splice(index,1);
    }
  }
  ......
})

D.完成選中狀態(tài)的改變

首先,打開App.vue文件,給“復選”按鈕綁定點擊事件,編寫處理函數(shù)

//綁定事件
<a-checkbox :checked="item.done" @change="cbStateChanged(item.id,$event)">{{item.info}}</a-checkbox>

//編寫事件處理函數(shù)
methods:{
    ......
    cbStateChanged(id,e){
      //復選框狀態(tài)改變時觸發(fā)
      const param = {
        id:id,
        status:e.target.checked
      }

      //根據(jù)id更改事項狀態(tài)
      this.$store.commit('changeStatus',param)
    }
  }

然后打開store.js編寫addItem

export default new Vuex.Store({
  ......
  mutations: {
    ........
    changeStatus(state,param){
      //根據(jù)id改變對應事項的狀態(tài)
      const index = state.list.findIndex( x => x.id === param.id )
      if(index != -1) state.list[index].done = param.status
    }
  }
  ......
})

E.剩余項統(tǒng)計

打開store.js,添加getters完成剩余項統(tǒng)計

getters:{
  unDoneLength(state){
    const temp = state.list.filter( x => x.done === false )
    console.log(temp)
    return temp.length
  }
}

打開App.vue,使用getters展示剩余項

//使用映射好的計算屬性展示剩余項
<!-- 未完成的任務個數(shù) -->
<span>{{unDoneLength}}條剩余</span>

//導入getters
import { mapState,mapGetters } from 'vuex'
//映射
computed:{
  ...mapState(['list','inputValue']),
  ...mapGetters(['unDoneLength'])
}

F.清除完成事項

首先,打開App.vue文件,給“清除已完成”按鈕綁定點擊事件,編寫處理函數(shù)

<!-- 把已經(jīng)完成的任務清空 -->
<a @click="clean">清除已完成</a>

//編寫事件處理函數(shù)
methods:{
  ......
  clean(){
    //清除已經(jīng)完成的事項
    this.$store.commit('cleanDone')
  }
}

然后打開store.js編寫addItem

export default new Vuex.Store({
  ......
  mutations: {
    ........
    cleanDone(state){
      state.list = state.list.filter( x => x.done === false )
    }
  }
  ......
})

G.點擊選項卡切換事項

打開App.vue,給“全部”,“未完成”,“已完成”三個選項卡綁定點擊事件,編寫處理函數(shù)
并將列表數(shù)據(jù)來源更改為一個getters。

<a-list bordered :dataSource="infoList" class="dt_list">
  ......
  <!-- 操作按鈕 -->
  <a-button-group>
    <a-button :type="viewKey ==='all'?'primary':'default'" @click="changeList('all')">全部</a-button>
    <a-button :type="viewKey ==='undone'?'primary':'default'" @click="changeList('undone')">未完成</a-button>
    <a-button :type="viewKey ==='done'?'primary':'default'" @click="changeList('done')">已完成</a-button>
  </a-button-group>
  ......
</a-list>

//編寫事件處理函數(shù)以及映射計算屬性
methods:{
  ......
  changeList( key ){
    //點擊“全部”,“已完成”,“未完成”時觸發(fā)
    this.$store.commit('changeKey',key)
  }
},
computed:{
  ...mapState(['list','inputValue','viewKey']),
  ...mapGetters(['unDoneLength','infoList'])
}

打開store.js,添加getters,mutations,state

export default new Vuex.Store({
  state: {
    ......
    //保存默認的選項卡值
    viewKey:'all'
  },
  mutations: {
    ......
    changeKey(state,key){
      //當用戶點擊“全部”,“已完成”,“未完成”選項卡時觸發(fā)
      state.viewKey = key
    }
  },
  ......
  getters:{
    .......
    infoList(state){
      if(state.viewKey === 'all'){
        return state.list
      }
      if(state.viewKey === 'undone'){
        return state.list.filter( x => x.done === false )
      }
      if(state.viewKey === 'done'){
        return state.list.filter( x => x.done === true )
      }
    }
  }
})
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容