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ù)是響應(yīng)式的,當數(shù)據(jù)發(fā)生改變時寺酪,頁面中的數(shù)據(jù)也會同步更新

2.Vuex的基本使用

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



第二步渤愁,設(shè)置手動配置項目


第三步,設(shè)置功能項




第四步深夯,創(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).先按需導(dǎo)入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中的對應(yīng)函數(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中不能編寫異步的代碼饰剥,會導(dǎo)致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中蜒什,導(dǎo)入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. 導(dǎo)入 ant-design-vue 組件庫
import Antd from 'ant-design-vue'
// 2. 導(dǎo)入組件庫的樣式表
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: {
    //所有任務(wù)列表
    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="請輸入任務(wù)" 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">
        <!-- 復(fù)選框 -->
        <a-checkbox :checked="item.done">{{item.info}}</a-checkbox>
        <!-- 刪除鏈接 -->
        <a slot="actions">刪除</a>
      </a-list-item>

      <!-- footer區(qū)域 -->
      <div slot="footer" class="footer">
        <!-- 未完成的任務(wù)個數(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)完成的任務(wù)清空 -->
        <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: {
    //所有任務(wù)列表
    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文件倦春,給“復(fù)選”按鈕綁定點擊事件,編寫處理函數(shù)

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

//編寫事件處理函數(shù)
methods:{
    ......
    cbStateChanged(id,e){
      //復(fù)選框狀態(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改變對應(yīng)事項的狀態(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展示剩余項

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

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

F.清除完成事項

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

<!-- 把已經(jīng)完成的任務(wù)清空 -->
<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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市懈叹,隨后出現(xiàn)的幾起案子乖杠,更是在濱河造成了極大的恐慌,老刑警劉巖项阴,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滑黔,死亡現(xiàn)場離奇詭異,居然都是意外死亡环揽,警方通過查閱死者的電腦和手機略荡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歉胶,“玉大人汛兜,你說我怎么就攤上這事⊥ń瘢” “怎么了粥谬?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵肛根,是天一觀的道長。 經(jīng)常有香客問我漏策,道長派哲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任掺喻,我火速辦了婚禮芭届,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘感耙。我一直安慰自己褂乍,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布即硼。 她就那樣靜靜地躺著逃片,像睡著了一般。 火紅的嫁衣襯著肌膚如雪只酥。 梳的紋絲不亂的頭發(fā)上褥实,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音裂允,去河邊找鬼性锭。 笑死,一個胖子當著我的面吹牛叫胖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播她奥,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼瓮增,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哩俭?” 一聲冷哼從身側(cè)響起绷跑,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凡资,沒想到半個月后砸捏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡隙赁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年垦藏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伞访。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掂骏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厚掷,到底是詐尸還是另有隱情弟灼,我是刑警寧澤级解,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站田绑,受9級特大地震影響勤哗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掩驱,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一芒划、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昙篙,春花似錦腊状、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至焚辅,卻和暖如春映屋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背同蜻。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工棚点, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人湾蔓。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓瘫析,卻偏偏與公主長得像,于是被迫代替她去往敵國和親默责。 傳聞我的和親對象是個殘疾皇子贬循,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容