• 欢迎来到本博客,希望可以y一起学习与分享

vuex

JavaScript/Jquery benz 2年前 (2019-03-08) 73次浏览 0个评论 扫描二维码
文章目录[隐藏]

安装vuex与简单使用

使用命令:npm install vuex安装vuex.。

初始化vuex

引入vuex –> 声明使用vuex –> 创建Vuex.Store实例(创建一个store容器) –> 把store容器全局注册到vue上

简单使用vuex

合理布局文件夹

在根目录的src文件夹下创建名为:store的文件夹,用于存放vuex的文件。
创建store.js文件,作为vuex的入口文件,用于实例vuex的store:

在vue入口文件main.js,定义使用vuex:

还可以进一步分离,把state和mutations单独分出去。
在src/store文件夹下,创建名为state的文件夹,这个文件夹用于存放state的文件:

在src/store文件夹下,创建名为mutations的文件夹,这个文件夹用于存放mutations的文件:

最后在vuex的入口文件中引入它们:

Vuex简介

vuex是什么?

vuex就是一个状态(数据)管理工具,每一个vuex都有一个store(仓库),store是一个容器,它包含着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有以下两点不同:

  • 1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

Vuex 和单纯的全局对象有以下两点不同:

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 不能直接改变 store 中的状态改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。

核心概念 state

单一状态树

Vuex 使用 单一状态树 —— 是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

单状态树和模块化并不冲突 —— 在后面的章节里我们会讨论如何将状态和状态变更事件分布到各个子模块中。

在组件中获取state状态

由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。

因为我们在根实例已经注册了store,所以我们也可以使用这种写法

这样我们在模块化的构建系统中,在每个需要使用 state 的组件中就不需要频繁地导入,并且在测试组件时不需要模拟状态。

mapState 辅助函数

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

对象展开运算符

mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?

对象展开运算符可以将mapstate与局部计算属性混合使用

组件仍然保有局部状态

使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。

核心概念 mutations

mutation 必须是同步函数!!!

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

state的数据可以直接修改,但不推荐

虽然在组件上可以通过this.$store.state.字段=值来直接修改store的state里的值,但是官方并不推荐这么做。使用vuex是为了更好的管理数据,而不是简单的修改值。通过mutations修改state,可以追踪到state的修改,而不是像直接修改state数据那样,无声无息。

禁止直接修改state的值

禁止直接修改state的值,仅且只能通过mutations来修改state的数据,那么,只需在vuex实例store的时候开启严格模式即可:

严格模式只推荐在开发环境下开启(用作规范vuex代码),不推荐正式环境使用,所以,应该区别开启:

mutations的使用

Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。调用 store.commit(type, payload) 方法来触发mutations中的相关方法。

提交载荷(Payload)

你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):

对象风格的提交方式

提交 mutation 的另一种方式是直接使用包含 type 属性的对象:

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:

核心概念 getters

getters可以说是store的计算属性,它可以接受state作为第一参数和其他getters作为第二参数来进行计算,这样我们就可以在多个组件使用这个gtters而不必在每一个组建都书写一遍。

mapGetters

同样,vuex也为我们定义了mapGetters

核心概念 actions

actions的目的与mutations是一样的,只是actions是异步的,actions依赖于mutations已定义的方法。

actions使用的步骤:

mutations里定义方法 –> actions里定义方法(方法的第一个参数一定是state),并在方法里面使用commit方法调用mutations里定义的方法,state.commit('mutations里定义的方法名',需要传递的自定义参数) –> 在组件里使用dispatch触发actions,this.$store.dispatch('Actions定义的方法名',需要传递的自定义参数)

让我们来使用一个简单的 action:

前提:
mutations:

state:

开始:

定义一个actions:

把actions注册到vuex:

使用actions:

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • 通过 store.dispatch 方法触发

组合 Action:store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise。

辅助函数:…mapState …mapMutations …mapGetters …mapActions

…mapState

原来是这样写的:

使用辅助函数…mapState代替:

如果state的字段名与computed自定义的方法名 不一致 就这样写:

还有一种写法,以为基本上和原来的写法差不多,所以不太常用:

扩展运算符…mapState,意思是把vuex的state数据映射到计算属性里面,映射后的名字为count(或者counter),所以,就不用写this.$store.state.count这个长串了。

…mapGetters

…mapGetters与 …mapState的用法是一样的。

…mapMutations

…mapActions

总结

mapState与mapGetters的使用方法是差不多的,都先在computed里进行解析。
mapMutations与mapActions的使用方法是差不多的,都先在methods里进行解析。然后直接使用this.方法名(参数)进行使用

