Vuex的理解

Posted lily-wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vuex的理解相关的知识,希望对你有一定的参考价值。

Vuex的理解?

Vuex是适用于Vue.js应用的状态管理库,是一个独立的应用程序,充当应用程序中所有组件的集中存储,其规则确保状态只能以可预测的方式进行变更。

 

Vuex的主要思想?

把组件的共享状态抽取出来,以一个全局单例模式进行管理,在这个模式下,我们的组件树构成了一个强大的视图,不管在树的哪个位置,任何组件都能获取状态或者触发行为。

 

Vuex的优点缺点?

优点:

传统的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力,而且对于父子组件直接或者通过事件来变更和同步状态的多分拷贝,以上的这些模式非常脆弱,通常会导致无法维护代码,所以把组件的共享状态抽取出来,以一个全局单例模式管理,在这种模式下,我们的组件树构成了一个巨大的:视图,不管树在那个位置,任何组件都能获取状态或者触发行为,并且通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将变得更结构化且易于维护

缺点:如果开发的不是大型单页应用,使用Vuex可能是繁琐冗余的。

 

Vuex的特点?

Vuex的状态存储是响应式的,当vue组件从store中读取状态时,若store中状态发生改变,响应的组件也会得到更新状态。但不能直接改变state,必须通过显示的commit(提交)mutations来追踪每一个状态的变化。

 

Vuex的属性?

state,mutations,getters,actions,module(action,mutation,getter都必须是函数)

state:state 状态管理 ,为单一状态树(用一个对象包含了全部的应用层级状态),但与模块化并不冲突。关于状态值的获取,可以通过this.$store访问,当需要访问多个状态时,可以import mapState函数,来获取多个状态。

state为单一状态树,在state中需要定义我们所需要管理的数组、对象、字符串等等,只有在这里定义了,在vue.js的组件中才能获取你定义的这个对象的状态。

一、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data
二、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
三、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中

mutations:

Mutations 改变state状态的函数。每个mutation都有一个事件类型和一个回调函数。可以使用state.commit()提交相应的事件type驱动事件回调函数。且回调函数必须是同步函数。当需要同时调用两个包含异步回调的函数时,可以使用actions来异步调用mutations.

更改store中state状态的唯一方法就是提交mutation,就很类似事件。每个mutation都有一个字符串类型的事件类型和一个回调函数,我们需要改变state的值就要在回调函数中改变。我们要执行这个回调函数,那么我们需要执行一个相应的调用方法:store.commit。

一、更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。二、这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数: 而且Mutation必须为同步函数 当触发一个类型为 increment 的 mutation 时,调用此函数。”

三、要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:store.commit(‘increment’)

mutations,里面装着一些改变数据方法的集合,这是Veux设计很重要的一点,就是把处理数据逻辑方法全部放在mutations里面,使得数据和视图分离。切记:Vuex中store数据改变的唯一方法就是mutation!

getters:Getters 相当于store的计算属性,可以从state中派生出一些状态。接收state作为第一个参数,而且getter的返回值会根据它的依赖被缓存起来,只有getter中的依赖值(state中的某个需要派生状态的值)发生改变的时候才会被重新计算。同时可以利用mapGetters来引入getters。

一、getters 可以对State进行计算操作,它就是Store的计算属性
二、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
三、 如果一个状态只在一个组件内使用,是可以不用getters

actions:

Actions 主要是commit mutations,而不是用于直接更变状态,同时可以包含任何异步操作。Actions主要是通过store.dispatch触发。调用方式:1.在组件中分发actions;2.使用mapActions辅助函数将组建的methods映射为store.dispatch调用。

  action可以提交mutation,在action中可以执行store.commit,而且action中可以有任何的异步操作。在页面中如果我们要调用这个action,则需要执行store.dispatch

一、Action 类似于 mutation,不同在于: 
二、Action 提交的是 mutation,而不是直接变更状态。 
三、Action 可以包含任意异步操作。actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据(但是还是通过mutation来操作,因为只有它能操作)

一个store.dispatch在不同模块中可以触发多个action函数。在这种情况下,只有当所有触发函数完成后,返回的Promise才会执行;

