成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Vuex-一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式

Freeman / 2742人閱讀

摘要:的出現(xiàn)就是為了解決這一狀況?;旧暇褪且粋€(gè)容器,它包含著你的應(yīng)用中大部分的狀態(tài)。無(wú)法直接修改的狀態(tài)。如果有些狀態(tài)嚴(yán)格屬于單個(gè)組件,最好還是作為組件的局部狀態(tài)。因此解決辦法也是相同的使用一個(gè)函數(shù)來(lái)聲明模塊狀態(tài)和等等

為什么會(huì)出現(xiàn)Vuex

非父子關(guān)系的組件如何進(jìn)行通信?(Event Bus)
bus.js

import Vue from "vue";
export default new Vue();

foo.vue

import bus from "./bus.js";
export default {
    methods: {
        changeBroData() {
            bus.$emit("changeBarData");
        }
    }
}

bar.vue

import bus from "./bus.js";
export default {
    created() {
        bus.$on("changeBarData",() => {
            this.count++;
        });
    }
}

查看效果

但是當(dāng)我們需要修改這個(gè)操作的時(shí)候,我們需要?jiǎng)?個(gè)地方,倘若項(xiàng)目小的話還倒好說(shuō),但是對(duì)于大項(xiàng)目組件間交互很多的概況,Event Bus就會(huì)表現(xiàn)的很吃力。Vuex的出現(xiàn)就是為了解決這一狀況。

Vuex介紹

安裝:
script標(biāo)簽引入
https://unpkg.com/vuex
NPM
npm install vuex --save-dev

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

每一個(gè) Vuex 應(yīng)用的核心就是 store(倉(cāng)庫(kù))?!皊tore”基本上就是一個(gè)容器,它包含著你的應(yīng)用中大部分的狀態(tài) (state)。Vuex 和單純的全局對(duì)象有以下兩點(diǎn)不同:

Vuex的狀態(tài)存儲(chǔ)是響應(yīng)式的。當(dāng)Vuex的狀態(tài)屬性發(fā)生變化時(shí),相應(yīng)的組件也會(huì)更新。

無(wú)法直接修改Vuex的狀態(tài)。只能通過(guò)顯式的提交(commit)。

簡(jiǎn)單的Store

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increase(state) {
      state.count++;
    }
  }
});
store.commit("increase");
console.log(store.state.count); // 1
State

從上文我們知道Vuex是響應(yīng)式的,我們?nèi)绾卧赩ue實(shí)例中使用Vuex中的實(shí)例呢,自然離不開(kāi)計(jì)算屬性computed了。

在 Vue 組件中獲得 Vuex 狀態(tài)

//倉(cāng)庫(kù)
const store = new Vuex.Store({
  state: {
    count: 1
  }
});
//foo組件
const foo = {
  template: `
            
{{ count }}
`, computed: { count: () => store.state.count } };

這時(shí)候問(wèn)題就來(lái)了,如果這樣進(jìn)行引入store的話,組件就會(huì)以來(lái)全局狀態(tài)單例。
Vuex 通過(guò) store 選項(xiàng),提供了一種機(jī)制將狀態(tài)從根組件“注入”到每一個(gè)子組件中(需調(diào)用 Vue.use(Vuex)):

