文章目录
Vuex 是什么
Vuex是什么javascript
- 一个专为
Vue.js
应用程序开发的响应式状态管理模式.
状态管理是什么?
从我我的角度来看,状态能够指代数据。而状态管理也就能够看做数据管理,主要是用于分层解耦。html
在Vuex
中状态管理能够看做是全局变量,这个变量能够经过state
取出变量映射到view
中,也能够根据用户的输入actions
改变该变量vue
响应式是什么?
从我我的角度来看,响应式就是自适应。java
在Vuex
中响应式是指数据(状态)的改变可以及时的全部数据变动为最新的数据。git
不用 Vuex 也是能够的
- 从父组件一层一层将数据传递给子组件(麻烦)
- 经过 EventBus 的订阅/发布模式实现数据数据传递
可看这篇文章介绍:什么状况下我应该使用 Vuexgithub
使用
安装
npm 安装web
npm install vuex --save
知识储备
全局 store
参考:shoppint-cart 示例
在 store
目录下建立index.js
vuex
import Vue from 'vue' import Vuex from 'vuex' import cart from './modules/cart' import products from './modules/products' import createLogger from '../../../src/plugins/logger' Vue.use(Vuex) const debug = process.env.NODE_ENV !== 'production' export default new Vuex.Store({ // 注入其它模块的 store modules: { cart, products }, strict: debug, plugins: debug ? [createLogger()] : [] })
在app.js
中注入store
,如:npm
import Vue from 'vue' import App from './components/App.vue' import store from './store' import { currency } from './currency' Vue.filter('currency', currency) new Vue({ el: '#app', store, // 全局注入 render: h => h(App) })
如在counter
组件中经过this.$store
去使用缓存
this.$store.commit('increment')
State
用于声明数据。
computed 计算属性
对于任何复杂逻辑,你都应当使用计算属性。
例以下面的示例中,第二个 message ,若是咱们要在 view 中写也是能够,可是会比较复杂,以下:
<p>Computed reversed message: "{ { message.split('').reverse().join('') }}"</p>
那么咱们能够将该复杂写法经过计算属性
封装成一个方法,直接调用该方法对象
便可。
示例:
<div id="example"> <p>Original message: "{ { message }}"</p> <p>Computed reversed message: "{ { reversedMessage }}"</p> <!-- 在 Vuex 中若是不用计算属性,咱们须要这么写 --> <p>Computed reversed message: "{ { this.$store.state.counter.message.split('').reverse().join('') }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 // 使用 vuex 则可经过 $store 取到数据以后再转换,以下 // return this.$store.state.counter.message.split('').reverse().join('') return this.message.split('').reverse().join('') } } }) 输出结果: Original message: "Hello" Computed reversed message: "olleH"
mapState 辅助函数
当一个组件须要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,咱们可使用
mapState
辅助函数帮助咱们生成计算属性。
辅助函数,用于简化this.$store.state
,示例以下:
<template> <div> <!-- 直接使用 --> Clicked: { { $store.state.counter.count }} times. <br> <!-- 使用 Vuex mapState --> mapState使用: { { count }} times. </div> </template> <script> // 在单独构建的版本中辅助函数为 Vuex.mapState import { mapState } from 'vuex' export default { computed:{ ...mapState({ count: state => state.counter.count }), }, methods: { } } </script>
有时候咱们须要从 store
中的 state
中派生出一些状态。
如上面的字符串反转功能就是派生出来的,咱们可使用Getters
去实现。
Getters
能够认为是
store
的计算属性。getter
的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。
经过一个示例来看一下getters
如何使用。
Counter.vue
文件以下:
<template> <div> <p>hello 字符串反转:{ { reverseStr }}</p> <p>getter 获取 todo done: { { doneTodosCount }}</p> <p>传入 getters 作参数:{ { doneTodosCount }}</p> <p>直接访问:{ { doneTodos }}</p> </div> </template> <script> // 在单独构建的版本中辅助函数为 Vuex.mapGetters import { mapGetters } from "vuex"; export default { computed: { // 因为使用了命名空间,所以须要加上,不然获取反转的字符串如: reverseStr:'counter/reverseStr' ...mapGetters('counter',{ reverseStr: "reverseStr", doneTodosCount: "doneTodosCount", doneTodos: "doneTodos", }), }, }; </script>
counter.js
文件以下:
const state = () => ({ message: 'hello', todos: [{ id: 1, text: '写日报', done: true }, { id: 2, text: '看一篇英文文章', done: false } ] }) // getters const getters = { doneTodos: state => { return state.todos.filter(todo => todo.done) }, doneTodosCount: (state, getters) => { // 传入 getters 作参数 return getters.doneTodos.length }, reverseStr: state => { return state.message.split('').reverse().join('') } } export default { namespaced: true, state, getters, }
Mutations
经过提交 mutation
的方式,而非直接改变 store.state.count
。
其实也就是经过方法的方式去操做数据。并且Mutation
必须是同步函数,若是是异步函数请使用下一节的Action
看个示例:每次点击increment
文本+2,每次点击decrement
文本-2
Counter.vue
文件以下
<template> <div> <p @click="mIncrement">mutations 获取 increment: { { mutationsCount }}</p> <p @click="mDecrement">mutations 获取 decrement: { { mutationsCount }}</p> </div> </template> <script> // 在单独构建的版本中辅助函数为 Vuex.mapState import { mapState } from "vuex"; export default { computed: { ...mapState({ count: (state) => state.counter.count, mutationsCount: (state) => state.counter.mutationsCount, }), }, methods: { mIncrement() { this.$store.commit("counter/mIncrement",2); }, mDecrement() { this.$store.commit("counter/mDecrement",{ amount:2 }); }, }, }; </script>
counter.js
以下:
const state = () => ({ mutationsCount:0, }) const mutations = { mIncrement(state, n) { state.mutationsCount += n }, // 经过对象传递 mDecrement(state,payload) { state.mutationsCount -= payload.amount }, } export default { namespaced: true, state, mutations }
Actions
Action
相似于 mutation
,不一样在于:
Action
提交的是mutation
,而不是直接变动状态。Action
能够包含任意异步操做。
counter
计数器示例:
Counter.vue
文件以下:
<template> <div> Clicked: { { $store.state.counter.count }} times. <br /> <button @click="increment">+</button> <button @click="decrement">-</button> </div> </template> <script> // 在单独构建的版本中辅助函数为 Vuex.mapState import { mapState, mapGetters } from "vuex"; export default { computed: { ...mapState({ count: (state) => state.counter.count, }), }, methods: { increment() { this.$store.dispatch("counter/increment"); }, decrement() { this.$store.dispatch("counter/decrement"); }, }, }; </script>
counter.js
文件以下:
const state = () => ({ count: 0, }) const mutations = { increment(state) { state.count++ }, decrement(state) { state.count-- }, } const actions = { increment: ({ commit }) => commit('increment'), decrement: ({ commit }) => commit('decrement'), } export default { namespaced: true, state, actions, mutations }
Modules
也就是分模块。
例如Counter
组件,在 store/modules
下建立counter.js
用于处理store
相关的数据,而Counter.vue
组件页面就正常写便可。
接着在store/
目录下的 index.js
添加 module
的注入。具体可看上文的store
全局注入。
购物车示例
对照上面的分析,你能够很容易看懂Vuex examples 中的 shoppint-cart
示例了
shoppint-cart 示例地址
该示例是经过shop.js
模拟数据,而后将products 和 cart
组件注入全局 store
而后ProductList.vue
展现shop.js
中的商品列表,而ShoppingCart.vue
展现购物车数据。
END~
本文同步分享在 博客“_龙衣”(CSDN)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。