人妻精品在线观看一区二区三区,蜜臀av精品一区二区三区网站,中文一区二区三区亚洲欧美,熟女人妇精品一区二区,人妻av在线观看视频,欧美日韩国产三级精品网站,黄色免费网站直接进入,超碰公开福利正在播放,国产毛片乡下农村妇女毛片

深入了解vuex的實現(xiàn)原理-今日快訊

來源:php中文網(wǎng) | 2023-03-20 18:10:09 |

當面試被問vuex的實現(xiàn)原理,你要怎么回答?下面本篇文章就來帶大家深入了解一下vuex的實現(xiàn)原理,希望對大家有所幫助!

關(guān)于vuex就不再贅述,簡單回顧一下:當應(yīng)用碰到多個組件共享狀態(tài)時,簡單的單向數(shù)據(jù)流很容易被破壞:第一,多個視圖依賴于同一狀態(tài);第二,來自不同視圖的行為需要變更同一狀態(tài)。


(資料圖片)

若解決前者使用傳參的方式,則不適用于多層嵌套的組件以及兄弟組件;若解決后者使用父子組件直接引用或事件變更和同步狀態(tài)的多份拷貝,則不利于代碼維護。

所以,最好的辦法是:把組件的共享狀態(tài)抽取出,以一個全局單例模式管理!這也正是vuex背后的基本思想?!鞠嚓P(guān)推薦:vuejs視頻教程、web前端開發(fā)】

所以,vuex的大致框架如下:

