Vuex簡單使用

一蒜鸡、初始化Vuex

Vuex是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式瓢姻。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)肉康,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。
如果一份數(shù)據(jù)需要在多個(gè)組件中使用诫钓,組件間傳值又比較復(fù)雜赋咽,就可以使用vuex托管數(shù)據(jù)。

1芹扭、安裝

npm install vuex --save

2麻顶、導(dǎo)入

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

3、創(chuàng)建狀態(tài)管理對象 store

state選項(xiàng):定義狀態(tài)(狀態(tài)就是數(shù)據(jù))舱卡。
mutations選項(xiàng):定義修改狀態(tài)的方法(注意:這里面只能定義同步方法)辅肾。

export default new Vuex.Store({
  // 定義全局狀態(tài)(狀態(tài)就是數(shù)據(jù))
  state:{
    car:{
        name:'奔馳',
        price:'40W'
    }
  },
  // 定義修改狀態(tài)的方法
  mutations:{
    //該方法,修改汽車信息
    updateCar(state,val){
        state.car = val
    }
  }
})

4轮锥、注冊給Vue

// 導(dǎo)入當(dāng)前項(xiàng)目中的全局狀態(tài)管理對象
import store from './store'
new Vue({
  // 在vue實(shí)例中使用全局狀態(tài)管理對象
  store,
  render: h => h(App)
}).$mount('#app')

5矫钓、簡單使用

$store:返回的是當(dāng)前項(xiàng)目中的全局狀態(tài)對象。
commit()方法:用于執(zhí)行指定的mutations里面的方法。

(1)獲取數(shù)據(jù)

在組件中新娜,直接通過$store.state就可以獲取到全局狀態(tài)對象管理的狀態(tài)數(shù)據(jù)赵辕,直接渲染到頁面。

<div>車輛名稱:{{ $store.state.car.name }}</div>
<div>車輛價(jià)格:{{ $store.state.car.price }}</div>

(2)修改數(shù)據(jù)

<div>車輛名稱:{{ $store.state.car.name }}</div>
<div>車輛價(jià)格:{{ $store.state.car.price }}</div>
<button @click="updateCar">修改汽車信息</button>
methods: {
  updateCar() {
    this.$store.commit("updateCar", { name: "奔馳", price: "60W" });
  }
}

二杯活、核心概念

1匆帚、state

state選項(xiàng):定義狀態(tài)(狀態(tài)就是數(shù)據(jù))熬词。

  state: {
    name:'張三'
  }

通過$store.state.數(shù)據(jù)名使用旁钧。

<div>姓名:{{ $store.state.name }}</div>

2、getters

getters選項(xiàng):定義計(jì)算屬性互拾。方法的參數(shù)是狀態(tài)對象歪今。

  getters:{
    // 方法的第一個(gè)參數(shù)是全局狀態(tài)
    nameInfo(state){
      return `我的名字叫${state.name}`
    }
  }

通過$store.getters.屬性名使用計(jì)算屬性。

<div>{{ $store.getters.nameInfo }}</div>

3颜矿、mutations

mutations選項(xiàng):定義修改狀態(tài)的方法(注意:這里的方法一般都是同步方法)寄猩。方法的第一個(gè)參數(shù)是狀態(tài)對象,第二個(gè)參數(shù)是新值骑疆。

  mutations:{
    // 修改姓名
    updateName(state,val){
      state.name = val
    }
  },

通過commit()方法田篇,調(diào)用mutations里面的方法。

this.$store.commit("updateName", '李四');

4箍铭、actions

actions選項(xiàng):定義操作狀態(tài)的方法(這里的方法可以定義異步方法)泊柬。
注意:actions里的方法最好不要直接操作state狀態(tài),而是通過調(diào)用mutations里面的方法去修改狀態(tài)诈火。所以兽赁,actions直接操作的是mutations。

  state: {
    carAddress:'意大利'
  },
  mutations:{
    //修改汽車的產(chǎn)地
    updateCarAddress(state,val){
      state.carAddress = val
    }
  },
  actions:{
    //修改汽車的產(chǎn)地
    //方法的第一個(gè)參數(shù)是全局狀態(tài)管理對象冷守,第二個(gè)參數(shù)是具體的值
    updateCarAddress(store,val){
      axios.get(val).then(({data})=>{
        // 方式一:這里可以直接修改狀態(tài)
        // store.state.carAddress = data.address
        // 方式二:通過調(diào)用mutations里面的方法修改狀態(tài)
        store.commit('updateCarAddress',data.address)
      })
    }
  }

