安装方式vue-cli直接安装
//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
state:{
//你的数据状态注册
count:0
},
})
//mian.js
import Vue from 'vue'
import App from './App.vue'
//引入Vuex
import Vuex from './store'
//全局挂载Vuex 与router一样
new Vue ({
store,
render:h=>h(app)
}).$mount('#app')
大型項目于普通的小項目相似,
Vuex 允许我们将 store 分割成模块(module)
思路是把所有状态都集中到一个store/index.js里面
然后通过store的全局挂载实现信息同步,
但实际工作做用一般都属于第二种
//创建子状态文件及文件夹 store/global/button.js
const state={
count:0
}
const mutations={
//同步处理函数
}
const actions={
//异步处理函数
}
//共享出去
export default{
//namespaced解决不同模块命名冲突的问题,之后在
//不同页面中引入getter、actions、mutations时,需要加上所属的模块名
namespaced:ture,
state,
mutations,
actions
}
import Vue from 'vue'
import Vuex from 'vuex'
//引入你的子状态js文件
import button from './global/button.js'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
//注册到模块化组件内 由store全局共享
button,
button1,
button2
....
},
getters // store 的计算属性 接收参数state 与computed相似 一般单独一个文件夹
})
export default store
//方法一
//注意:如果将数据count写到store/index.js文件夹中
// this.store.state.变量名(js名.全局数据名称)
//注意:如果将数据count写到store/.文件夹名.count
// this.store.state.文件夹名.变量名
//例子 调用第一章节中的count值
<template>
<div class='main-container'>
<h1>数据的最新值:{{this.$store.state.button.count}}</h1>
//在html结构中 此处this可省略
</div>
</template>
//方法二
import {mapState} from 'vuex'
// 通过此函数将全局数据映射为 当前组件 的计算属性
//例如 调用第一章节中的count值
<javascript>
...
computed:{
//可追加所需要的数据 前面 ‘... ’为对象展开运算符,
//与复制不同,映射可以随着原数据的更新,此组件也随之更新。
...mapState({
count:state=>state.button.count
})
//如果将数据count写到store/index.js文件夹中 则可简写
//num为组件应用处命名:数据的最新值:{{num}}
...mapState({
num:'count'
})
//如果不命名则可以:数据的最新值:{{count}}
更简写
...mapState(['count'])
}
...
</javascript>
第一种:适合少量数据传输,写法简单快捷
第二种:更适合大量数据传输,方便查看更整洁
在vuex中如果数据发生变化如何实现?
(注意:此案例vuex状态写在模块js内 路径为 src/store/global/button.js)
//创建子状态文件及文件夹 store/index.js
const state={
count:0
}
const mutations={
//同步处理函数
}
const actions={
//异步处理函数
}
//共享出去
export default{
namespaced:ture,
state,
mutations,
actions
}
<template>
<div class='main-container'>
//此处为双大括号 此处必须加上组件名字“button”
<h1>数据的最新值:{{this.$store.state.button.count}}</h1>
<button @click="countAdd"> +1 </button>
//在html结构中 此处this可省略
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
};
},
methods: {
countAdd(){
this.$store.state.button.count++
}
}
};
</script>
不利于后期维护,无法检测数据变化
简单的说Vuex就相当于一个班级的班长,
vue相当于班级班主任,不同的状态js文件相当于一个科目课代表,
所有的状态数据都通过js课代表存储到班长,
任何学生想要更改作业个人信息,不能自己随便更改,
需要通过课代表来更改,然后课代表汇总所有数据存储在班长哪里
*如果使用微型项目单文件store的形式不存在课代表 班长就相当于课代表
从组件中改变count数据在Vuex的框架下,应该叫做提交数据
在vuex中只能通过mutations提交变更Store数据,不能直接操作Store的数据
可通过vuex中的mutations此函数来改变数据
//定义mutations 为简单在组件vuex的总文件夹index.js创建
const store=new Vuex.store({
//模块内部的 mutation,接收的第一个参数是模块的局部状态对象。
mutations:{
add(state){
state.count++
}
}
})
//组件中
<script>
export default {
name: 'Home',
data() {
return {
};
},
methods: {
countAdd(){
//add为mutations函数中对应的函数名
this.$store.commit('add')
}
}
};
</script>
//定义mutations
const store=new Vuex.store({
mutations:{
add(state,num){
//将vuex中的数据 num为传递来的参数
//最新count=count+num 结果赋值给count
state.count+=num
}
}
})
//组价触发mutations
const store=new Vuex.store({
methods:{
handle(){
//提交mutations并传递参数
this.$store.commit("add",任意参数)
}
}
})
官方文档在此处说明有些模糊,导致很不容易理解!!!
Ⅰ.绑定事件,从vuex中按需导入mapMutations 函数
<button @click='countAdd'></button>
import { mapMutations} from 'vuex'
Ⅱ.将指定的mutations 函数,映射为当前组件的methods函数
methods: {
//可映射多个mutations中的函数映射过来
//注意:“ ... ” 为对象展开运算符
//功能一 button点击触发事件countAdd()
...mapMutations({countAdd:'add'})
//功能二 当button点击触发事件时候需要传递参数 countAdd(value) 例如数字变量num 仍然可以保持这样写
...mapMutations({countAdd:'add'})
//只是需要在mutations函数中加一个接收参数num就行
//功能三 button点击触发事件@click='add'函数命名
//如果与mutations中的函数名一致为add 则可简写为:
...mapMutations(['add']) //{}变为[]
}
}
模块内注册的状态数据访问
注意点1、
数据的最新值:{{this.$store.state.button.count}}
此处一定要加上组件名 ‘button’
注意点2、 this.$store.commit('button/add',任意参数)
提交时一定要加上组件名 ‘button’
在store内函数commit内提交
可打印console.log(this.$store)查看更好理解
action函数不能直接更改vuex中数据
他主要处理异步函数
比较相对繁琐的工作
处理完成后提交给mutations更改数据
异步与同步举例:
//还是刚才的数据count
<template>
<div class='main-container'>
//此处为双大括号
<h1>数据的最新值:{{this.$store.state.count}}</h1>
<button @click="countAdd"> +1 </button>
//在html结构中 此处this可省略
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
};
},
methods: {
countAdd(){
this.$store.commit('add')
}
}
};
</script>
如果想实现点击按钮 让数据 count 延迟1秒再增加 如何实现?
可以通过增加一个定时器!!!
假如给mutations添加结果怎样?
//定义mutations
const store=new Vuex.store({
mutations:{
add(state){
setTimeout( ()=>{
state.count++
},1000)
}
}
})
结果就是数字虽然会延时触发
但打开vue调试工具会发现add时间虽然触发 但右侧 state中count数据并未发生变化
这显然是不行的
所有这里引入Action函数帮助处理这些异步函数
Actions就当于Mutations的个人助理
大大小小的事件都交给Actions,Mutations只做最终签字就行
//定义mutations
const store=new Vuex.store({
mutations:{
ADD(state){
state.count++
}
}
actions:{
//Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
//因此你可以调用 context.commit 提交一个 mutation函数。
add(context){
setTimeout( ()=>{
context.commit('ADD')
},1000)
}
}
})
这个例子很好的阐述Mutations函数与Actions的区别,各自分工。
实际开发中Mutations与Actions
一般都不会直接调用Mutations函数,
一般都通过调用Actions函数来提交更改数据申请
并且为了彼此对应,常常把Mutations中的函数名大写,Actions函数名小写
运行流程如下
组件提交>Actions>Mutations>状态改变>同步到全局组件>组件再次改变…
一个完整闭环流程
//1、组件调用
this.$store.dispatch('add')
//2、Actions接受信号,并提交给Mutations
add(context){
context.commit('ADD')
}
}
//3、Mutations修改数据
ADD(state){
state.count++
}
}
下面介绍两种提交:
未模块化单store.js 无参数提交 修改vuex
模块化并且携带参数提交
//1、组件调用
//单文件01 store.js
this.$store.dispatch('add')
//模块化1 提交到 user为user.js, user_Info为提交Actis函数名字, nickname为提交参数
this.$store.dispatch('user/user_Info', 'nickname');
//2、Actions接受信号,并提交给Mutations
//单vuex文件02 store.js
add:({commit}){
commit('ADD')
}
//模块化2
user_Info ({ commit }, nickname) {
commit('USER_INFO', 'nickname')
}
//3、Mutations修改数据
//单vuex文件03 store.js
ADD:(state)=>{
state.count++
}
//模块化3
USER_INFO (state, nickname) {
state.nickname = nickname
}
Actions同样有mapActions辅助函数帮助数据传输
与mapMutations用法类似 这里不做演示
区分:
1、mapState在computed中注册使用
2、mapActions与Actions在methods中注册使用
到这里再看这张图就简单多了,devtools为vue调试工具 能检测到vuex的变化状态
上面的看懂了解清楚,Getter就很容易明白了
主要意义处理state中的数据,然而这个数据又不能是原始数据,
Getter就可以作为一个过滤处理函数
const store=new Vuex.store({
state:{
fruit: [
{ name: 'a', num: 5 },
{ name: 'b', num: 10 },
{ name: 'c', num: 16 }
],
}
}
mutations:{}
actions:{}
getters:{
fruitNum: state => {
return state.fruit[0].num
}
}
})
...
<el-button> 第一个水果数量:{{ this.$store.getters.fruitNum }}</el-button>
...
...
console.log(this.$store);
...
getters:{
//查询数据
maxCount: (state) => (who) => {
return state.fruit.find(fruit => fruit.name === who)
}
}
...
<el-button> 第一个水果数量:{{ this.$store.getters.maxCount('a') }}</el-button>
...
...
//还能可以打印查看
console.log(this.$store.getters.maxCount('a'));
//注意 这里有一个坑
//你如果直接打印
console.log(this.$store.getters);
// 会发现找不到maxCount的数据,因为这里是需要传参数的
...
与其他Vuex的函数一样,Getters同样具备mapGetters
getters:{
//计算返回数据
maxCount: (state) => (who) => {
return state.fruit.find(fruit => fruit.name === who)
}
}
//引入函数注册提交
import { mapGetters} from 'vuex';
...
computed: {
...mapGetters(['maxCount'])
},
...
<h3> c水果的信息为:{{ maxCount('c') }}<h3>
//渲染结果为 c水果的信息为:{ "name": "c", "num": 16}
...
此处注意点 若为模块化项目 getters也模块化独立文件js 例如:src/store/myCount.js
注册提交时要添加上文件名
computed: {
...mapGetters('myCount',['maxCount'])
},
在组件内重命名使用
注意 [ ] 改变{ }
computed: {
...mapGetters('myCount',{yourname:'maxCount'})
},