1、安装Vuex
a、vue之后直接引入vuex.js
b、npm安装:
npm install vuex --save
c、在一个模块化的打包系统中,你必须显式通过Vue.use()来安装
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
注:当使用全局script引入vuex时,不需要以上安装过程。而且vuex依赖Promise。如果浏览器没有实现Promise(IE)需要自己安装。
2、安装Promise
a、script引入:
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
b、npm安装:
npm install es6-promise --save
c、或者更近一步,将下列代码添加到你使用Vuex之前
import 'es6-promise/auto'
注:项目开发时,需要先通过npm安装依赖,在通过模块化引入
3、最简单的Store(仓库)
import Vue from 'vue'
import Vuex from "vuex"
Vue.use(Vuex);
const store=new Vuex.Store({
state:{
count:0
},
mutations:{
increment(state){
state.count++
}
}
});
//通过commit()可以触发函数
store.commit('increment');
console.log(store.state.count);//此时结果为1
Vuex 通过 store
选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)
):
const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
4、核心概念
- State(Vuex使用单一状态树)。
- Getter(可以认为是 store 的计算属性)
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)
}
}
})
Getter 会暴露为
store.getters
对象,你可以以属性的形式访问这些值:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
也可以通过方法访问:
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
- Mutation(类似于事件,但必须同步)
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
store.commit('increment')
向store.commit传入额外的参数
mutations: {
increment (state, n) {
state.count += n
}
}
/第一个参数为方法名,第二个是传入参数(也可以使用对象)
store.commit('increment', 10)
在组件中提交 Mutation
你可以在组件中使用 this.$store.commit('xxx')
提交 mutation,或者使用 mapMutations
辅助函数将组件中的 methods 映射为 store.commit
调用(需要在根节点注入 store
)。
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')`
})
}
}
- Action(类似于Mutaion,但可以提交异步):提交mutation,不是直接变更状态
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用
context.commit
提交一个 mutation,或者通过
context.state
和
context.getters
来获取 state 和 getters。
Action 通过
store.dispatch
方法触发:
store.dispatch('increment')
- Module:Vuex 允许我们将 store 分割成模块(module)
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 的状态 store.state.b // -> moduleB 的状态
5、项目结构
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
6、严格模式
strict:true(发布环境下不要启用严格模式)
7、表单处理
严格模式下
:
<input v-model="obj.message">会报错,
需要用Vuex的思维去处理;
给input绑定value,然后监听input或者change事件,在事件回调中调用action:
<input :value="message" @input="updateMessage">
computed: {
...mapState({
message: state => state.obj.message
})
},
methods: {
updateMessage (e) {
this.$store.commit('updateMessage', e.target.value)
}
}