通過dispatch()方法刀崖,調(diào)用actions里面定義的方法。

this.$store.dispatch('updateCarAddress','data/address.json')

5拍摇、modules

由于使用單一狀態(tài)樹亮钦,應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí)充活,store 對象就有可能變得相當(dāng)臃腫或悲。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)堪唐。每個(gè)模塊擁有自己的 state巡语、mutation、action淮菠、getter男公、甚至是嵌套子模塊。

(1)定義模塊

namespaced屬性:默認(rèn)情況下,action枢赔、mutation 和 getter 是注冊在全局命名空間的澄阳。通過設(shè)置namespaced屬性為true,將action踏拜、mutation 和 getter全部注冊到私有命名空間中碎赢。

export default {
    namespaced:true,
    // 狀態(tài)
    state:{
        planeName:'空客404',
        planePrice:'10Y',
        planeAddress:'中國'
    },
    // 計(jì)算屬性
    getters:{
        planeInfo(state){
            return `飛機(jī)名稱:${state.planeName},飛機(jī)價(jià)格:${state.planePrice}速梗,飛機(jī)產(chǎn)地:${state.planeAddress}`
        }
    },
    // 同步方法
    mutations:{
        updatePlaneName(state,val){
            state.planeName = val
        },
        updatePlanePrice(state,val){
            state.planePrice = val
        }
    },
    // 異步方法
    actions:{
        updatePlanePrice(store,val){
            setTimeout(() => {
                store.commit('updatePlanePrice',val)
            }, 500);
        }
    }
}

(2)在全局狀態(tài)管理對象中導(dǎo)入模塊

// 導(dǎo)入飛機(jī)模塊
import plane from './modules/plane.js'

// 創(chuàng)建一個(gè)全局狀態(tài)管理對象并導(dǎo)出
export default new Vuex.Store({
  // 模塊
  modules:{
    // 飛機(jī)模塊
    plane
  }
})

(3)使用模塊

① 獲取模塊中的state狀態(tài)

要從私有模塊中獲取數(shù)據(jù)肮塞,方式是:$store.state.模塊名稱.模塊的數(shù)據(jù)

<div>飛機(jī)名稱:{{ planeName }}</div>
planeName() {
  return this.$store.state.plane.planeName;
}

② 獲取模塊中的getters計(jì)算屬性

要從私有模塊中獲取計(jì)算屬性姻锁,方式是:$store.getters['模塊名/計(jì)算屬性']枕赵。

<div>{{planeInfo}}</div>
planeInfo(){
    return this.$store.getters['plane/planeInfo']
}

③ 調(diào)用模塊中的mutations定義的方法

調(diào)用私有模塊里面的mutations定義的方法,方式是:$store.commit('模塊名/方法名',新值)位隶。

<button @click="updatePlaneName">修改飛機(jī)名稱</button>
updatePlaneName(){
  this.$store.commit('plane/updatePlaneName','波音747')
}

④ 調(diào)用模塊中的actions定義的方法

調(diào)用私有模塊里面的actions定義的方法拷窜,方式是:$store.dispatch('模塊名/方法名',新值)

<button @click="updatePlanePrice">修改飛機(jī)價(jià)格</button>
updatePlanePrice(){
  this.$store.dispatch('plane/updatePlanePrice','20Y')
}

三涧黄、Vuex使用

1篮昧、計(jì)算屬性中轉(zhuǎn)

直接在模板中使用全局狀態(tài)管理數(shù)據(jù),表達(dá)式會(huì)寫的很長笋妥。所以可以使用計(jì)算屬性懊昨。

  // getters選項(xiàng)定義計(jì)算屬性
  getters:{
    carInfo(state){
      return `汽車名稱:${state.carName},汽車價(jià)格:${state.carPrice}挽鞠,汽車產(chǎn)地:${state.carAddress}`
    }
  }
 <!-- 直接在模板中使用全局狀態(tài)里面的計(jì)算屬性 -->
 <div>{{$store.getters.carInfo}}</div>
 <div>{{carInfo}}</div>
  //計(jì)算屬性
  computed:{
    // 汽車信息
    carInfo(){
      // 返回全局狀態(tài)管理里面的計(jì)算屬性
      return this.$store.getters.carInfo
    }
  }

