什么时候使用 vuex? 下面本篇文章给大家介绍一下. 有一定的参考价值, 有需要的朋友可以参考一下, 希望对大家有所帮助.
组件通信
在使用 Vue 进行组件化开发这个. 组件通信是一个十分重要的部分.
应用在组件化之后, 组件之间必然存在某种联系; 组件化意味着协同工作, 通常存在着 父子组件, 兄弟组件, 跨级组件 等组件关系, 那么组件之间如何进行协调工作, 即组件通信;
在 Vue 中, 父子组件的关系可以总结为 props down,events up.
父子组件通信: 父组件通过 props 向下传递数据给子组件
子父组件通信: 子组件通过 events 给父组件发送消息
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
非父子组件通信: 使用一个空的 Vue 实例作为中央事件总线
父子, 子父 组件之间的通信是很轻松的, 通过 props 和 events 即可实现; 但是往往我们的应用可能不只有这么简单的层级关系, 在多层跨级组件如果通过 props 去传递, 那意味着一层一层的往子组件传递, 最终你可能不知道当前组件的数据最终来自哪个父组件(当然你可以逆着方向一层一层往上找), 通过 events 事件机制显然也存在着类似的问题. 如果你觉得这样也可以接受, 你可能不需要 Vuex; 但如果你在想有没有什么好的模式优雅的去解决, 你可以继续阅读下面的部分.
状态管理
随着 JavaScript 单页应用开发日趋复杂, JavaScript 需要管理比任何时候都要多的 state (状态). 这些 state 可能包括服务器响应, 缓存数据, 本地生成尚未持久化到服务器的数据, 也包括 UI 状态, 如激活的路由, 被选中的标签, 是否显示加载动效或者分页器等等.
管理不断变化的 state 非常困难. 如果一个 model 的变化会引起另一个 model 变化, 那么当 view 变化时, 就可能引起对应 model 以及另一个 model 的变化, 依次地, 可能会引起另一个 view 的变化. 直至你搞不清楚到底发生了什么. state 在什么时候, 由于什么原因, 如何变化已然不受控制. 当系统变得错综复杂的时候, 想重现问题或者添加新功能就会变得举步维艰.
-- 摘自《Redux 中文文档》
Vuex 是一个专为 vue.js 应用程序开发的状态管理模式. 它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化.
-- from vuex docs
在应用中, 组件之间的通信其实是归根于应用的状态管理; 而应用的状态是来自多方面的, 如何对状态进行管理, 提高代码的可维护性, 提升开发效率. Vue 的核心库只关注视图层, 单文件组件, 其模板, 逻辑和样式是内部耦合的, 侧重数据和视图的同步; Vue 本身并没有对数据状态的管理进行处理, 但其提供了另外一个解决方案 Vuex, 一个集中式状态管理的库; 也就是说, 你可能不需要 Vuex, 它只是对你应用状态进行管理的一个库.
Vuex 状态自管理应用包含以下几个部分:
state, 驱动应用的数据源;
view, 以声明方式将 state 映射到视图;
actions, 响应在 view 上的用户输入导致的状态变化.
如上图, Vuex 为 Vue Components 建立起了一个完整的生态圈, 包括开发中的 API 调用一环. 围绕这个生态圈, 简要介绍一下各模块在核心流程中的主要功能:
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 对象.
集中式状态管理的好处
相对于分治 (碎片化) 的状态管理, 多个状态分散的跨越在不同组件交互在各个角落, 每个 View 会有相对应的 Model 维护状态; 而集中式管理模式则用于将分散于组件的状进行集中化管理, 提供一个全局的 store 存储管理应用的状态. 集中式的状态管理可以让整体的状态变化更加明晰, 尤其是配合各自的 devtools.
什么情况下我应该使用 Vuex?
虽然 Vuex 可以帮助我们管理共享状态, 但也附带了更多的概念和框架. 这需要对短期和长期效益进行权衡.
如果您不打算开发大型单页应用, 使用 Vuex 可能是繁琐冗余的. 确实是如此 -- 如果您的应用够简单, 您最好不要使用 Vuex. 一个简单的 global event bus 就足够您所需了. 但是, 如果您需要构建是一个中大型单页应用, 您很可能会考虑如何更好地在组件外部管理状态, Vuex 将会成为自然而然的选择.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
通俗版使用
- import Vue from 'vue';
- import Vuex from 'vuex';
- Vue.use(Vuex);
- const store = new Vuex.Store({
- state: { count: 0 },
- mutations: {
- increment (state) {
- state.count++
- }
- }
- })
以上就是一个最简单的 Vuex, 每一个 Vuex 应用就是一个 store, 在 store 中包含组件中的共享状态 state 和改变状态的方法(暂且称作方法)mutations.
vuex 的核心是: state,getter,actions,mutations
1,state
state 就是根据你项目的需求, 自己定义的一个数据结构, 里面可以放些通用的状态.
- const state = {
- openId:"",
- storeId:"",
- storeName:''
- }
例如上面所写的, 这些状态可以在各个页面通过 vuex 访问. 如下:
this.$store.state.openId = "111"
之前我一直通过上面的方式来修改 state 里面的状态值, 行, 肯定能用, 但是好像官方并不建议我们这样使用, 而是建议使用 mutations 来改变 state 里面的值, 因为不通过 mutations 改变 state, 状态不会被同步. 至于 mutations 下面会讲到.
2,getter
getter 怎么理解呢? 通俗的理解可以认为是 getter 里的函数就是 vuex 里的计算属性, 类似于 computed 函数.
- const store = new Vuex.Store({
- state: {
- count: 0
- },
- getters: { // getters
- countAdd: function (state) {
- return state.count++
- }
- },
- mutations: {
- increment (state) {
- state.count++
- }
- }
- })
getter 函数怎么用呢? 如上 vuex 里定义了一个 getter 函数 countAdd. 我们可以在 vue 文件里的 computed 计算属性里引用, 如下.
- computed: {
- ...mapGetters{["countAdd"]}
- show:function(){
- alert("这个是测试页面")
- }
- }
这样我们可以直接在 vue 页面里取到 countAdd 的值 {{countAdd}} 即为 1. 可惜在我的项目里目前还没用到 getter, 可能写的少了, 还没理解其中的要义.
3,mutations
官方定义: 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation.Vuex 中的 mutations 非常类似于事件: 每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler). 这个回调函数就是我们实际进行状态更改的地方, 并且它会接受 state 作为第一个参数:
- const store = new Vuex.Store({
- state: {
- count: 1
- },
- mutations: {
- increment (state) {
- // 变更状态
- state.count++
- }
- }
- })
你不能直接调用一个 mutation handler. 这个选项更像是事件注册:"当触发一个类型为 increment 的 mutation 时, 调用此函数." 要唤醒一个 mutation handler, 你需要以相应的 type 调用 store.commit 方法:
store.commit('increment')
也可以向 store.commit 传入第二参数, 也就是 mutation 的 payload:
- mutaion: {
- increment (state, n) {
- state.count += n;
- }
- }
- store.commit('increment', 10);
但是有时候, 单个传入 n 可能并不能满足我们的业务需要, 这时候我们可以选择传入一个 payload 对象:
- mutation: {
- increment (state, payload) {
- state.totalPrice += payload.price + payload.count;
- }
- }
- store.commit({
- type: 'increment',
- price: 10,
- count: 8
- })
不例外, mutations 也有映射函数 mapMutations, 帮助我们简化代码, 使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用.
- import { mapMutations } from 'vuex'
- export default {
- methods: {
- ...mapMutations({
- add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
- })
- }
- }
这样我们可以在 vue 文件里直接调用函数: this.add()而不用 this.$store.commit('increment')这样写了, 简化了很多.
需要注意: Mutations 必须是同步函数.
如果我们需要异步操作, Mutations 就不能满足我们需求了, 这时候我们就需要 Actions 了.
4,action
Action 类似于 mutation, 不同在于:
Action 提交的是 mutation, 而不是直接变更状态.
Action 可以包含任意异步操作.
官方 demo 如下:
- const store = new Vuex.Store({
- state: {
- count: 0
- },
- mutations: {
- increment (state) {
- state.count++
- }
- },
- actions: {
- increment (context) {
- context.commit('increment')
- }
- }
- })
如果我在 vue 页面里想用 action, 我们可以分发 Action,Action 通过 store.dispatch 方法触发:
store.dispatch('increment')
Actions 支持同样的载荷方式和对象方式进行分发:
- // 以载荷形式分发
- store.dispatch('incrementAsync', {
- amount: 10
- })
- // 以对象形式分发
- store.dispatch({
- type: 'incrementAsync',
- amount: 10
- })
我们也可以运用其映射函数: mapActions
- methods:{
- ...mapActions{[
- "add":"increment"// 函数命名不相同
- // "increment":"increment"// 函数命名相同
- ]}
- }
调用: this.add()即可. 相同时候调用: this.increment()
Modules
由于使用单一状态树, 应用的所有状态会集中到一个比较大的对象. 当应用变得非常复杂时, store 对象就有可能变得相当臃肿.
为了解决以上问题, Vuex 允许我们将 store 分割成模块(module). 每个模块拥有自己的 state,mutation,action,getter, 甚至是嵌套子模块 -- 从上至下进行同样方式的分割:
- const moduleA = {
- state: { ... },
- mutations: { ... },
- actions: { ... },
- getters: { ... }
- }
- const moduleB = {
- state: { ... },
- mutations: { ... },
- actions: { ... }
- }
- const store = new Vuex.Store({
- modules: {
- a: moduleA,
- b: moduleB
- }
- })
- store.state.a // -> moduleA 的状态
- store.state.b // -> moduleB 的状态
总结起来: mutation 只管存, 你给我 (dispatch) 我就存; action 只管中间处理, 处理完我就给你, 你怎么存我不管(所有的改变 state 状态的都是 mutation 来操作);Getter 我只管取, 我不改的(类似计算属性).
关于 vuex 目前也就了解这么多, 在实际项目中 vuex 用什么, 怎么用, 还需要灵活改变, 以后慢慢摸索吧. 上面的示例很多都是 vuex 文档上的, 总结起来还是需要多看文档, 在实际项目中运用, 才是最好的办法吧.
更多 web 前端开发 https://www.html.cn/ 知识, 请查阅 HTML 中文网 !!
来源: http://www.css88.com/qa/vue-js/17881.html