//掛載App
new Vue({
  el: "#app",
  //注入store選項(xiàng)
  store,
  render: h => h(App)
});
//foo組件
const foo = {
  template: `
            
{{ count }}
`, computed: { count() { // 不能使用箭頭函數(shù),不然this就不是Vue實(shí)例了 // 通過(guò)this.$store獲取到store實(shí)例 return this.$store.state.count } } };

如果有很多狀態(tài)需要映射,我們豈不是要寫好多代碼,這時(shí)候需要用到mapState輔助函數(shù),使用 mapState 輔助函數(shù)幫助我們生成計(jì)算屬性。
輔助函數(shù) 實(shí)例1

const foo = {
  template: `
            
count: {{ count }} countAlias: {{ countAlias }} countPlusLocalCount: {{ countPlusLocalCount }}
`, data() { return { localCount: 2 }; }, computed: Vuex.mapState({ //只處理倉(cāng)庫(kù)中的count count: state => state.count*2, //映射 countAlias: "count", //需要用到Vue實(shí)例的話不能使用箭頭函數(shù)不然this無(wú)法獲取到Vue實(shí)例 countPlusLocalCount(state) { return state.count + this.localCount; } }) };

當(dāng)然當(dāng)映射名與state中屬性名相同時(shí),可以通過(guò)mapState(["count"])這種形式書(shū)寫。
因?yàn)榻M件本身也有許多計(jì)算屬性直接使用mapState的話無(wú)法擴(kuò)充computed了,這時(shí)候我們可以使用ES新屬性: 對(duì)象展開(kāi)運(yùn)算符

computed: {
    localComputed() {
        return this.count;
    },
    ...Vuex.mapState({
        //只處理倉(cāng)庫(kù)中的count
              count: state => state.count*2,
        //映射
        countAlias: "count",
        //需要用到Vue實(shí)例的話不能使用箭頭函數(shù)不然this無(wú)法獲取到Vue實(shí)例
        countPlusLocalCount(state) {
          return state.count + this.localCount;
        }
    })
}

ATT:使用 Vuex 并不意味著你需要將所有的狀態(tài)放入 Vuex。雖然將所有的狀態(tài)放到 Vuex 會(huì)使?fàn)顟B(tài)變化更顯式和易調(diào)試,但也會(huì)使代碼變得冗長(zhǎng)和不直觀。如果有些狀態(tài)嚴(yán)格屬于單個(gè)組件,最好還是作為組件的局部狀態(tài)。你應(yīng)該根據(jù)你的應(yīng)用開(kāi)發(fā)需要進(jìn)行權(quán)衡和確定。

Getter

有時(shí)候我們需要過(guò)濾/處理state中的屬性值,就像Vue實(shí)例中我們需要處理data數(shù)據(jù)一樣,Vue有computed。Vuex同樣提供給我們一個(gè)屬性getter,getter就是Vuex的“計(jì)算屬性”。
Getter接收state作為第一個(gè)參數(shù)

//倉(cāng)庫(kù)
const store = new Vuex.Store({
  state: {
    users: [{
      name: "jason",
      id: 1,
      female: false
    }, {
      name: "molly",
      id: 2,
      female: true
    }, {
      name: "steven",
      id: 3,
      female: false
    }]
  },
  getters: {
    // 過(guò)濾所有屬性中female是true的對(duì)象
    getFemaleUsers: state => state.users.filter(user => user.female)
  }
});
console.log(store.getters.getFemaleUsers);
//[{ "name": "molly", "id": 2, "female": true }]

當(dāng)然Getter同樣有輔助函數(shù) mapGetters將 store 中的 getter 映射到局部計(jì)算屬性
直接上對(duì)象展開(kāi)運(yùn)算符了
輔助函數(shù) 實(shí)例1

//foo組件
const foo = {
  template: `
            
femaleList: {{ femaleList }}
`, computed: { // 屬性名相同的不再闡述 ...Vuex.mapGetters({ femaleList: "getFemaleUsers" }) } };
Mutation

更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation
提交時(shí)額外的參數(shù)被稱為載荷
普通風(fēng)格提交方式

store.commit("mutationName", {
    params: "參數(shù)"
});

對(duì)象風(fēng)格提交方式

store.commit({
    type: "mutationName",
    params: "參數(shù)"
});

注意點(diǎn):

設(shè)置對(duì)象新屬性時(shí)
方法1:Vue.set(obj, "newVal", 100)
方法2:obj = {...obj, newVal: 100};

Mutations的事件類型盡量使用常量,并用一個(gè)文件進(jìn)行維護(hù)。方便協(xié)同開(kāi)發(fā)以及維護(hù)。

// 存儲(chǔ)事件名mutations-types.js
export const MUTATIONS_GETDATA = "MUTATIONS_GETDATA";
export const MUTATIONS_SUCCESS = "MUTATIONS_SUCCESS";
import { MUTATIONS_GETDATA ,MUTATIONS_SUCCESS } from "path/mutations-types.js";

const store = new Vuex.Store({
    mutations: {
        [MUTATIONS_GETDATA]() {
            // todo
        },
        [MUTATIONS_SUCCESS]() {
            // todo
        }
    }
});

Mutations中的函數(shù)必須都是同步函數(shù),異步函數(shù)都要寫在Actions中。

在組件中提交Mutation
$store.commit("xxx","yyy")
當(dāng)然也有對(duì)應(yīng)的輔助函數(shù)幫助我們映射到對(duì)應(yīng)的methods方法中

import { mapMutations } from "vuex";
export default {
    methods: {
        ...mapMutations([
            "event1",
            "event2"
        ]),
        ...mapMutations({
            eventAlias: "event3" //將this.eventAlias()映射為this.$store.commit("event3")
        })
    }
};
Action

Action與Mutation的不同在于Action不直接修改狀態(tài)只是做commit一個(gè)mutation、然后就是可以做異步操作。
簡(jiǎn)單的Action

const INCREASE_COUNT = "INCREASE_COUNT";
const store = new Vuex.Store({
  state: {
    count: 0
  },
    mutations: {
    [INCREASE_COUNT](state) {
      state.count++;
    }
  },
  actions: {
    add({ commit }) {
      commit(INCREASE_COUNT);
    }
  }
});

看到這我們或許以為Actions的作用與Mutations不一樣么,對(duì)到現(xiàn)在為止作用是一樣的,但是Actions可以執(zhí)行異步操作

const INCREASE_COUNT = "INCREASE_COUNT";
const store = new Vuex.Store({
  state: {
    count: 0
  },
    mutations: {
    [INCREASE_COUNT](state) {
      state.count++;
    }
  },
  actions: {
    add({ commit }) {
        setTimeout(() => {
            commit(INCREASE_COUNT);
        }, 1000);
    }
  }
});

Action的分發(fā)也有兩種方式
普通風(fēng)格分發(fā)方式

store.dispatch("actionName", {
    params: "參數(shù)"
});

對(duì)象風(fēng)格分發(fā)方式

store.dispatch({
    type: "actionName",
    params: "參數(shù)"
});

輔助函數(shù)mapActions用法與mapMutations無(wú)異
代碼鏈接

methods: {
    ...mapActions({
        add: "add"
    })
}

組合Action

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit("someMutation")
        resolve()
      }, 1000)
    })
  },
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch("actionA").then(() => {
      commit("someOtherMutation")
    })
  }
}
store.dispatch("actionA").then(() => {
  // ...
})
或者
store.dispatch("actionB");
Module

