数据共享:VueX学习
1.Vuex是干什么的?
本质:多个界面一起管理某些数据
- 它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
- 有什么状态时需要我们在多个组件间共享的呢?如果你做过大型开放,你一定遇到过多个状态,在多个界面间的共享问题。比如用户的登录状态、用户名称、头像、地理位置信息等等。比如商品的收藏、购物车中的物品等等。
2.Vuex状态管理图
- Vuex的核心概念:State、Mutations、Actions、Getters、Modules
- State:全局共享变量
- Mutations:修改State
- Getter:State的变异值(如平方、+10、-10等)
- Actions:异步修改State,类似于Mutations
- Modules:模块化
3.Vuex入门案例
-
安装:npm install vuex@3.6.2 -save
-
实现案例:
-
1.创建store文件夹,创建index.js文件
import Vue from 'vue' import Vuex from 'vuex' //1.安装插件 Vue.use(Vuex) //2.创建对象 const store = new Vuex.Store({ state:{ counter:100, students:[ {id:110,name:'why',age:18}, {id:111,name:'kobe',age:24}, {id:112,name:'james',age:30}, {id:113,name:'curry',age:10}, ], info:{ name:"kobe", age:40, height:1.98 } }, //定义方法,state默认传过来 //store状态的唯一更新方式 //异步操作的时候,devtools 检测不到 mutations: { increment(state){ state.counter++; }, decrement(state){ state.counter--; } } }) //3.导出store对象 export default store
-
2.挂载到Vue实例(main.js)
-
3.App.vue
<template> <div id="app"> <h2>----------App内容:state相关信息-----------------</h2> <h2>{{message}}</h2> <h2>{{$store.state.counter}}</h2> <!-- <button @click="$store.state.counter++">+</button> <button @click="$store.state.counter--">-</button> --> <button @click="addtion">+</button> <button @click="subtraction">-</button> </div> </template> <script> export default { name: 'App', components: { }, data(){ return { message:"我是App组件", counter:0 } }, methods:{ addtion(){ this.$store.commit('incrment') }, subtraction(){ this.$store.commit('decrement') } } } </script> <style> </style>
4.State单一状态树
- 案例:在国内我们有很多的信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录,结婚后的婚姻信息,以及其他相关的户口、医疗、文凭、房产记录等等(还有很多信息)。这些信息被分散在很多地方进行管理,有一天你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误。这种保存信息的方案,不仅仅低效,而且不方便管理,以及日后的维护也是一个庞大的工作(需要大量的各个部门的人力来维护,当然国家目前已经在完善我们的这个系统了)。
- 这个和我们在应用开发中比较类似:如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。
- 所以Vuex也使用了单一状态树来管理应用层级的全部状态。单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
- 使用:参考基本案例。
5.Getters的基本使用
-
将其放入上面的index.js文件中,主要时原始数据state进一步处理后返回,一些简单的操作:平方、+10 等等
-
但是这些操作不会改变原来的值,相当于Getters只是copy一份state进行修改,而原来的值不会发生变化,主要通过mutations来修改state的值
-
默认参数state
//对于共享数据进一步处理后地数据 getters: { powerCounter(state){ return state.counter * state.counter; }, more20stu(state){ return state.students.filter(s => s.age>20 ) }, more20stuLength(state,getters){ return getters.more20stu.length; }, moreAgestu(state){ // return function(age){ // return state.students.filter(s => s.age>age ) // } return age =>{ return state.students.filter(s => s.age>age ) } }, },
-
App中使用如下:
-
其中moreAgestu可以传递参数,这时候getters需要利用函数处理
<h2>-----------App内容:getters相关信息</h2> <h2>{{$store.getters.powerCounter}}</h2> <h2>{{$store.getters.more20stu}}</h2> <h2>{{$store.getters.more20stuLength}}</h2> <h2>{{$store.getters.moreAgestu(12)}}</h2>
6.Mutations的基本使用
-
Vue中store状态的更新唯一方式:Mutations
-
1.参数传递
-
其中updateInfo函数可以实现State数据实时变化(包括添加对象、删除对象等)
-
index.js
mutations: { increment(state){ state.counter++; }, decrement(state){ state.counter--; }, incrementCount(state,count){ state.counter += count }, addStudent(state,stu){ state.students.push(stu) }, updateInfo(state){ //state.info.name = 'codewhy' //state.info['address'] = '洛杉矶' //自动拼接 //Vue.set(state.info,'address','洛杉矶') //Vue.delete(state.info,'age') } },
-
App.vue
methods:{ addtion(){ this.$store.commit('increment') }, subtraction(){ this.$store.commit('decrement') }, addCount(count){ //payload:负载 //1.普通的提交风格 this.$store.commit('incrementCount',count) //2.特殊的提交风格--感觉这个有点麻烦 // this.$store.commit( // { // type:'incrementCount', // count:count // } // ) }, addStudent(){ const stu = {id:115,name:'ale',age:30} this.$store.commit('addStudent',stu) }, updateInfo(){ this.$store.commit('updateInfo'); } }
-
2.常量
-
在mutation中, 我们定义了很多事件类型(也就是其中的方法名称).
-
当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多.
-
方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.
-
- 创建文件mutations-types.js
- 创建文件mutations-types.js
-
2.编写(这里只写了一个常量为例子)
-
3.index.js中导入
-
4.App.vue引入如下
-
5.mutation引入如下
-
-
3.Mutations的响应规则
- Vue的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.
-
4.Mutations的监控规则
- 当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照.
- 但是如果是
异步操作
, 那么devtools将不能很好的追踪这个操作什么时候会被完成. - 安装的话:谷歌商城下载插件
7.Actions的基本使用
-
我们强调, 不要再Mutation中进行异步操作.
-
但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求, 必然是异步的.
-
这个时候怎么处理呢? Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.
-
使用方法:dispatch函数,之前的mutations是commit方法
-
参数传递:payload传递(mutations的第二种参数传递方法)
- 基本案例:
- App.vue
updateInfo(){ //this.$store.commit('updateInfo') //this.$store.dispatch('aUpdateInfo','我是payload'); this.$store.dispatch('aUpdateInfo','我是携带的信息').then(res => { console.log('里面完成了提交'); console.log(res); }) },
- index.js
actions: { //解决异步操作的时候,devtools 检测问题 //context:上下文 //context==store // aUpdateInfo(context,payload){ // setTimeout(()=>{ // context.commit('updateInfo') // console.log(payload); // },1000) // } aUpdateInfo(context,payload){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ context.commit('updateInfo') console.log(payload); resolve('11111111') },1000) }) } },
- 分析:actions是为了解决异步操作的,内部会调用mutations中的方法,通过new Promise可以实现异步调用,并将结果返回给App组件,并且可以实现devtools插件的检测。
8.Modules的基本使用
Module是模块的意思, 为什么在Vuex中我们要使用模块呢?
- Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.
- 当应用变得非常复杂时,store对象就有可能变得相当臃肿.
- 为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而
每个模块拥有自己的state、mutations、actions、getters等
在index.js文件中,则格式如下:
需要注意的两点:
- 1:在模块中的getters使用根模块的state
//2.创建对象
const moduleA = {
state:{
name:'zhangsan'
},
mutations: {
updateName(state,payload){
state.name=payload
}
},
actions: {
aUpdateName(context){
setTimeout(()=>{
context.commit('updateName','wangwu')
},1000)
}
},
getters: {
fullname(state){
return state.name + '1111';
},
fullname2(state,getters){
return getters.fullname + '22222';
},
//这里:在模块中使用根模块的state
//第三个参数rootState
fullname3(state,getters,rootState){
return getters.fullname2 + rootState.counter;
}
}
}
const store = new Vuex.Store({
state:{
counter:100,
students:[
{id:110,name:'why',age:18},
{id:111,name:'kobe',age:24},
{id:112,name:'james',age:30},
{id:113,name:'curry',age:10},
],
info:{
name:"kobe",
age:40,
height:1.98
}
},
//定义方法,state默认传过来
//store状态的唯一更新方式
//异步操作的时候,devtools 检测不到
mutations: {
[INCREMENT](state){
state.counter++;
},
decrement(state){
state.counter--;
},
incrementCount(state,count){
state.counter += count
},
addStudent(state,stu){
state.students.push(stu)
},
updateInfo(state){
//state.info.name = 'codewhy'
//state.info['address'] = '洛杉矶' //自动拼接
//Vue.set(state.info,'address','洛杉矶')
//Vue.delete(state.info,'age')
}
},
actions: {
//解决异步操作的时候,devtools 检测问题
//context:上下文
//context==store
// aUpdateInfo(context,payload){
// setTimeout(()=>{
// context.commit('updateInfo')
// console.log(payload);
// },1000)
// }
aUpdateInfo(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
context.commit('updateInfo')
console.log(payload);
resolve('11111111')
},1000)
})
}
},
//对于共享数据进一步处理后地数据
getters: {
powerCounter(state){
return state.counter * state.counter;
},
more20stu(state){
return state.students.filter(s => s.age>20 )
},
more20stuLength(state,getters){
return getters.more20stu.length;
},
moreAgestu(state){
// return function(age){
// return state.students.filter(s => s.age>age )
// }
return age =>{
return state.students.filter(s => s.age>age )
}
},
},
modules: {
a : moduleA
}
})
- 2:App.vue如何调用模块中的state、getters、mutations、actions
<template>
<div id="app">
<h2>----------App内容:modules-----------------</h2>
<h2>{{$store.state.a.name}}</h2>
<button @click="updateName">修改名字</button>
<h2>----------App内容:modules--getters-----------------</h2>
<h2>{{$store.getters.fullname}}</h2>
<h2>{{$store.getters.fullname2}}</h2>
<h2>{{$store.getters.fullname3}}</h2>
<button @click="asynUpdateName">异步修改名字</button>
</div>
</template>
<script>
import {
INCREMENT
} from './store/mutations-types'
export default {
name: 'App',
components: {
},
data(){
return {
message:"我是App组件",
counter:0
}
},
methods:{
addtion(){
//常量统一--减少错误
this.$store.commit(INCREMENT)
},
subtraction(){
this.$store.commit('decrement')
},
addCount(count){
//payload:负载
//1.普通的提交风格
this.$store.commit('incrementCount',count)
},
updateName(){
this.$store.commit('updateName','lisi')
},
asynUpdateName(){
this.$store.dispatch('aUpdateName')
}
}
}
</script>
<style>
</style>
9.Store的项目组织结构
-
除了state全部抽取出去,为了方便修改
-
mutations.js
import { INCREMENT }from "./mutations-types" export default { [INCREMENT](state){ state.counter++; }, decrement(state){ state.counter--; }, incrementCount(state,count){ state.counter += count }, addStudent(state,stu){ state.students.push(stu) }, updateInfo(state){ //state.info.name = 'codewhy' //state.info['address'] = '洛杉矶' //自动拼接 //Vue.set(state.info,'address','洛杉矶') //Vue.delete(state.info,'age') } }
-
getters.js
export default { powerCounter(state){ return state.counter * state.counter; }, more20stu(state){ return state.students.filter(s => s.age>20 ) }, more20stuLength(state,getters){ return getters.more20stu.length; }, moreAgestu(state){ // return function(age){ // return state.students.filter(s => s.age>age ) // } return age =>{ return state.students.filter(s => s.age>age ) } }, }
-
actions.js
export default { //解决异步操作的时候,devtools 检测问题 //context:上下文 //context==store // aUpdateInfo(context,payload){ // setTimeout(()=>{ // context.commit('updateInfo') // console.log(payload); // },1000) // } aUpdateInfo(context,payload){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ context.commit('updateInfo') console.log(payload); resolve('11111111') },1000) }) } }
-
moduleA.js
export default { state:{ name:'zhangsan' }, mutations: { updateName(state,payload){ state.name=payload } }, actions: { aUpdateName(context){ setTimeout(()=>{ context.commit('updateName','wangwu') },1000) } }, getters: { fullname(state){ return state.name + '1111'; }, fullname2(state,getters){ return getters.fullname + '22222'; }, fullname3(state,getters,rootState){ return getters.fullname2 + rootState.counter; } } }
-
index.js
import Vue from 'vue' import Vuex from 'vuex' import mutations from './mutations' import actions from './actions' import getters from './getters' import moduleA from './modules/moduleA' //1.安装插件 Vue.use(Vuex) //2.创建对象 const store = new Vuex.Store({ state:{ counter:100, students:[ {id:110,name:'why',age:18}, {id:111,name:'kobe',age:24}, {id:112,name:'james',age:30}, {id:113,name:'curry',age:10}, ], info:{ name:"kobe", age:40, height:1.98 } }, mutations, actions, //对于共享数据进一步处理后地数据 getters, modules: { a : moduleA } }) //3.导出store对象 export default store
- 点赞
- 收藏
- 关注作者
评论(0)