2疚颊、映射函數(shù)

通過映射函數(shù)mapState、mapGetters信认、mapActions材义、mapMutations,可以將vuex.store中的屬性映射到vue實(shí)例身上嫁赏,這樣在vue實(shí)例中就能訪問vuex.store中的屬性了其掂,便于操作vuex.store。

(1)導(dǎo)入映射函數(shù)

// 從vuex中潦蝇,導(dǎo)入映射函數(shù)
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";

(2)使用映射函數(shù)生成計(jì)算屬性

如果vuex里面state的數(shù)據(jù)名稱 跟 頁面中的計(jì)算屬性名稱相同款熬,就可以使用mapState映射函數(shù),自動(dòng)生成頁面中的計(jì)算屬性攘乒。
如果vuex里面getters的數(shù)據(jù)名稱 跟 頁面中的計(jì)算屬性名稱相同贤牛,就可以使用mapGetters映射函數(shù),自動(dòng)生成頁面中的計(jì)算屬性则酝。
注意:如果要映射模塊里面的state/getters殉簸,函數(shù)的第一個(gè)參數(shù)設(shè)置為模塊的名稱。

<div>汽車名稱:{{ carName }}</div>
<div>汽車價(jià)格:{{ carPrice }}</div>
<div>汽車產(chǎn)地:{{ carAddress }}</div>
<div>{{ carInfo }}</div>
<hr/>
<div>飛機(jī)名稱:{{ planeName }}</div>
<div>飛機(jī)價(jià)格:{{ planePrice }}</div>
<div>飛機(jī)產(chǎn)地:{{ planeAddress }}</div>
<div>{{ planeInfo }}</div>
computed: {
  // mapState映射state
  ...mapState(["carName", "carPrice", "carAddress"]),
  // mapGetters映射getters
  ...mapGetters(["carInfo"]),

  // 映射私有模塊里面的數(shù)據(jù)
  ...mapState('plane',['planeName','planePrice','planeAddress']),
  ...mapGetters('plane',['planeInfo'])
}

(3)使用映射函數(shù)生成方法

如果定義的方法名跟全局管理對象中mutations里面的方法名相同,并且定義的方法會(huì)帶有一個(gè)參數(shù)般卑,通過參數(shù)傳遞數(shù)據(jù)武鲁。滿足該規(guī)則,就可以使用mapMutations映射函數(shù)生成方法蝠检。
如果定義的方法名跟全局管理對象中actions里面的方法名相同沐鼠,并且定義的方法會(huì)帶有一個(gè)參數(shù),通過參數(shù)傳遞數(shù)據(jù)叹谁。滿足該規(guī)則饲梭,就可以使用mapActions映射函數(shù)生成方法。
注意:如果要映射私有模塊中mutations/actions里面的方法本慕,函數(shù)的第一個(gè)參數(shù)設(shè)置為模塊的名稱排拷。

<button @click="updateCarName('賓利')">修改汽車名稱</button>
<button @click="updateCarPrice('300W')">修改汽車價(jià)格</button>
<button @click="updateCarAddress('data/address.json')">修改汽車產(chǎn)地</button>
<hr/>
<button @click="updatePlaneName('波音747')">修改飛機(jī)名稱</button>
<button @click="updatePlanePrice('20Y')">修改飛機(jī)價(jià)格</button>
methods: {
  // 映射全局管理對象中mutations里面的方法
  ...mapMutations(["updateCarName", "updateCarPrice"]),
  // 映射全局管理對象中actions里面的方法
  ...mapActions(["updateCarAddress"]),

  // 映射私有模塊里面的方法
  ...mapMutations('plane',['updatePlaneName']),
  ...mapActions('plane',['updatePlanePrice'])
}

3侧漓、購物車模塊