如果項(xiàng)目龐大的話我們需要維護(hù)很多狀態(tài),這時(shí)候store會(huì)變得非常龐大,我們就需要store分割成很多模塊(Module),每個(gè)模塊同樣擁有自己的state,getters,mutations,actions以及modules

const moduleA = {
  state: {
    a: "A"
  }
};
const moduleB = {
  state: {
    a: "B"
  }
};
const store = new Vuex.Store({
  modules: {
    moduleA,
    moduleB
  }
});
console.log(store.state.moduleA.a); //A
console.log(store.state.moduleB.a); //B

模塊內(nèi)部的mutationgetter接收的第一個(gè)參數(shù)都是局部狀態(tài)對(duì)象

例如
const moduleA = {
    state: {
        price: 50,
        count: 2
    },
    getters: {
        totalPrice: state => state.price*state.count
    },
    mutations: {
        decreaseCount(state) {
            state.count--;
        }
    }
};

模塊內(nèi)部的getter,根節(jié)點(diǎn)的狀態(tài)會(huì)在第三個(gè)參數(shù)展示出來(lái)。
注:根節(jié)點(diǎn)的狀態(tài)就是指的store.state

const moduleB = {
  state: {
      count: 2
  },
  getters: {
    sum: (state, getters, rootState) => state.count+rootState.count
  }
};
const store = new Vuex.Store({
  state: {
    count: 1
  },
  modules: {
    moduleB
  }
});
console.log(store.getters.sum);// 3

模塊內(nèi)部的action,局部狀態(tài):context.state根部狀態(tài):context.rootState

const moduleC = {
  state: {
      count: 2
  },
  mutations: {
    increaseCount(state) {
        state.count++;
    }
  },
  actions: {
    addCount({ commit, state, rootState }) {
        let sum = state.count + rootState.count;
        if(sum % 3 === 0) {
            commit("increaseCount");
        }
    }
  }
};
const store = new Vuex.Store({
  state: {
    count: 1
  },
  modules: {
    moduleC
  }
});
console.log(store.state.moduleC.count);// 2
store.dispatch("addCount");
console.log(store.state.moduleC.count);// 3

