vuex作用
vuex就是为了提供这样一个在多个组件间共享状态的插件
vuex管理什么状态呢?
例如:用户的登录状态,用户名称,头像,地理位置信息等
例如商品的收藏,购物中的物品等等
这些状态信息,可以放在统一的地方,对它进行保存和管理,而且还是响应式的
安装vuex包
npm install vuex -S
简单案例演示
App.vue
<template> <div id="app"> <HelloWorld></HelloWorld> </div> </template> <script> import HelloWorld from "./components/HelloWorld"; export default { name: "App", components: { HelloWorld, }, }; </script> <style> </style>
main.js
import Vue from "vue"; import App from "./App.vue"; import store from "./store/index.js"; Vue.config.productionTip = false; new Vue({ render: (h) => h(App), store, }).$mount("#app");
components/HelloWorld.vue
<template> <div> <h2>这是一个HelloWorld</h2> <h2>{{ $store.state.counter }}</h2> <button @click="add">+</button> <button @click="sub">-</button> <button @click="addCount(8)">跳数</button> <div>-------------getter----------------</div> <h2>{{ $store.getters.powerCounter }}</h2> <div>-------modules---------</div> <h2>{{ $store.state.a.name }}</h2> <button @click="updateName"></button> <h2>{{ $store.getters.fullName }}</h2> </div> </template> <script> import { INCREMENT } from "../store/mutations-type"; export default { data() { return {}; }, methods: { add() { this.$store.commit(INCREMENT); }, sub() { this.$store.commit("decrement"); },addCount(count) { //简单方式提交封装 this.$store.commit("incrementCount", count); //特殊的提交封装 this.$store.commit({ type: "incrementCount", count, }); }, addStudent() { let stu = { id: 160, name: "kkk", age: 18 }; this.$state.commit("addStudent", stu); }, updateInfo() { // this.$state.dispatch("aUpdateInfo", { // msg: "我是携带的信息", // success() { // console.log("里面已经完成了"); // }, // }); this.$state.dispatch("aUpdateInfo").then((res) => { console.log(res); }); }, updateName() { this.$store.commit("updateName", "李四"); }, }, }; </script> <style lang=""></style>
/store/index.js
import Vue from "vue"; import Vx from "vuex"; import { INCREMENT } from "./mutations-type";//1安装插件 Vue.use(Vx); const moduleA = { state: { name: "zhangsan", count: 15, }, mutations: { updateName(state, payload) { state.name = payload; }, }, getters: { fullName(state) { return state.name + "111"; }, fullName3(state, getter, rootState) { //rootState 是指Vx.Store对象中的state对象 return getter.fullName + state.name + rootState.counter; }, }, actions: { aupdateName(context) { console.log(context); setTimeout(() => { //只能调用moduleA中的mutations context.commit("updateName"); }, 1000); }, incrementRootSum({ state, commit, rootState }) { if ((state.count + rootState.counter) % 2 === 1) { commit("updateName"); } }, }, }; const moduleB = { state: {}, mutations: {}, }; //2创建对象 const store = new Vx.Store({ state: { counter: 10000, students: [ { id: 110, name: "why", age: 18 }, { id: 120, name: "kobe", age: 19 }, { id: 130, name: "james", age: 20 }, { id: 140, name: "curry", age: 10 }, ], info: { name: "张三", age: 18, }, }, mutations: { //方法 [INCREMENT](state) { state.counter++; }, decrement(state) { state.counter--; },
incrementCount(state, count) { state.counter += count; //当是普通方式时 count就是普通的数字 8 //当是特殊方式时 count 是对象,所以推荐使用 payload来取名,通过payload.count来获取 }, addStudent(state, stu) { state.students.push(stu); }, test(state, payload) { //多参数时,可以将payload对为对象,名字可以修改 state.counter = payload.counter; }, updateInfo(state) { //不能在这里进行异步操作 // setTimeout(() => { // state.info.name = "王五"; // }, 1000); state.counter = ""; }, },
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); }; }, }, actions: { //context是上下文 aUpdateInfo(context, payload) { // setTimeout(() => { // context.commit("updateInfo"); // console.log(payload.msg); // payload.success(); // }, 1000);
return new Promise((resolve, reject) => { setTimeout(() => { console.log(payload.msg); context.commit("updateInfo"); let err = ""; if (err === "err") { resolve("11"); } else { reject("11"); } }, 1000); }); }, }, modules: { a: moduleA, b: moduleB, }, });
//3导出store独享 export default store;
mutations-type.js
export const INCREMENT = "increment";
Vuex核心概念
(1)State 状态树
1>vuex提出使用单一状态树,什么是单一状态树?
英文名称是Single Source of Truth 也可以翻译为单一数据源
(2)Getters
1> 类似于计算属性
如上面的简单案例代码中的使用
2>getters作为参数和传递参数
如上面的简单案例代码中的使用
(3)Mutations 状态更新
1>官方:修改state的值肯定是在mutations中进行
参数被称为是mutation的载荷(Payload)
2>mutations 简单使用(不带参数)
如上面的简单案例代码中的使用
3>mutations 携带参数
如上面的简单案例代码中的使用
4>若参数不是一个呢?
有时候需要用到多个参数,那么就会以对象的形式传递,也就是payload是一个对象,这样就可以从对象获取
5>mutation提交风格
上面是通过commit进行提交是一种普通的方式
Vue还提供了另外一种风格,他是一个包含type属性的对象
6>mutation响应规则
vuex的store是响应式的,当state中的数据改变时,vue组件会更新
(1).提前在store中初始化好所需的属性
(2).当给state中的对象添加新属性时,使用下面的方式
方式一:使用Vue.set(obj,'newProp',123)
方式二:用新对象给旧对象重新赋值
在state中,实际上,这里的info各种属性在定义时,就会自动挂载到响应式系统中,只要而响应式系统会监听这些属性的变化,当属性发生变化是,就会通知所有用到该属性的页面进行刷新 info:{ name:'张三', age:18 } 在mutation中 updateInfo(state){ // state.info.name ='李四' //state.info['address'] = '中国' //不报错,info虽然添加了该属性,但是界面并不会发生刷新,因为需要提前在store中初始化才行
Vue.set(state.info,'address','洛杉矶')
//delete state.info.name //没发生任何变化,info没有变化
Vue.delete(state.info,'name') }
7>mutations的类型常量
如上面的简单案例代码中的使用(就是创建 mutations-type.js来处理)
8>mutation同步函数
devtools可以帮助扑捉mutation的快照
若是异步操作,那么devtools将不能很好的追踪这个操作什么时候会被完成,通过铜鼓vue工具看时,里面的state没有变化,实际页面已经发生变化了
(4)Actions
1>基本定义
actions类似于mutation,但是是用来替代mutation进行异步操作的,可以解决mutation同步函数问题
2>基本使用
如上面的简单案例代码中的使用(dispatch部分)
(5)Modules
1>module是模块的意思,为什么要用到模块呢?
1.因为使用单一状态树,也就意味着很多模块都会交给vuex来管理
2.当应用变得非常复杂时,store对象就会变得相当臃肿
3.为了解决该问题,vuex允许我们将store分割成模块,而每个模块拥有自己的state,mutations,actions,getters等
如上面的简单案例代码中的使用(moduleA部分)
合理的项目结构