import axios from "axios";
export default {
  namespaced: true,
  state: {
    //商品數(shù)組
    goodses: [],
  },
  getters: {
    //總價(jià)
    totalPrice(state) {
      return state.goodses.filter((r) => r.ck).map((r) => r.price * r.count).reduce((a, b) => a + b, 0);
    },
    // 是否全選
    isCkAll(state) {
      return state.goodses.length>0 & state.goodses.every((r) => r.ck);
    },
  },
  mutations: {
    // 加載數(shù)據(jù)的同步方法
    loadGoodses(state, val) {
      state.goodses = val;
    },
    // 設(shè)置所有商品的狀態(tài)
    ckAll(state, val) {
      state.goodses.forEach((r) => {
        r.ck = val;
      });
    },
    // 根據(jù)id刪除商品
    delGoodsById(state, id) {
      let index = state.goodses.findIndex((r) => r.id == id);
      state.goodses.splice(index, 1);
    },
  },
  actions: {
    // 加載數(shù)據(jù)的異步方法
    loadGoodses(store, val) {
      axios.get(val).then(({ data }) => {
        store.commit("loadGoodses", data);
      });
    },
    // 設(shè)置所有商品的狀態(tài)
    ckAll(store, val) {
      store.commit("ckAll", val);
    },
    // 根據(jù)id刪除商品
    delGoodsById(store, id) {
        store.commit("delGoodsById", id);
    },
  },
};
<template>
  <div class="shopcart">
    <h4>購物車</h4>
    <table>
      <thead>
        <tr>
          <th>
            <input type="checkbox" v-model="isCkAll" />
          </th>
          <th>名稱</th>
          <th>圖片</th>
          <th>單價(jià)</th>
          <th>數(shù)量</th>
          <th>小計(jì)</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in goodses" :key="item.id">
          <td>
            <input type="checkbox" v-model="item.ck" />
          </td>
          <td>{{ item.name }}</td>
          <td>
            <img :src="item.img" />
          </td>
          <td>{{ item.price }}</td>
          <td>
            <button @click="item.count--" :disabled="item.count === 1">
              -
            </button>
            <input type="text" v-model="item.count" />
            <button @click="item.count++" :disabled="item.count === 10">
              +
            </button>
          </td>
          <td>{{ item.price * item.count }}</td>
          <td>
            <button @click="delGoodsById(item.id)">刪除</button>
          </td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td colspan="7">
            <span>總價(jià):</span>
            <span>{{ totalPrice }}</span>
          </td>
        </tr>
      </tfoot>
    </table>
  </div>
</template>
<script>
import { mapState, mapGetters, mapActions } from "vuex";
export default {
  name: "Shopcart",
  computed: {
    ...mapState("shopcart", ["goodses"]),
    ...mapGetters("shopcart", ["totalPrice"]),
    // 定義可以修改的計(jì)算屬性
    isCkAll: {
      set(val) {
        this.ckAll(val);
      },
      get() {
        return this.$store.getters["shopcart/isCkAll"];
      },
    },
  },
  methods: {
    // 映射actions對應(yīng)的方法
    ...mapActions("shopcart", ["ckAll", "delGoodsById"]),
  },
  // 頁面掛載完成
  mounted() {
    this.$store.dispatch("shopcart/loadGoodses", "data/shopcart.json");
  },
};
</script>
購物車效果圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锅尘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子布蔗,更是在濱河造成了極大的恐慌藤违,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纵揍,死亡現(xiàn)場離奇詭異顿乒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)泽谨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門璧榄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吧雹,你說我怎么就攤上這事骨杂。” “怎么了雄卷?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵搓蚪,是天一觀的道長。 經(jīng)常有香客問我丁鹉,道長妒潭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任揣钦,我火速辦了婚禮雳灾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冯凹。我一直安慰自己谎亩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著团驱,像睡著了一般摸吠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嚎花,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天寸痢,我揣著相機(jī)與錄音,去河邊找鬼紊选。 笑死啼止,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的兵罢。 我是一名探鬼主播献烦,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卖词!你這毒婦竟也來了巩那?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤此蜈,失蹤者是張志新(化名)和其女友劉穎即横,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裆赵,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡东囚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了战授。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片页藻。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖植兰,靈堂內(nèi)的尸體忽然破棺而出份帐,到底是詐尸還是另有隱情,我是刑警寧澤钉跷,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布弥鹦,位于F島的核電站,受9級特大地震影響爷辙,放射性物質(zhì)發(fā)生泄漏彬坏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一膝晾、第九天 我趴在偏房一處隱蔽的房頂上張望栓始。 院中可真熱鬧,春花似錦血当、人聲如沸幻赚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽落恼。三九已至箩退,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佳谦,已是汗流浹背戴涝。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钻蔑,地道東北人啥刻。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像咪笑,于是被迫代替她去往敵國和親可帽。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345