命名空間
默認(rèn)情況下,模塊內(nèi)部的 actionmutationgetter 是注冊(cè)在全局命名空間的——這樣使得多個(gè)模塊能夠?qū)ν?mutationaction 作出響應(yīng)。
如果希望你的模塊具有更高的封裝度和復(fù)用性,你可以通過(guò)添加 namespaced: true 的方式使其成為命名空間模塊。當(dāng)模塊被注冊(cè)后,它的所有 getter、actionmutation 都會(huì)自動(dòng)根據(jù)模塊注冊(cè)的路徑調(diào)整命名。(摘自官網(wǎng))
注1:特別提出:模塊內(nèi)的state是嵌套的,namespaced屬性不會(huì)對(duì)其產(chǎn)生絲毫影響。
注2:沒(méi)加namespaced: true的模塊會(huì)繼承父模塊的命名空間
代碼鏈接

const store = new Vuex.Store({
    modules: {
    moduleA: {
      namespaced: true,
      getters: {
        count: () => 0 // store.getters["moduleA/count"]
      },
      modules: {
        moduleB: {
          getters: {
              count1: () => 1 //繼承了父模塊的命名空間 store.getters["moduleA/count1"]
            }
        },
        moduleC: {
          namespaced: true,
          getters: {
              count2: () => 2 //繼承了父模塊的命名空間 store.getters["moduleA/moduleC/count1"]
            }
        }
      }
    }
  }
});
console.log(store.getters["moduleA/count"]);// 0
console.log(store.getters["moduleA/count1"]);// 1
console.log(store.getters["moduleA/moduleC/count2"]);// 2

在命名空間模塊內(nèi)部訪問(wèn)全局內(nèi)容

模塊內(nèi)部希望使用全局state與全局getter

rootStaterootGetters會(huì)作為getter第三個(gè)第四個(gè)參數(shù)傳入

someGetter: (state, getters, rootState, rootGetters) => {
    //todo
}
const store = new Vuex.Store({
  getters: {
    someOtherGetter: state => "ROOT"
  },
  modules: {
    moduleA: {
      namespaced: true,
      getters: {
        someGetter(state,getters,rootState,rootGetters) {
          return getters.someOtherGetter; // INSIDE
          // return rootGetters.someOtherGetter; // ROOT
        },
        someOtherGetter: state => "INSIDE"
      }
    }
  }
});
console.log(store.getters["moduleA/someGetter"]);

也會(huì)通過(guò)context.rootStatecontext.rootGetts傳入

someAction:(context) => {
    //todo
}
或者
someAction:({ commit, dispatch, rootState, rootGetters }) => {
    //todo
}

模塊內(nèi)部希望使用全局mutation與全局action,只需要在執(zhí)行分發(fā)或者提交的時(shí)候在第三個(gè)參數(shù)位置傳入{ root: true }

dispatch("someOtherAction", null, {root: true});
commit("someOtherMutation", null, {root: true});

栗子(沒(méi)有寫mutation與state的可以自行嘗試)

const store = new Vuex.Store({
  getters: {
    someOtherGetter: state => "ROOT"
  },
  actions: {
    someOtherAction() {
      console.log("ROOT_ACTION");
    }
  },
  modules: {
    moduleA: {
      namespaced: true,
      getters: {
        someGetter(state,getters,rootState,rootGetters) {
          return getters.someOtherGetter; // INSIDE
          // return rootGetters.someOtherGetter; // ROOT
        },
        someOtherGetter: state => "INSIDE"
      },
      actions: {
        someAction({ dispatch, getters, rootGetters }) {
          console.log(getters.someOtherGetter);//INSIDE
          console.log(rootGetters.someOtherGetter);//ROOT
          dispatch("someOtherAction");//INSIDE_ACTION
          dispatch("someOtherAction", null, {root: true});//ROOT_ACTION
        },
        someOtherAction() {
          console.log("INSIDE_ACTION");
        }
      }
    }
  }
});
console.log(store.getters["moduleA/someGetter"]);
store.dispatch("moduleA/someAction");

當(dāng)我們將store里的狀態(tài)映射到組件的時(shí)候,會(huì)出現(xiàn)下面的問(wèn)題

computed: {
    ...mapState({
        b1:state => state.moduleA.moduleB.b1,
        b2:state => state.moduleA.moduleB.b2
    })
},
methods: {
    ...mapActions({
        "moduleA/moduleB/action1",
        "moduleA/moduleB/action2"
    })
}
是不是比較繁瑣,代碼太過(guò)冗余。

