vueX

VueX 才坑指南

1.不支持...mapActions([语法

解决方法很简单了,可以安装整个stage2的预置器或者安装 Object Rest Operator
的babel插件 babel-plugin-transform-object-rest-spread
配置文件添加
{ "presets": [ ["es2015"] ], "plugins": ["transform-object-rest-spread"]}

2.getters数据获得不到

export const getUsers = state => {
    //这里非常重要!!!!user表示模块名
    return state.user.users;
}
3.

1.什么是Vuex

是组件之间的状态管理器。

2.为什么??

look下面的图

vueX_第1张图片
Paste_Image.png

问题:
组件不能共享数据,如果共享只能通过引用父组件,导致状态有多个。代码失控

vueX_第2张图片
Paste_Image.png

3.demo1

// Make sure to call Vue.use(Vuex) first if using a module system

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})
//只能通过提交action来改变状态,因为统一,易读,方便控制
store.commit('increment')
console.log(store.state.count) // -> 1

4.State

解决了我一开始的疑问
Using Vuex doesn't mean you should put all the state in Vuex. Although putting more state into Vuex makes your state mutations more explicit and debuggable, sometimes it could also make the code more verbose and indirect.
整个应用只有一个状态树
问题1:如何把vuex的状态放在vue组件中
用computed

// let's create a Counter component
const Counter = {
  template: `
{{ count }}
`, computed: { count () { return store.state.count } } }

问题二:store的引用问题
Vue.use(Vuex)注入到所有的子组件中

const app = new Vue({
  el: '#app',
  // provide the store using the "store" option.
  // this will inject the store instance to all child components.
  store,
  components: { Counter },
  template: `
    
` }) //给父组件提供store //会自动注入到子 components // 直接使用this.$store const Counter = { template: `
{{ count }}
`, computed: { count () { return this.$store.state.count } } }

问题三:可能属性比较多,如上写法比较冗余和麻烦

// in standalone builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // arrow functions can make the code very succinct!
    count: state => state.count,

    // passing the string value 'count' is same as `state => state.count`
    countAlias: 'count',

    // to access local state with `this`, a normal function must be used
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
    computed: mapState([
        // map this.count to store.state.count
        'count'
    ])
  })
}

问题四:如果想合并其他来源的数据,利用ECMAScript语法

computed: {
  localComputed () { /* ... */ },
  // mix this into the outer object with the object spread operator
  ...mapState({
    // ...
  })
}

5.Getters

问题:如下所示,基于计算的属性,如果在多个地方用咋办,每个地方写,冗余

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

解决,利用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)
    }
  }
})

然后我们可以直接使用

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

可以接受两个参数

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

通4中的,我们可以用mapGetters来
simply maps store getters to local computed properties:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    // mix the getters into computed with object spread operator
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

6.Mutations

只能用mutation改变状态

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // mutate state
      state.count++
    }
  }
})
//提交
store.commit('increment')

如果想要传参??

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

另一种方式

store.commit({
  type: 'increment',
  amount: 10
})

增加状态,只能按照vue的方式

Use Vue.set(obj, 'newProp', 123)
或者直接来一个新的
state.obj = { ...state.obj, newProp: 123 }

增加常量方便操作

// 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: {
    // we can use the ES2015 computed property name feature
    // to use a constant as the function name
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

如何提条Mutation:
this.$store.commit('xxx') 或者 mapMutations

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment' // map this.increment() to this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // map this.add() to this.$store.commit('increment')
    })
  }
}

7.Actions

actions 提交mutations.
Actions 包含任意异步的操作

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

也可以用ECMAScript

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

Dispatching Actions
store.dispatch('increment')
一个异步操作的例子

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

// dispatch with a payload
store.dispatch('incrementAsync', {
  amount: 10
})

// dispatch with an object
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

购物车的例子

actions: {
  checkout ({ commit, state }, payload) {
    // save the items currently in the cart
    const savedCartItems = [...state.cart.added]
    // send out checkout request, and optimistically
    // clear the cart
    commit(types.CHECKOUT_REQUEST)
    // the shop API accepts a success callback and a failure callback
    shop.buyProducts(
      products,
      // handle success
      () => commit(types.CHECKOUT_SUCCESS),
      // handle failure
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

Dispatching Actions in Components

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // map this.increment() to this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // map this.add() to this.$store.dispatch('increment')
    })
  }
}

因为action是异步的,如何在异步结束后做处理??

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
Now you can do:

store.dispatch('actionA').then(() => {
  // ...
})
//可以在其他action中
actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

8.Modules

However, as our application grows in scale, the store can get really bloated.

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's state
store.state.b // -> moduleB's state

Module Local State

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment: (state) {
      // state is the local module state
      state.count++
    }
  },

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

context.state will expose the local state, and root state will be exposed as context.rootState
:

const moduleA = {
  // ...
  actions: {
    incrementIfOdd ({ state, commit }) {
      if (state.count % 2 === 1) {
        commit('increment')
      }
    }
  }
}

nside module getters, the root state will be exposed as their 3rd argument:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

Namespacing

// types.js

// define names of getters, actions and mutations as constants
// and they are prefixed by the module name `todos`
export const DONE_COUNT = 'todos/DONE_COUNT'
export const FETCH_ALL = 'todos/FETCH_ALL'
export const TOGGLE_DONE = 'todos/TOGGLE_DONE'
// modules/todos.js
import * as types from '../types'

// define getters, actions and mutations using prefixed names
const todosModule = {
  state: { todos: [] },

  getters: {
    [types.DONE_COUNT] (state) {
      // ...
    }
  },

  actions: {
    [types.FETCH_ALL] (context, payload) {
      // ...
    }
  },

  mutations: {
    [types.TOGGLE_DONE] (state, payload) {
      // ...
    }
  }
}

你可能感兴趣的:(vueX)