浅谈vuex
程序员文章站
2022-05-15 17:42:58
...
Vuex
-
官网:
https://vuex.vuejs.org/zh/
-
概念:
-
01:Vuex是一个专为Vue.js应用程序开发的状态管理模式
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的规则发送变化
Vuex也集成到Vue的官方调试工具devtool.extension,提供了诸如零配置的time-travel测试,状态快照导入导出等高级调试功能。 -
02:状态管理是什么?
状态管理其实可以看出多个组件的共享的变量全部存储在一个对象里面
把这个对象放在Vue实例的顶层中,让其他组件可以使用,实现变量的共享 -
03:管理什么状态呢?
多状态,在多个组件界面的共享问题
用户登录,用户头像,用户名称,地理位置等
商品收藏,购物车的商品
诸如这些,都可以存放在Vuex上面管理
-
-
特点:
- 具有响应式 => 采用的是单例模式!
-
安装Vuex
npm i vuex -S
vuex的简单使用
- 使用:
一般而言 => 就是在文件根目录下创建一个文件夹 store/index.js
store/index.js
import Vue from "vue"
import Vuex from "vuex";
//1:使用插件
Vue.use(vuex);
//2:创建一个对象
const store = new Vuex.store({
})
//3:导出
export default store;
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from "./store"
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Vuex内的store对象内的属性
- state
- mutations
- getters
state 单一状态树
- 概念:所谓单一状态树,就是用一个对象(store)来包裹全部应用层的状态数据!
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
state => view => actions => state 形成一个圆圈,这也就是一个单一状态树!
store.state.XXX 来获取store对象上的state状态数据!
一般来说,操作数据还是在store对象上的mutations属性来操作的,这样有利于与对状态数据改变的监听$store.state.XXX
=> 在其他视图之中,呈现vuex管理的state状态数据!this.$store.commit("add")
=> 在当前视图add(){ } 里面拿到视图的修改状态,提交到 mutations中的add方法去修改状态数据add(state){ store.state.count++ }
=> 在store/index.js中mutations下的add方法,去修改状态数据!
getters 类似于计算属性
-
作用:就是对state中的状态数据,做出一定的修改后(带有复杂的操作,比如 求一个state中某个值的平方等,或者字符串的翻转等,那么可以在getters这个属性中操作!)
-
参数:
- 1:state => 为了获取state中的状态数据
- 2: getters => 为了可以调用getters属性中的其他方法
-
需求:
- 1:求count的平方
- 2:求age大于20岁的人
- 3:求age大于20岁的人 的个数
- 4:求age超过 XXX 用户自己输入的 年龄!
store/index.js文件
import Vue from "vue"
import Vuex from "vuex";
//1:使用插件
Vue.use(Vuex);
//2:创建一个对象
const store = new Vuex.Store({
//保存的状态 =>用于数据的共享!
state: {
count: 10,
studengs: [{
id: 1,
name: "ppp",
age: 20
},
{
id: 2,
name: "www",
age: 10
},
{
id: 3,
name: "wwwp",
age: 40
},
{
id: 4,
name: "ccc",
age: 13
},
]
},
//对状态数据的 监听 和 操作
mutations: {
add(state) {
state.count++;
},
sub(state) {
state.count--;
}
},
getters: {
//求平方
getPower(state) {
return state.count * state.count
},
//求 年龄大于18的人 还想获取这个大于18岁的个数(总数)
getAge20(state) {
return state.studengs = state.studengs.filter(item => item.age > 18)
},
//getters的第二个参数:只能是getters属性,这是获取getters属性中的其他方法!
getAge20Num(state, getters) {
return getters.getAge20.length
},
getAge(state) {
return function (age) {
return state.studengs.filter(item => item.age > age)
}
},
getStuId(state) {
return function (id) {
return state.studengs.filter(item => item.id > id)
}
}
}
})
//3:导出
export default store;
其他组件中引用getters中处理后的数据
<p>我是求平方 {{ $store.getters.getPower}}</p>
<p>我是超过20岁的{{ $store.getters.getAge20 }}</p>
<p>我是超过20岁的数量{{ $store.getters.getAge20Num }}</p>
<p>我是内部返回函数 {{ $store.getters.getAge(20) }}</p>
<p>我是内部返回函数id {{ $store.getters.getStuId(1) }}</p>
mutations
-
作用:
- 就是vuex中状态值发生改变的时候,针对其他组件提交的方法,来操作状态数据,类似于事件!
- 还有就是在这边可以使用工具监听到状态数据从哪里改变
-
注意点:mutations里面的必须为同步函数!
-
提交风格:
- 格式1:
- 1:在mutations属性中定义函数,处理数据
add(state){ return state.count++ }
- 2:需要在其他组件中定义方法,然后来触发mutations中的处理数据方法
{{$store.state.count}} <button @click="add">+</button> methods:{ add(){ this.$store.commit("add"); } }
- 1:在mutations属性中定义函数,处理数据
- 格式2: 推荐使用,对象的形式更为直观!
- 1:在mutations属性中定义函数,处理数据
addCount(state,payload){ //payload => 负载 也就是携带参数 这个方式的提交 是一个对象! state.count += payload.count }
- 2:在需要其他组件触发事件
<button @click="addCount(20)">+20</button> methods:{ addCount(count){ this.$store.commit({ type:"addCount", count }) } }
store/index.js文件
- 需求:
- 1:定义一个++ 的函数,用户输入多少,就+多少
- 2:添加一个学生!
import Vue from "vue"
import Vuex from "vuex";
//1:使用插件
Vue.use(Vuex);
//2:创建一个对象
const store = new Vuex.Store({
//保存的状态 =>用于数据的共享!
state: {
count: 10,
studengs: [{
id: 1,
name: "ppp",
age: 20
},
{
id: 2,
name: "www",
age: 10
}
]
},
//对状态数据的 监听 和 操作
mutations: {
//普通mutations提交风格
// addcount(state, count) {
// state.count += count
// },
// 这是特殊的mutations提交风格
addCount(state, payload) {
state.count += payload.count
},
addStu(state, stuObj) {
state.studengs.push(stuObj)
}
},
})
//3:导出
export default store;
其他.vue文件
<button @click="addCount(10)">+10</button>
<button @click="addCount(20)">+20</button>
<p @click="addStu">我是添加一个对象</p>
methods: {
addCount(count) {
// this.$store.commit("addcount", count);
//另外一种 mutations提交风格
this.$store.commit({
type: "addCount",
count,
});
},
addStu() {
const stuObj = {
id: 5,
name: "pink",
age: 33,
};
this.$store.commit("addStu", stuObj);
},
},
mutations 的响应式数据
- Vuex中的 store 状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。
- 使用 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
- 1:最好提前在你的 store 中初始化好所有所需属性。
- 2:当需要在对象上添加新属性时,你应该
使用Vue.set(obj, 'newProp', 123)
=> 参数1: 对象 || 数组 ,参数2: String || Number ,参数3:修改后的值(或者新添加的值!) - 3:以新对象替换老对象。
state.obj = { ...state.obj, newProp: 123 }
- 4:删除对象中的属性,具有响应式!
Vue.delete(obj,prop)
mutations 的中的定义常量
- 官网:
https://vuex.vuejs.org/zh/guide/mutations.html
actions 属性对异步的处理
-
作用:就是类似带有异步的操作,都需要在action之中操作,什么定时器啊,ajax啊!
-
流程:
- 1:在组件中自定义一个方法 aupdataInfo方法
- 然后在methods之中去分发(触发事件,传递到actions之中)
this.$store.dispatch("aupdataInfo",{ msg:"这是携带的信息", success:()=> { log输出成功信息 } }
- 然后在methods之中去分发(触发事件,传递到actions之中)
- 2:在store/index.js文件中
- 先定义state状态数据
info:[ {id:1,name:"lll",address: "1" }]
- 然后在actions属性之中,接受组件调用的方法,并且去触发mutations中的方法,最后返回组件给调用者!
aupdataInfo(context,payload){ setTimeout(() => { context.commit("aupdataInfo") // 更新完毕后 执行下面的代码! log可输出 payload.msg信息 payload.success(); }, 1000); }
- 在mutations属性之中,接受actions所触发的函数调用!
aupdataInfo(state){ state.info.address:"lll" || Vue.set(state.info, "address", "闪烁!") }
- 先定义state状态数据
- 1:在组件中自定义一个方法 aupdataInfo方法
-
需求:
- 点击更新用户按钮,给这个对象添加一条数据 (address:)
- 01:使用回调函数的方式 来告知更新完成
- 02:使用promise方法 来告知更新完成 =>推荐使用这种方式!
组件中触发事件
{{ $store.state.info }}
<button @click="aupdataInfo">我是使用actions分发的更新数据</button>
- 01:使用回调函数的方式 来告知更新完成
- 02:使用promise方法 来告知更新完成
methods:{
//01:使用回调函数的方式
// aupdataInfo(){
// this.$store.dispatch("aupdataInfo",{
// msg:"我是携带的信息",
// success:()=>{
// consele.log("我是更新完成")
// }
// })
// }
//02:使用promise的方式
aupdataInfo(){
this.$store.dispatch("aupdataInfo","我是携带的信息")
.then(res => consele.log(res))
}
}
}
store/index.js状态管理文件中
state:{
info: {
id: 2,
name: "小黑",
}
},
mutatoons:{
aupdataInfo(state){
state.info.address:"修修"
}
},
actions:{
//方式1:使用回调的函数的方式 => 告知 更新用户成功
// aupdataInfo(context,payload){
// setTimeout(() => {
// context.commit("aupdataInfo");
// consele.log(payload.msg)
// payload.success()
// }, 1000);
// }
//方式2:使用promise的方式 解决异步编程
aupdataInfo(context, payload) {
return new Promise((resolve) => {
setTimeout(() => {
context.commit("aupdataInfo")
console.log(payload);
resolve("123") //成功的回调 这个是返回一个promise对象 在触发这个函数的时候 返回成功的
})
}, 1000);
}
}
modules 属性
- 就是state是单一状态树,那么所有数据都依托它管理的话,他会显得很臃肿,因此有了模块化的区分
- modules 就是在modules之中定义一个或者多个属性 a:moduleA => 挂载一个对象,那么这个moduleA模块对象A,就会被划分到store中!
- 先在store中定义模块 然后在外面声明这个模块对象moduleA
const moduleA = { } const store = new Vuex.Store({ state:{ count:10 }, modules:{ a:moduleA, b:modulesB } })
- 然后在外面声明这个模块对象moduleA,里面操作!
- state属性 => 定义的是模块的状态数据
- getters属性 => 定义的是模块的getters属性,类似计算属性
- 参数:参数1:context(上下文) 参数2:payload(携带的参数) 参数3:rootState(根对象的状态数据)
- mutations属性 => 定义的是模块中所要操作的同步状态数据 在里面定义方法
- actions属性 =>定义的是模块中的所有操作的异步状态数据 =>还是需要提交到mutations中操作!
- modules属性
- 注意点:
- $store.state.a => 模块a的状态数据
- $store.getters.XXX => 还是依旧这样写 不过的是,先去store对象中查询,查询不到才到模块中查询
- 因此模块中的方法和数据 与 store内定义的不能同名!
- 先在store中定义模块 然后在外面声明这个模块对象moduleA
组件中使用模块状态数据
<div>我是modules的</div>
<p>{{ $store.state.a.name }}</p>
<button @click="updataName">修改name</button>
<p>{{ $store.getters.fullName }}</p>
<p>{{ $store.getters.fullName2 }}</p>
<p>{{ $store.getters.fullName3 }}</p>
<button @click="aupdataName">异步修改name</button>
fullName() {
this.$store.commit("fullName");
},
updataName() {
this.$store.commit("updataName");
},
aupdataName() {
this.$store
.dispatch("aupdataName", "嘿嘿")
.then((res) => console.log(res));
},
store/index.js
const moduleA = {
state: {
name: "pink"
},
mutations: {
//注意点:就是模块中的方法名称 不用和store对象中的内定义的方法名称重名,因为在触发事件的时候,先先去store对象中的查询的,
// 查询没有之后,才到模块之中查询是否含有该方法,才触发的!
updataName(state) {
state.name = "deepPink"
},
aupdataName(state) {
state.name = "deepPinkBig"
}
},
getters: {
//注意点:就是getters 不管你定义在哪里 在组件引用数据的时候,都是 `$store.getters.XXX`
fullName(state) {
return state.name + "666"
},
fullName2(state, getters) {
return getters.fullName + "000"
},
fullName3(state, getters, rootState) {
return getters.fullName2 + rootState.count
}
},
actions: {
aupdataName(context) {
return new Promise((resolve) => {
setTimeout(() => {
context.commit("aupdataName")
console.log("我是携带的信息");
resolve("666成功了")
}, 1000);
})
}
}
}
const store = new Vuex.Store({
//保存的状态 =>用于数据的共享!
state: {
count: 10,
}
modules: {
a: moduleA,
}
})
上一篇: 数据流:输入流和输出流 --简单介绍