當(dāng)然mapState、mapGettersmapMutations、mapActions這些輔助函數(shù)都可以將空間名稱字符串作為第一個(gè)參數(shù)傳遞,這樣上面的例子可以簡(jiǎn)化成

computed: {
    ...mapState("moduleA/moduleB", {
        b1:state => state.b1,
        b2:state => state.b2
    })
},
methods: {
    ...mapActions("moduleA/moduleB", {
        "action1",
        "action2"
    })
}

當(dāng)然還有一個(gè)方法,使用Vuex提供的createNamespacedHelpers創(chuàng)建基于某個(gè)命名空間函數(shù),它返回一個(gè)對(duì)象,對(duì)象里有新的綁定在給定命名空間值上的組件綁定輔助函數(shù)。

import { createNamespacedHelpers } from "vuex";
const { mapState , mapActions } = createNamespacedHelpers("moduleA/moduleB");
export default {
    computed: {
        ...mapState({
            b1:state => state.b1,
            b2:state => state.b2
        })
    },
    methods: {
        ...mapActions({
            "action1",
            "action2"
        })
    }
}

模塊重用
有時(shí)我們可能需要?jiǎng)?chuàng)建一個(gè)模塊的多個(gè)實(shí)例:

創(chuàng)建多個(gè) store,他們公用同一個(gè)模塊

在一個(gè) store 中多次注冊(cè)同一個(gè)模塊

如果我們使用一個(gè)純對(duì)象來(lái)聲明模塊的狀態(tài),那么這個(gè)狀態(tài)對(duì)象會(huì)通過(guò)引用被共享,導(dǎo)致?tīng)顟B(tài)對(duì)象被修改時(shí) store 或模塊間數(shù)據(jù)互相污染的問(wèn)題。

實(shí)際上這和 Vue 組件內(nèi)的 data 是同樣的問(wèn)題。因此解決辦法也是相同的——使用一個(gè)函數(shù)來(lái)聲明模塊狀態(tài)

const MyReusableModule = {
  state () {
    return {
      foo: "bar"
    }
  },
  // mutation, action 和 getter 等等...
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90526.html

相關(guān)文章

  • Vuex10分鐘入門

    摘要:它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。寫需要的組件創(chuàng)建一個(gè)組件,懟下面的內(nèi)容,你喜歡彬哥哪一點(diǎn)創(chuàng)建一個(gè)展示組件我喜歡彬哥打開(kāi),刪掉沒(méi)用的東西,直接懟下面的代碼,到這里,架子就搭好了。 通過(guò)本文你將: 1.知道什么是Vuex. 2.知道為什么要用Vuex. 3.能跑一個(gè)Vuex的例子。 4.了解相關(guān)概念,面試的時(shí)候能說(shuō)出一個(gè)所以然 5...

    idisfkj 評(píng)論0 收藏0
  • Vue.js狀態(tài)管理模式 Vuex

    摘要:是一個(gè)專為應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。通過(guò)方法觸發(fā)在內(nèi)部執(zhí)行異步操作對(duì)象形式傳參以載荷形式分發(fā) showImg(https://segmentfault.com/img/bVDxBu?w=701&h=551); vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理...

    Codeing_ls 評(píng)論0 收藏0
  • vue 項(xiàng)目實(shí)戰(zhàn) (vue全家桶之--- vuex)

    摘要:官方文檔對(duì)的解讀是是一個(gè)專為應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。而就是為了解決這樣的問(wèn)題,把組件的共享狀態(tài)抽取出來(lái),以一個(gè)全局單例模式管理。我們還可以傳入?yún)?shù)傳入一個(gè)對(duì)象可以修改中的狀態(tài),但是并不是說(shuō)隨隨便便修改的比如說(shuō)老規(guī)矩先安裝 npm install vuex --save 在看下面內(nèi)容之前 你應(yīng)該大概的看了一邊vuex官方的文檔對(duì)vuex有個(gè)大概對(duì)了解 首先 vuex 是什么? vuex...

    番茄西紅柿 評(píng)論0 收藏0
  • 淺談vuex

    摘要:概念淺談是一個(gè)專為應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。更改的中的狀態(tài)的唯一方法,類似。允許我們將分割成模塊。 通過(guò)購(gòu)物車的一個(gè)案列,把vuex學(xué)習(xí)了一篇。 vuex概念淺談 Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以...

    chaos_G 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

Freeman

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<