vuex的原理

1.vuex的作用

vuex是专门为Vuejs应用程序设计的状态管理工具。其实是集中的数据管理仓库。相当于数据库mongoDB等,任何组件都可以存取仓库中的数据。
vuex的组成部分:

  1. state:是存储的基本数据。
  2. mutations:提交更改数据。
  3. getter:对state加工,和computed计算属性一样。
  4. actions:处理异步,通过store.commit方法触发mutations中的方法,从而改变state值。
  5. module:是store分割的模块,每个模块拥有自己的state、mutations、getters、actions。

2.vuex流程和vue对比

在这里插入图片描述
vue中的data、methods、computed,可以实现响应式。
视图通过点击事件,触发methods中的方法,更改data的值,一旦数据发生变化,computed中的函数把数据能更新到视图。那么computed是如何更新的?其实就是vue的双向绑定原理了。
computed中的计算属性getter生成唯一的watcher—>访问computed中的方法时,会将Dep.target指向它的watcher–>在方法中访问this.。。。,会调用get方法,新增watcher到dep中—>设置时,会调用set方法触发dep.notify实现视图更新。

1.那vuex和vue的响应式例子有什么关系?

我们也可以通过vuex实现同样的功能。vuex中的四部分与vue的对应关系:
state--->data、mutations--->methods、getters--->computed、actions:为了处理异步,不能直接更新state,需要借助mutations。

2.dispatch、commit又是做什么的呢?

在vue中,我们触发点击事件,就能触发methods中的方法,这是vue设计好的。而在vuex中则不行了,一定要有个东西来触发才行。①通过dispatch可以触发可以触发actions中的方法②actions中的commit可以触发mutations中的方法。从而实现state的更新。
在这里插入图片描述
vuex实现响应式的例子:

//store.js
const store =  new Vuex.Store({
state<span class="token punctuation">:</span> <span class="token punctuation">{<!-- --></span>
    count<span class="token punctuation">:</span> <span class="token number">0</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>

<span class="token comment">//第三步:改变state值,state的值只能通过mutations来修改</span>
mutations<span class="token punctuation">:</span> <span class="token punctuation">{<!-- --></span>
    <span class="token function">increment</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        state<span class="token punctuation">.</span>count<span class="token operator">++</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>

//第二步:this.$store.commit("increment")触发mutations中函数"increment"
actions: {
increment({commit}) {
commit("increment"); //this.$store.commit("increment")
}

<span class="token punctuation">}</span><span class="token punctuation">,</span>

//第四步:通过getter中的方法来获取state值
getters: {
getCount(state) {
return state.count
}
}
})

<span class="token keyword">export</span> <span class="token keyword">default</span> store
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
//App.vue
<template>
      <div id="app">
            <button @click="increment">增加</button>
            {{this.$store.getters.getCount}}
      </div>
    </template>
<span class="token operator">&lt;</span>script<span class="token operator">&gt;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{<!-- --></span>
    methods<span class="token punctuation">:</span> <span class="token punctuation">{<!-- --></span>
    <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
            <span class="token comment">//第一步:this.$store.dispatch("increment")触发actions函数"increment"</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token string">"increment"</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">&gt;</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.vuex的原理

vuex吸收了redux的各种优点,完美的结合了vue的响应式数据。那么它的原理是什么呢?
1.每一个vue的插件,都需要一个公开的install方法,vuex也不例外。

// src/store.js
export function install (_Vue) {
  if (Vue && _Vue === Vue) {
    return
  }
  Vue = _Vue
  applyMixin(Vue)//在所有组件的beforeCreate注入了设置this.$store这样的一个对象,
  //在任意组件中执行this.$store都能找到store对象
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.Vuex.Store的构造函数中,有一堆初始化以及resetStoreVM(this,state)整个vuex的关键。

// src/store.js
function resetStoreVM (store, state, hot) {
  // 省略无关代码
  Vue.config.silent = true
  //本质:将我们传入的state作为一个隐藏的vue组件的data
  //也就是说,我们的commit操作,本质上其实是修改这个组件的data
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
}
//this.$store._vm.$data.$$state===this.$store.state
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

总结:

  • vuex是针对vuejs的状态管理工具。vuex完美的结合了vue的响应式数据
  • vue可以直接触发methods中的方法,vuex不行。为了处理异步,当你触发一个点击事件时,会通过dispatch来访问actions中的方法,actions中的commit会触发mutations中的方法从而修改state的值,通过getters来把数据反映到视图。
  • vuex通过Vue.use(vuex),从而调用install方法,通过applyMixin(Vue)在任意组件执行this.$store都能访问到store对象,实现将store挂载注入到组件中。
  • vuex的state状态是响应式的,是借助vue的data是响应式,将state存入vue实例组件的data中
  • vuex的getters则是借助于vue的计算属性computed实现数据的实时监听。

4.mapState辅助函数

当一个组件需要获取多个状态时,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,可以使用mapState辅助函数来帮助我们生成计算属性。当映射的计算属性名称与state的子节点名称相同时,我们也可以给mapState传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])// {count: 1}
//mapState返回的是一个对象,我们也可以使用对象展开符获取
computed: {
    ...mapState(['selectedCard', 'count']), 
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5.mapGetters辅助函数

mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性:

import { mapGetters } from 'vuex'

export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

6. vuex namespaced的作用以及使用方式

1、vuex中的store分模块管理,需要在store的index.js中引入各个模块,为了解决不同模块命名冲突的问题,将不同模块的namespaced:true,之后在不同页面中引入getter、actions、mutations时,需要加上所属的模块名。

2、使用模块中的mutations、getters、actions时候,要加上模块名,例如使用commint执行mutations时

格式:模块名/模块中的mutations

1 this.$store.commit("userInfo/setUserInfo",userInfo)
  • 1

3、获取属性时同样加上模块名

格式:store.state.模块名.模块属性

 1 $store.state.userInfo.userName 
  • 1

参考文档:http://www.imooc.com/article/291242
https://www.jianshu.com/p/d95a7b8afa06
https://www.cnblogs.com/tg666/p/11532587.html

posted @ 2022-08-26 16:42  arrowolf  阅读(474)  评论(0)    收藏  举报