module:

  module其实只是解决了当state中很复杂臃肿的时候,module可以将store分割成模块,每个模块中拥有自己的state、mutation、action和getter。对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState;对于模块内部的 getter,根节点状态会作为第三个参数暴露出来

 

vuex里store有哪些属性值?

state,mutations,active,getters

当一个全局组件需要一个事件才能做出对应响应,需要事件机制,比如说全局有个模态窗口,各个特定组件点击时候,都会显示各个组件对应得data时候,这时候需要事件机制,那么我那些东西需要存在store里面。

 

Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?

一、如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
二、如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便。

 

不用vuex会带来什么问题?

一、可维护性会下降,你要想修改数据,你得维护三个地方

二、可读性会下降,因为一个组件里的数据,你根本就看不出来是从哪来的

三、增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。

 

解决的问题?

一、组件之间的数据通信

二、使用单向数据流的方式进行数据的中心化管理

 

vuex大体可以看做哪四步?

第一到action里面查到这个事件的触发,然后立马是mutaction里面查看对应处理,第三步改变store的状态,第四部getter视图渲染

 

辅助函数?

mapGetters :

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

1、...mapGetters表示// 使用对象展开运算符将 getters 混入 computed 对象中

2、mapGetters里面的都是store.js里面的getters的方法名

mapState:

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余为了解决这个问题,我们可以使用。mapState辅助函数帮助我们生成计算属性,让你少按几次键

mapActions:

mapActions辅助函数将组件的methods映射为store.dispatch调用(需要先在根节点注入store) 

 

数据传递的流程?

技术分享图片

  • Vue Components:Vue组件。html页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
  • dispatch:操作行为触发方法,是唯一能执行action的方法。
  • actions:操作行为处理模块。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
  • commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
  • mutations:状态改变操作方法。是Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
  • state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
  • getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。
  • Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components,界面随之更新。

 

命名空间:namespaced: true

模块具有更高的封装度和复用性

 

1.  使用Vuex只需执行 Vue.use(Vuex),并在Vue的配置中传入一个store对象的示例,store是如何实现注入的?

:Vue.use(Vuex) 方法执行的是install方法,它实现了Vue实例对象的init方法封装和注入,使传入的store对象被设置到Vue上下文环境的$store中。因此在Vue Component任意地方都能够通过this.$store访问到该store。

2.  state内部支持模块配置和模块嵌套,如何实现的?

:在store构造方法中有makeLocalContext方法,所有module都会有一个local context,根据配置时的path进行匹配。所以执行如dispatch(‘submitOrder’, payload)这类action时,默认的拿到都是module的local state,如果要访问最外层或者是其他module的state,只能从rootState按照path路径逐步进行访问。

3.  在执行dispatch触发action(commit同理)的时候,只需传入(type, payload),action执行函数中第一个参数store从哪里获取的?

:store初始化时,所有配置的action和mutation以及getters均被封装过。在执行如dispatch(‘submitOrder’, payload)的时候,actions中type为submitOrder的所有处理方法都是被封装后的,其第一个参数为当前的store对象,所以能够获取到 { dispatch, commit, state, rootState } 等数据。

4.  Vuex如何区分state是外部直接修改,还是通过mutation方法修改的?

:Vuex中修改state的唯一渠道就是执行 commit(‘xx’, payload) 方法,其底层通过执行 this._withCommit(fn) 设置_committing标志变量为true,然后才能修改state,修改完毕还需要还原_committing变量。外部修改虽然能够直接修改state,但是并没有修改_committing标志位,所以只要watch一下state,state change时判断是否_committing值为true,即可判断修改的合法性。

5.  调试时的”时空穿梭”功能是如何实现的?

:devtoolPlugin中提供了此功能。因为dev模式下所有的state change都会被记录下来,’时空穿梭’ 功能其实就是将当前的state替换为记录中某个时刻的state状态,利用 store.replaceState(targetState) 方法将执行this._vm.state = state 实现。

 








以上是关于Vuex的理解的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段13——Vue的状态大管家

对vuex的认识和简单理解

项目集成 vue-router 和 vuex

金蝶handler中 collection 代码片段理解

调用模板化成员函数:帮助我理解另一个 *** 帖子中的代码片段

如何理解这段代码片段中的两对括号?