class Store {    constructor() {        // state        // getters          // mutations        // actions    }    // commit    // dipatch}

接下來,就寫寫看。

一、創(chuàng)建vue項目

vue create vue2-vuex//創(chuàng)建vue2項目yarn add vuex@next --save//安裝vuexyarn serve//啟動項目

二、實現(xiàn)原理

1、State

(1)使用

//store.js// 倉庫import Vue from "vue"import Vuex from "vuex"import extra from "./extra.js"Vue.use(Vuex) //引入vuex的方式,說明Store需要install方法export default new Vuex.Store({    // 倉庫數(shù)據(jù)源    state: {        count: 1,        dowhat: "addCount"    },}
//app.vue<template>    <div class="testState">        <p>{{mycount}}</p>        <p>{{dowhat}}:{{count}}</p>    </div></template><script>export default {    import {        mapState    } from "vuex"    // 推薦方式    computed: mapState()({        mycount: state => state.count    }),    // 推薦方式的簡寫方式    computed: {        // 解構(gòu)的是getters        ...mapState(["count", "dowhat"])    },  }</script>

(2)注意

由于 Vuex 的狀態(tài)存儲是響應(yīng)式的,從 store 實例中讀取狀態(tài)最簡單的方法就是在計算屬性中返回某個狀態(tài),這種模式導(dǎo)致組件依賴全局狀態(tài)單例。在模塊化的構(gòu)建系統(tǒng)中,在每個需要使用 state 的組件中需要頻繁地導(dǎo)入,并且在測試組件時需要模擬狀態(tài)

Vuex 通過 store選項,提供了一種機制將狀態(tài)從根組件“注入”到每一個子組件中(需調(diào)用 Vue.use(Vuex)

(3)實現(xiàn)

所以除了Store內(nèi)部的五大屬性以外,還需要考慮插件的一個install方法,所以大致框架如下:

class Store {    constructor() {        // state        // getters          // mutations        // actions        //modules    }    // commit    // dipatch}let Vuex = {    Store,    Install}export default Vuex

所以,接下來就可以具體實現(xiàn)了,

class Store {    constructor(options) {        // state        this.state = options.state    }}let install = function(_Vue) {    _Vue.mixin({        beforeCreate() { //在組件創(chuàng)建之前自動調(diào)用,每個組件都有這個鉤子            if (this.$options && this.$options.store) { //this.$options讀取根組件                this.$store = this.$options.store            } else {                this.$store = this.$parent && this.$parent.$store            }        }    })}

然而,上述的state的實現(xiàn)有一個缺點:當改變數(shù)據(jù)的時候,state的數(shù)據(jù)不能動態(tài)的渲染。所以如何把state里的數(shù)據(jù)成為響應(yīng)式成為關(guān)鍵問題?實際上,類似vue里的data,也可以通過這種方式讓其成為響應(yīng)式。那么就得從install方法中傳入Vue,所以改變后:

let Vue=nullclass Store {    constructor(options) {        // state        this.vm = new _Vue({          data: {            state: options.state//data中的數(shù)據(jù)才是響應(yīng)式          }        })    }      get state() {        return this.vm.state    }}let install = function(_Vue) {//用于Vue.use(plugin)    Vue=_Vue    _Vue.mixin({        onBeforeCreate() { //在組件創(chuàng)建之前自動調(diào)用,每個組件都有這個鉤子            if (this.$options && this.$options.store) { //this.$options讀取根組件                this.$store = this.$options.store            } else {                this.$store = this.$parent && this.$parent.$store            }        }    })}

2、getters

(1)使用

//store.jsexport default new Vuex.Store({    // 計算屬性    getters: {        // 這里的函數(shù)不需要調(diào)用,可以直接使用,官方默認前面有g(shù)et        getCount(state) {//接受 state 作為其第一個參數(shù)            return state.count * 100;        }    },}

(2)注意

有時候我們需要從 store 中的 state 中派生出一些狀態(tài)(比如增加,刪除,過濾等等),Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據(jù)它的依賴被緩存起來,且只有當它的依賴值發(fā)生了改變才會被重新計算,Getter 接受 state 作為其第一個參數(shù),getter 在通過方法訪問時,每次都會去進行調(diào)用,而不會緩存結(jié)果

(3)實現(xiàn)

// getters    let getters = options.getters || {}    this.getters = {}    Object.keys(getters).forEach(getterName => {      Object.defineProperty(this.getters, getterName, {        get: () => {          return getters[getterName](this.state)        }      })    })

3、mutations

(1)使用

//store.jsexport default new Vuex.Store({        // 相當于methods    mutations: {        // mutations內(nèi)部的函數(shù),天生具備一個形參        add(state, n) {            state.count += n;        },        decrease(state, n) {            state.count -= n;        }    },}
methods: {            submit() {                console.log("success");            },            // 解構(gòu)倉庫mutations里面的方法,要啥解構(gòu)啥            ...mapMutations(["add", "decrease"]),            // this.$store.commit("add"),                            ...mapActions(["addAction", "decreaseAction"]),            // this.addAction()調(diào)用actions里面的方法            // this.$store.dispatch("add"),}

(2)注意

更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 類似于事件:每個 mutation 都有一個字符串的 事件類型 (type)和 一個 回調(diào)函數(shù) (handler)。這個回調(diào)函數(shù)就是進行狀態(tài)更改的地方,并且它會接受 state 作為第一個參數(shù),不能直接調(diào)用一個 mutation handler。這個選項更像是事件注冊:“當觸發(fā)一個類型為 increment的 mutation 時,調(diào)用此函數(shù)?!币獑拘岩粋€ mutation handler,你需要以相應(yīng)的 type 調(diào)用 store.commit方法

可以向 store.commit傳入額外的參數(shù),即 mutation 的 載荷(payload),在大多數(shù)情況下,載荷應(yīng)該是一個對象,這樣可以包含多個字段并且記錄的 mutation 會更易讀

(3)實現(xiàn)

// mutations    let mutations = options.mutations || {}    this.mutations = {}    Object.keys(mutations).forEach(mutationName => {      this.mutations[mutationName] = (arg) => {//保證多個(第二個)參數(shù)的傳入        mutations[mutationName](this.state, arg)      }    })        commit = (method, arg) => {//使用箭頭函數(shù)改變被調(diào)用的this的指向        // console.log(this);        this.mutations[method](arg)  }

4、actions

(1)使用

//store.jsexport default new Vuex.Store({    actions: {        addAction(context) {            // 在這里調(diào)用add方法            context.commit("add", 10);        },        decreaseAction({            commit        }) {            commit("decreaseAction", 5)        }    },}

(2)注意

Action 提交的是 mutation,而不是直接變更狀態(tài)。Action 可以包含任意異步操作Action 函數(shù)接受一個與 store 實例具有相同方法和屬性的 context 對象Action 通過 store.dispatch方法觸發(fā)Action 通常是異步的,store.dispatch可以處理被觸發(fā)的 action 的處理函數(shù)返回的 Promise,并且 store.dispatch仍舊返回 Promise一個 store.dispatch在不同模塊中可以觸發(fā)多個 action 函數(shù)。在這種情況下,只有當所有觸發(fā)函數(shù)完成后,返回的 Promise 才會執(zhí)行

(3)實現(xiàn)

// actions    let actions = options.actions || {}    this.actions = {}    Object.keys(actions).forEach(actionName => {      this.actions[actionName] = (arg) => {        actions[actionName](this, arg)      }    })       dispatch=(method, arg) =>{    this.actions[method](arg)  }

5、modules

(1)使用

// actions    let actions = options.actions || {}    this.actions = {}    Object.keys(actions).forEach(actionName => {      this.actions[actionName] = (arg) => {        actions[actionName](this, arg)      }    })       dispatch=(method, arg) =>{    this.actions[method](arg)  }
//store.js    modules: {        extra: extra    }

(2)注意

由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會集中到一個比較大的對象。當應(yīng)用變得非常復(fù)雜時,store 對象就有可能變得相當臃腫,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割對于模塊內(nèi)部的 mutation 和 getter,接收的第一個參數(shù)是模塊的局部狀態(tài)對象對于模塊內(nèi)部的 action,局部狀態(tài)通過 context.state暴露出來,根節(jié)點狀態(tài)則為 context.rootState

對于模塊內(nèi)部的 getter,根節(jié)點狀態(tài)(rootState)會作為第三個參數(shù)暴露出來

三、整體代碼

let Vue = null//全局的_Vueclass Store {  constructor (options) {    // state    //this.state = options.state 寫法不完美,當改變數(shù)據(jù)的時候,不能動態(tài)的渲染,所以需要把data中的數(shù)據(jù)做成響應(yīng)式的    this.vm = new _Vue({      data: {        state: options.state//data中的數(shù)據(jù)才是響應(yīng)式      }    })    // getters    let getters = options.getters || {}    this.getters = {}    Object.keys(getters).forEach(getterName => {      Object.defineProperty(this.getters, getterName, {        get: () => {          return getters[getterName](this.state)        }      })    })    // mutations    let mutations = options.mutations || {}    this.mutations = {}    Object.keys(mutations).forEach(mutationName => {      this.mutations[mutationName] = (arg) => {//保證多個(第二個)參數(shù)的傳入        mutations[mutationName](this.state, arg)      }    })    // actions    let actions = options.actions || {}    this.actions = {}    Object.keys(actions).forEach(actionName => {      this.actions[actionName] = (arg) => {        actions[actionName](this, arg)      }    })  }  dispatch=(method, arg) =>{    this.actions[method](arg)  }  commit = (method, arg) => {    // console.log(this);    this.mutations[method](arg)  }  get state() {    return this.vm.state  }}let install = function(_Vue) {  Vue = _Vue  Vue.mixin({    beforeCreate() {//在組件創(chuàng)建之前自動調(diào)用,每個組件都有這個鉤子      if (this.$options && this.$options.store) {  // this.$options讀取到根組件        this.$store = this.$options.store      } else { // //如果不是根組件的話,也把$store掛到上面,因為是樹狀組件        this.$store = this.$parent && this.$parent.$store      }    }  })}let Vuex = {  Store,  install}export default Vuex

(學(xué)習視頻分享:vuejs入門教程、編程基礎(chǔ)視頻)

以上就是深入了解vuex的實現(xiàn)原理的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!

關(guān)鍵詞: