背景:
vue2.x项目组件工程化数据的层层传递太麻烦。如下图:内层的在家呢需要父组件的数据需要一层一层地传递,组件加载数据到父组件的时候需要一层一层回递,这样加重页面的负担。所以推出vuex状态管理来统一分发和部署。把组件中的状态抽取出来,放入Vuex进行统一管理。
这样他们就变成一级关系:
vuex其实是一种套路(学会运行机制就ok)
官网:
网址:
vuex.vuejs.org/zh/installa…
手画图解:
需求:
取数据:
1.components(组件)把数据取出来渲染到界面上、改变里面的数据。
2.全局注册后, $state.state直接取数据或者放到map里面再去取。
改数据:
1.dispath()方法触发actions,叫action改数据,但是action没有权限改,只能向上级(mutations)汇报,通过commit()提交。并且actions里面的行为和mutamutions的行为要一至。
2. 为了防止出错,统一常量(mutation-types)约束,用到方法就调用相对应的常量。
3. actions提交过来,通过commit()触发mutamutions,然后更新状态。
数据的单独处理getters:
例如state里面有价格的处理,过滤器过滤后变成单独的功能放到getters里面封装成一个get方法,然后组件上$state.getters直接调用。
准备工作:
vue项目中新建相对应的文件。如下图:
安装vuex:cmd
npm install vuex --save
引入使用:store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue use(Vuex);
对外暴露vuex和引入相对应的文件:store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
import state from './state';
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
getters,
actions
})
这里的Store的s要大写
要不会报错:TypeError: WEBPACK_IMPORTED_MODULE_1_vuex.a.store is not a constructor
这个报错的是_vuex2.default.store 不是一个构造函数因为在我们用vuex的时候需要将用到的actions,mutations模块最终导出,在导出的时候new Vuex.Store中的Store小写了,这里的一定要大写,就相当于我们在使用构造函数(类)的时候首字母要大写
全局使用vuex
全局注册:main.js
import store from './store';
/* eslint-disable no-new */
new Vue({
el: '#app',
store, //挂载
render: h => h(App)
// components: { App },
// template: '<App/>'
});
**实际应用:**现在有一段数据,不属于如何的组件,vuex进行状态管理,数据谁要谁一级直接拿,不用组件的一级一级的传递。vuex实现数据的添加功能。
数据的存放(任何类型):store/state.js
// 存放所有的状态,唯一的数据源
export default {
todos: [
{title:'坐下来好好聊聊天', finished: false},
{title:'和你一起的旅游', finished: false},
{title:'回家熬夜敲代码', finished: true},
]
}
App.vue:
<template>
<div class="">
</div>
</template>
<script>
import Header from './components/xxx/xxx'
export default {
name: "App",
data(){
return {
//store/state.js
}
},
components:{
xxx
},
methods:{
// 插入一条记录
addTodo(todo){
this.todos.unshift(todo);
},
//清空所有
delFinishedTodos(){
//filter方法
this.todos = this.todos.filter(todo => !todo.finished)
}
}
}
</script>
<style scoped>
</style>
components/xxx.vue:
<template>
<div>
<input type="text"
placeholder="请输入今天的任务清单,按回车键确认"
v-model="title"
@keyup.enter="addItem" />
</div>
</template>
<script>
export default{
name:"xxx",
props:{
addTodo:Function
},
data(){
return{
title:''
}
},
methods:{
addItem(){
//判断是否合理
const title = this.title.trim(); //清空所有的输入空格
if(!title){
alert('请输入内容不能为空');
return;
}
//生成todo对象
const todo = {title,finshed: false};
//调用方法
// this.addTodo(todo);
this.$store.dispatch('addTodo',todo);
//清空输入
this.title = ''
}
}
}
</script>
<style scoped>
</style>
组件的调用数据的方法:components/xxx.vue
this.$store.dispatch('addTodo',todo);
实现方法:store/actions.js
// 行为更新所有的状态
import {ADD_TODO
} from './mutations-types'
export default {
//添加一条记录到mutations
addTodo({commit},todo){
commit(ADD_TODO, {todo} )
}
}
action调用mutations的方法一定 要保证两者的函数名一致,需要第三方来保证:mutation-types来暴露出去。
store/mutation-types.js:
// 存放一些常量
export const ADD_TODO = 'add_todo';//添加一条记录
store/mutations.js:
// 存放一些常量
import {
ADD_TODO
} from './mutations-types'
export default{
//转字符串为变量,更新数据。
[ADD_TODO](state, {todo}){
state.todos.unshift(todo);
}
}
查看数据状态:
谷歌浏览器:需要安装devtools插件
链接: chrome.google.com/webstore/se…
更新数据:
输入框中输入数据添加:
总结:
一开始学vuex是有点绕,但是认识清其的运行机制,多多运用到实例中。