初步学习Vuex

栏目: JavaScript · 发布时间: 5年前

内容简介:vuex是专门为vue.js开发的状态管理模式,它将所有组件的状态集中的存储在一起,并且用相应的规则使这些状态以一种可预测的方式发生改变。前面说到vuex是专门为vue.js开发的状态管理模式,那么究竟什么是“状态管理模式”呢? 以我目前对状态的理解就是组件在某个时刻呈现出的视图、数据的状态。在vue的项目开发中我们经常会遇到多个组件共享某个状态。即:多个视图依赖同一组件 或者 不同视图的行为需要改变同一状态。对于这种情况父子组件之前通过props进行传参是很繁琐的,同时兄弟组件是没办法做到的。并且不同视图

vuex是专门为vue.js开发的状态管理模式,它将所有组件的状态集中的存储在一起,并且用相应的规则使这些状态以一种可预测的方式发生改变。

vuex是做什么用的

前面说到vuex是专门为vue.js开发的状态管理模式,那么究竟什么是“状态管理模式”呢? 以我目前对状态的理解就是组件在某个时刻呈现出的视图、数据的状态。在vue的项目开发中我们经常会遇到多个组件共享某个状态。即:多个视图依赖同一组件 或者 不同视图的行为需要改变同一状态。

对于这种情况父子组件之前通过props进行传参是很繁琐的,同时兄弟组件是没办法做到的。并且不同视图之间只能通过事件触发或直接引用的方式传递数据。这显然是很麻烦的。

因此就有了vuex,他将组件的所有状态抽离出来,存储在全局的一个仓库里,这样不管组件在哪个位置都可以获取到状态或者触发行为。vuex就像一个巨大的仓库一样可以为我们存储着所有组件的状态和改变状态的行为,同时维持着视图和状态之间的独立性,使得代码变得结构更加清晰且易维护。

vuex要如何使用

  • 首先安装vuex
npm install vuex --save
  • 引入vuex
import Vuex from 'vuex'  vue.use(Vuex)
  • 创建一个 store,仅需要提供一个初始 state 对象和一些 mutation:
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})
复制代码
  • 获取状态对象
// 创建一个 Counter 组件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}
复制代码

由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态

  • 通过 store.commit 方法触发状态变更:
store.commit('increment')
复制代码

注意:改变状态的唯一方式就是通过commit提交mutation

  • mapState 辅助函数

    当组件获取多个状态时,为了避免因将状态声明为计算属性而是代码重复冗余,我们可以使用mapState辅助函数

//引入mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}
复制代码

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])
复制代码
  • vuex中的Getter

    Getter相当于vuex中的计算属性,是对一些状态的操作(如果一些状态的操作会被多次使用不妨将他们写入Getter中调用),当他所依赖的状态发生改变的时候,Getter返回的值也会发生相应的变化。

//Getter 接受 state 作为其第一个参数,接受其他 getter 作为第二个参数:
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})
复制代码

通过属性访问Getter

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
复制代码
  • mapGetters 辅助函数

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

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}
复制代码
  • Vuex 中的 mutation

    vuex中的mutation类似于事件,每个mutation都由代表此事件的名称(type)和回调函数两部分组成,回调函数中就是进行状态更改的地方,在大型项目中为了使整个 app 包含的 mutation 一目了然,通常会使用常量替代 Mutation 事件类型,将这些常量单独写在一个.js文件中。 Mutation 必须是同步函数,若要进行异步操作可以将其写在action中

//它会接受 state 作为第一个参数:
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})
复制代码
  • 提交载荷(Payload)

    你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)大多数时候载荷是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

两种提交方式

//方式一
store.commit('increment', {
  amount: 10
})
*******
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
//方式二  ——对象风格的提交方式
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
*******
store.commit({
  type: 'increment',
  amount: 10
})
复制代码
  • vuex中的Action

    Action 类似于 mutation,不同在于:

  1. Action 提交的是 mutation,而不是直接变更状态。
  2. Action 可以包含任意异步操作。

注册一个简单的action

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  //action接受一个和store有相同属性和方法的context 对象
  //因此你可以调用 context.commit 提交一个 mutation
  //通过 context.state 和 context.getters 来获取 state 和 getters
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
复制代码
  • 触发Action
store.dispatch('increment')

// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
复制代码
  • 在组件中分发 Action
import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}
复制代码
  • 组合 Action
  • store.dispatch可以处理action返回的promise,并且 store.dispatch 仍旧返回 Promise:
store.dispatch('actionA').then(() => {
  // 处理Action返回的promise
})
复制代码
  • 使用async / await时,组合Action
// 假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}
复制代码
  • vuex中的module

    如果将每个组建的状态,都放在同一个store中,那么整个store会变得很臃肿,所以vuex提供了module这个属性,使得每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
复制代码
  • 命名空间

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

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模块内容(module assets)
      state: { ... }, // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: { ... },
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: { ... },
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

离心力:互联网历史与数字化未来

离心力:互联网历史与数字化未来

[英] 乔尼·赖安(Johnny Ryan) / 段铁铮 / 译言·东西文库/电子工业出版社 / 2018-2-1 / 68.00元

★一部详实、严谨的互联网史著作; ★哈佛、斯坦福等高校学生必读书目; ★《互联网的未来》作者乔纳森·L. 齐特雷恩,《独立报》《爱尔兰时报》等知名作者和国外媒体联合推荐。 【内容简介】 虽然互联网从诞生至今,不过是五六十年,但我们已然有必要整理其丰富的历史。未来的数字世界不仅取决于我 们的设想,也取决于它的发展历程,以及互联网伟大先驱们的理想和信念。 本书作者乔尼· ......一起来看看 《离心力:互联网历史与数字化未来》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码