Vuex 是适用于 Vue.js 应用的状态管理库,为应用中的所有组件提供集中式的状态存储与操作.

vuex管理数据的方式是用户界面触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上

应用级的状态集中放在store中,Vuex Store 具有关键的 5 个属性:state,actions,mutation,getters,modules.

npm i vuex --save后Vuex 中 Store 的模板化定义:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
  },
  actions: {
  },
  mutations: {
  },
  getters: {
  },  
  modules: {
    
  }
})
export default store

//或者
const mutations = {...};
const actions = {...};
const state = {...};

Vuex.Store({
  state,
  actions,
  mutation
});

State负责存储整个应用的状态数据,可使用this.$store.state获取状态

Mutations用于更改状态,本质是用来处理数据的函数,它是同步的

Actions也可以用于改变状态,可以包含异步操作;

有些状态需要做二次处理,就可以使用getters;

modules即模块

使用Mutation:

const mutations = {
  myMutation(state) {
    //在这里改变state中的数据
  }
}

//在一个组件中触发
export default {
  methods: {
    handleClick() {
      this.$store.commit('myMutation')
    }
  }
}
//或者使用辅助函数mapMutations直接将触发函数映射到methods上,这样就能在元素事件绑定上直接使用

import {mapMutations} from 'vuex'

//组件
export default {
  methods: mapMutations([
    'myMutation'
  ])
}

Getter,Action,state使用也是相似的:

//定义Actions
const actions = {
  actionName({ commit }) {
    //dosomething
    commit('mutationName')
  }
}
//在组件中使用,如果选择直接触发的话,使用this.$store.dispatch(actionName)方法
import {mapActions} from 'vuex'

//组件
export default {
  methods: mapActions([
    'actionName',
  ])
}
//state:对应的状态可以使用this.$store.state获取,也可用vuex提供的mapState辅助函数将state映射到计算属性中 //组件 import {mapState} from 'vuex' export default { computed: mapState({ count: state => state.count }) }
//getters:this.$store.getters.valueName对派生出来的状态进行访问。或使用辅助函数mapGetters将其映射到本地计算属性中 const getters = { strLength: state => state.aString.length//根据aString状态派生出了一个strLength状态 } import {mapGetters} from 'vuex' //组件 export default { computed: mapGetters([ 'strLength' ]) }

当我们使用module时,可以:

index.js写入:

import Vue from 'vue'
import Vuex from 'vuex'

import movie from './modules/movie'
import activities from './modules/activities'
import book from './modules/book'
import subject from './modules/subject'
import group from './modules/group'
import search from './modules/search'
import user from './modules/user'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    movie,
    activities,
    book,
    subject,
    group,
    search,
    user
  }
})

其中activities为:

import request from 'superagent'
import jsonp from 'superagent-jsonp'

const state = {
  events: [],
  temp: [],
  skip: 0,
  eventItem: {}
}

const mutations = {
  loadMore (state, payload) {
    state.skip += 3
    state.events = state.events.concat(payload.res)
  },
  getSingleEvent (state, payload) {
    state.eventItem = payload.res
  }
}

const actions = {
  /**
   * Loading more data
   * skip: 3 default
   * count: 3 default
   */
  loadMore ({commit, state}) {
    request
      .get('https://api.douban.com/v2/event/list?loc=108288&start=' +
        state.skip + '&count=3')
      .use(jsonp)
      .end((err, res) => {
        if (!err) {
          commit({
            type: 'loadMore',
            res: res.body.events
          })
        }
      })
  },
  /**
   * Getting single event
   * id: event id
   */
  getSingleEvent ({commit, state}, payload) {
    return new Promise((resolve, reject) => {
      request
        .get('https://api.douban.com/v2/event/' + payload.id)
        .use(jsonp)
        .end((err, res) => {
          if (!err) {
            commit({
              type: 'getSingleEvent',
              res: res.body
            })
            resolve(res)
          }
        })
    })
  }
}

export default {
  state,
  mutations,
  actions
}

在main.js  import store from './store'后即可在vue组件中使用:

<template>
  <div class="home-view has-header">
    <sub-nav mold="quickNav"></sub-nav>
    <list mold="thumbnail" :items="events"></list>
    <infinite-loading :on-infinite="onInfinite" ref="infiniteLoading">
      <loading slot="spinner"></loading>
    </infinite-loading>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex'

import InfiniteLoading from 'vue-infinite-loading'
import SubNav from '../components/SubNav'
import List from '../components/List'
import Loading from '../components/Loading'


export default {
  name: 'home-view',
  components: { SubNav, List, InfiniteLoading, Loading },
  data () {
    return {}
  },
  computed: {
    // Getting Vuex State from store/modules/activities
    ...mapState({
      events: state => state.activities.events
    })
  },
  methods: {
    // Using vue-infinite-loading
    onInfinite () {
      setTimeout(() => {
        this.loadMore()
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded')
      }, 1000)
    },
    // Dispatching Actions
    ...mapActions([
      'loadMore'
    ])
  }
}
</script>

<style lang="scss" scoped>
.sub-nav {
  margin: 0 1.8rem;
  padding-top: 0.2rem;
}
</style>

 

 参考https://vuex.vuejs.org/en/modules.html

示例代码:https://github.com/lanleilin/myHomepage