大型单页面应用需要Vuex管理全局/模块的状态,大型单页面组件如果靠事件(events)/属性(props)通讯传值会把各个组件耦合在一起。
快速入门
- 安装vuex库
cnpm install -S vuex
- 创建Vuex.Store
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
//组件数据源,单一的state属性
state: {
clickCount: 0
},
//相当于属性,封装获取state
getters: {
getClickCount: state => {
return state.clickCount;
}
},
//封装引起状态变化的方法
mutations: {
increment(state) {
state.clickCount++;
}
},
//类似于 mutation,不同在于actions支持异步,不是直接变更状态,而是提交到mutation
actions: {
increment(context) {
context.commit('increment')
},
async incrementAsync({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
commit('increment');
resolve(new Date().getTime() + ' 成功执行');
} catch (e) {
reject(e);
}
}, 1000)
});
}
}
});
export default store;
- Vue实例加入store
new Vue({
router: router,
store: store,
render: h => h(App),
}).$mount('#app')
- 组件获取store值
<script>
import { mapGetters } from "vuex";
export default {
computed: mapGetters({ count: ["getClickCount"] }),
};
</script>
- 组件触发更新
<script>
export default {
data() {
return { times: 0 };
},
methods: {
increment() {
this.times++;
//分发到action
this.$store.dispatch("incrementAsync");
//提交到mutations
this.$store.commit("increment");
},
},
};
</script>
解析
Vuex 是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
State - 数据源
Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。
Vue通过store选项,调用Vue.use(Vuex)注入到每一个子组件中(类似路由)
组件获取State
computed: {
count () {
return this.$store.state.count
}
}
或者使用辅助函数mapState
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count
})
Getter - 数据封装读取(类似属性)
Getter 接受 state 作为其第一个参数
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
通过属性访问
store.getters.doneTodos
通过方法访问
store.getters.getTodoById(2)
Getters 也提供了一个辅助函数方便访问(mapGetters )
Mutation - 进行状态更改的地方
定义Mutation
mutations: {
increment (state, n) {
state.count += n
}
}
组件触发变更
store.commit('increment', 1)
Mutations也提供辅助函数(mapMutations)
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
注意事项
- Mutation 必须是同步函数
- 最好提前在你的 store 中初始化好所有所需属性。
- 需要在对象上添加新属性时使用 Vue.set 或 替换旧对象
Action - 对Mutation封装
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
定义Action
actions: {
increment ({ commit }) {
commit('increment')
}
}
组件分发Action
store.dispatch('increment')
支持异步方式分发
actions: {
async incrementAsync({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
commit('increment');
resolve(new Date().getTime() + ' 成功执行');
} catch (e) {
reject(e);
}
}, 1000)
});
}
}
组件调用异步分发
this.$store.dispatch("incrementAsync").then(
(data) => {
console.log(data);
},
(err) => {
console.log(err);
}
);
网友评论