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