码迷,mamicode.com
首页 > 其他好文 > 详细

vuex 的使用

时间:2017-12-09 00:02:21      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:text   product   没有   文件太大   linq   常见   main   改变   mod   

技术分享图片

用于多组件共享状态,如果不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果应用够简单,您最好不要使用 Vuex。可使用简单Bus总线的方式来管理共享的数据详见(http://www.cnblogs.com/fanlinqiang/p/7756566.html)。但是,如果您需要构建是一个中大型单页应用,vuex可以更好地在组件外部管理状态

引入:

src/store/index.js

import Vue from ‘vue‘
import Vuex from ‘vuex‘
import createLogger from ‘vuex/dist/logger‘

Vue.use(Vuex)


const store = new Vuex.Store({
      plugins: [createLogger()]
      state: {
        count: 0,
        todos: [
          { id: 1, text: ‘...‘, done: true },
          { id: 2, text: ‘...‘, done: false }
        ]
      },
      getters: {
        doneTodos: state => {
          return state.todos.filter(todo => todo.done)
        },
        doneTodosCount: (state, getters) => { //Getter 也可以接受其他 getter 作为第二个参数
            return getters.doneTodos.length
        },
        getTodoById: (state) => (id) => { //getter 返回一个函数来实现给 getter 传参
            return state.todos.find(todo => todo.id === id)
        }
      },
      mutations: { //mutation 必须同步执行,为解决这个问题我们引入了action
       increment (state, payload) { //store.commit 传入额外的参数,即 mutation 的 载荷(payload)         
             state.count += payload.amount
          }
      },
      actions: {
        //Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
        //因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
        increment (context) {
          context.commit(‘increment‘)
        },
        increment ({ commit }) { //es6解构
            commit(‘increment‘)
        },
        incrementAsync ({ commit }) {
            setTimeout(() => {
              commit(‘increment‘)
            }, 1000)
        },
        //store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
        actionA ({ commit }) {
            return new Promise((resolve, reject) => {
              setTimeout(() => {
                commit(‘someMutation‘)
                resolve()
              }, 1000)
            })
          },
        actionB ({ dispatch, commit }) {
            return dispatch(‘actionA‘).then(() => {
              commit(‘someOtherMutation‘)
            })
          }
        // 假设 getData() 和 getOtherData() 返回的是 Promise
        async actionA ({ commit }) {
            commit(‘gotData‘, await getData())
          },
        async actionB ({ dispatch, commit }) {
            await dispatch(‘actionA‘) // 等待 actionA 完成
            commit(‘gotOtherData‘, await getOtherData())
         }
      }
})

export default store

最好提前在你的 store 中初始化好所有所需属性。当需要在对象上添加新属性时,你应该使用 Vue.set(obj, ‘newProp‘, 123), 或者
以新对象替换老对象。例如,利用 stage-3 的对象展开运算符我们可以这样写:

state.obj = { ...state.obj, newProp: 123 }

 

组件a:

import { mapState, mapActions, mapMutations } from ‘vuex‘

export default {
    data() {
        return {}
    },    
    methods:{
        getTodoById(id) {
            return  this.$store.getters.getTodoById(id)
        },
        increment(payload)(){ //payload可以为对象,如:{ amount: 10}
            this.$store.commit(‘increment‘, payload)
            //对象风格的提交方式
            //this.$store.commit({type: ‘increment‘,amount: 10})
        },
        ...mapMutations([ 
            //mutation 都是同步事务,store.commit(‘increment‘), 任何由 "increment" 导致的状态变更都应该在此刻完成。
            //为解决异步问题我们引入action
            ‘increment‘, // 将 `this.increment()` 映射为 `this.$store.commit(‘increment‘)`
            //add: ‘increment‘ // 将 `this.add()` 映射为 `this.$store.commit(‘increment‘)`
            // `mapMutations` 也支持载荷:
            ‘incrementBy‘ // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit(‘incrementBy‘, amount)`
        ]),
        ...mapActions([
          ‘increment‘, // 将 `this.increment()` 映射为 `this.$store.dispatch(‘increment‘)`
          //add: ‘increment‘ // 将 `this.add()` 映射为 `this.$store.dispatch(‘increment‘)`
          // `mapActions` 也支持载荷:
          ‘incrementBy‘ // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch(‘incrementBy‘, amount)`
        ]),
        actionA() {
            store.dispatch(‘actionA‘).then(() => {
              // ...
            })
        }        
    },
    computed:{
        //count () {
        //  return this.$store.state.count
        //}         
        ...mapState({ // 使用对象展开运算符将此对象混入到外部对象中
            // 箭头函数可使代码更简练
            count: state => state.count,

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

            // 为了能够使用 `this` 获取局部状态,必须使用常规函数
            countPlusLocalState (state) {
              return state.count + this.localCount
            }
          }),
          
        doneTodosCount () {
            return this.$store.state.todos.filter(todo => todo.done).length
          },
        DoneTodos(){
            return this.$store.getters.doneTodos
        },
        getDoneTodosCount () {
            return this.$store.getters.doneTodosCount
        },
        // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapGetters([
          ‘doneTodosCount‘,
            //映射 `this.doneCount` 为 `store.getters.doneTodosCount`
            doneCount: ‘doneTodosCount‘
        ])        
    }    
}

 

main.js

import Vue from ‘vue‘
import store from ‘./store/‘

new Vue({
  store
}).$mount(‘#app‘)

 

使用常量替代 Mutation 事件类型

使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然:

// mutation-types.js
export const SOME_MUTATION = ‘SOME_MUTATION‘
// store.js
import Vuex from ‘vuex‘
import { SOME_MUTATION } from ‘./mutation-types‘

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

 

Mutation 必须是同步函数

一条重要的原则就是要记住 mutation 必须是同步函数。为什么?请参考下面的例子:

mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}

 

现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的的状态的改变都是不可追踪的。

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  1. 应用层级的状态应该集中到单个 store 对象中。

  2. 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。

  3. 异步逻辑都应该封装到 action 里面。

只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

 

vuex 的使用

标签:text   product   没有   文件太大   linq   常见   main   改变   mod   

原文地址:http://www.cnblogs.com/fanlinqiang/p/8007317.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!