模块化:Module

转载于:https://www.jianshu.com/p/e6805c819abb

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

模块的局部状态

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。

同样,对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:

对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:

命名空间

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为命名空间模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如:

启用了命名空间的 getter 和 action 会收到局部化的 getter,dispatch 和 commit。换言之,你在使用模块内容(module assets)时不需要在同一模块内额外添加空间名前缀。更改 namespaced 属性后不需要修改模块内的代码。

在命名空间模块内访问全局内容(Global Assets)

如果你希望使用全局 state 和 getter,rootState 和 rootGetter 会作为第三和第四参数传入 getter,也会通过 context 对象的属性传入 action。

若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。

带命名空间的绑定函数

当使用 mapState, mapGetters, mapActions 和 mapMutations 这些函数来绑定命名空间模块时,写起来可能比较繁琐:

对于这种情况,你可以将模块的空间名称字符串作为第一个参数传递给上述函数,这样所有绑定都会自动将该模块作为上下文。于是上面的例子可以简化为:

而且,你可以通过使用 createNamespacedHelpers 创建基于某个命名空间辅助函数。它返回一个对象,对象里有新的绑定在给定命名空间值上的组件绑定辅助函数:

模块动态注册

在 store 创建之后,你可以使用store.registerModule方法注册模块:

之后就可以通过store.state.myModulestore.state.nested.myModule访问模块的状态。

模块动态注册功能使得其他 Vue 插件可以通过在 store 中附加新模块的方式来使用 Vuex 管理状态。例如,vuex-router-sync插件就是通过动态注册模块将 vue-router 和 vuex 结合在一起,实现应用的路由状态管理。

你也可以使用store.unregisterModule(moduleName)来动态卸载模块。注意,你不能使用此方法卸载静态模块(即创建 store 时声明的模块)。

在注册一个新 module 时,你很有可能想保留过去的 state,例如从一个服务端渲染的应用保留 state。你可以通过preserveState选项将其归档:store.registerModule('a', module, { preserveState: true })

模块重用

有时我们可能需要创建一个模块的多个实例,例如:

  • 创建多个 store,他们公用同一个模块 (例如当 runInNewContext 选项是 false'once' 时,为了在服务端渲染中避免有状态的单例)
  • 在一个 store 中多次注册同一个模块

如果我们使用一个纯对象来声明模块的状态,那么这个状态对象会通过引用被共享,导致状态对象被修改时 store 或模块间数据互相污染的问题。

实际上这和 Vue 组件内的data是同样的问题。因此解决办法也是相同的——使用一个函数来声明模块状态(仅 2.3.0+ 支持):

Vuex之热重载

使用webpack的热模替换(HMR)插件(Hot Module Replacement API)
Vuex支持在开发过程中热重载mutation、module、action和getter
对于mutation和模块,需要使用store.hotUpdate()方法:

表单处理

当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model 会比较棘手:

假设这里的 obj 是在计算属性中返回的一个属于 Vuex store 的对象,在用户输入时,v-model 会试图直接修改 obj.message
在严格模式中,由于这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误

用 “Vuex 的思维” 去解决这个问题的方法是:

  • < input> 中绑定 value
  • 然后侦听 input 或者 change 事件,在事件回调中调用 action:

双向绑定的计算属性:

vuex的一些api

subscribe

subscribe(handler: Function): Function

订阅 store 的 mutation。handler 会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数:

要停止订阅,调用此方法返回的函数即可停止订阅。

通常用于插件。

subscribeAction

subscribeAction(handler: Function): Function

2.5.0 新增
订阅 store 的 action。handler 会在每个 action 分发的时候调用并接收 action 描述和当前的 store 的 state 这两个参数:

要停止订阅,调用此方法返回的函数即可停止订阅。

3.1.0 新增
从 3.1.0 起,subscribeAction 也可以指定订阅处理函数的被调用时机应该在一个 action 分发之前还是之后 (默认行为是之前):

该功能常用于插件。

watch

watch(fn: Function, callback: Function, options?: Object): Function
响应式地侦听 fn 的返回值,当值改变时调用回调函数。fn 接收 store 的 state 作为第一个参数,其 getter 作为第二个参数。最后接收一个可选的对象参数表示 Vue 的 vm.$watch 方法的参数。

要停止侦听,调用此方法返回的函数即可停止侦听。


文章 vuex 转载需要注明出处
喜欢 (0)

您必须 登录 才能发表评论!