文章目录
1. Vuex是什么?
今天主管给我发了这样一张图,告诉我接下来要用到vuex,让我理解一下这张图
并附带参考文章链接
https://vuex.vuejs.org/zh/
开始看文章:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能balabalabala
这。。也看不懂啊
2. 该怎么学vuex?
我学习新东西还是觉得要实战练习才能真正理解,于是我找到了这篇文章
https://www.cnblogs.com/chinabin1993/p/9848720.html
标题五分钟搞懂什么是vuex
接下来我结合着两篇文章,开始动手敲代码了
3. 敲代码
1)创建一个vue项目
在本地新建一个文件夹vuex
在文件夹中打开终端
运行
$ vue init webpack app
前提是你安装过cli,命令如下
$ npm install -g vue-cli
一直按enter就可以,我这里网有些慢。。
成功后打开到app目录下
引入vuex
我每次在一个新项目中运行npm install 时总会遇到错误,如果你也遇到问题可参考我的另一篇博客
https://blog.csdn.net/qq_37842366/article/details/97629531
$ npm install vuex --save
成功后运行终端命令
$ npm run dev
2)引入vuex
在src下创建文件夹vuex,vuex文件夹下创建store.js
store.js引入vuex
state:存储状态(变量)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
export default new Vuex.Store({
state
})
main.js中引入
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './vuex/store' //引入store.js
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
3) 测试是否引入成功
在src -> components -> HelloWorld.vue中添加代码
在store.js中我们设置了state变量,里面添加了count属性,在界面代码处就可以直接通过属性调用count值
{{ $store.state.count }}
浏览器中查看,vuex使用成功
4) Mutation
a. mutations 里面放置的是我们操作state对象属性的方法
b. 更改 Vuex 的 store 中的状态的唯一方法是提交mutation,同步的
c. 每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)
d. 这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
首先在state中添加一个数组todos
const state = {
count: 0,
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
}
定义mutations对象
const mutations = {
//payload: 载荷 这里是一个对象
mutationsAddCount(state, payload){
return (state.count += payload.amount)
},
//这里的载荷是参数 n
mutationsReduceCount(state, n = 0){
return (state.count -= n)
}
}
不要忘了在Vuex.Store中使用它
export default new Vuex.Store({
state,
mutations
})
在HelloWorld中添加两个click事件测试
<div>
<button @click="handleAddClick(10)">增加</button>
<button @click="handleReduceClick(10)">减少</button>
</div>
要唤醒一个 mutation handler,你需要调用 store.commit 方法
methods: {
handleAddClick(n){
this.$store.commit('mutationsAddCount', {
amount: 10
});
},
handleReduceClick(n){
this.$store.commit('mutationsReduceCount',n);
}
}
回到浏览器测试一下吧
5) Getter
a. getters 一般使用getters获取state,因为它算是state的一个计算属性
b. getters 对数据获取之前的再次编译
c. getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
在store.js中定义getter属性
const getters = {
//Getter 接受 state 作为其第一个参数
doneTodos: state =>{
return state.todos.filter(todo => todo.done)
},
//Getter 也可以接受其他 getter 作为第二个参数
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
},
//通过让getter返回一个函数,实现给getter传参。
//这在对store里的数组进行查询时非常有用
getTodoById: (state) => (id) =>{
return state.todos.find(todo => todo.id === id)
}
}
而访问getter可以有两种方法
(1)以属性形式访问
(2)通过方法访问
<!-- Getter 会暴露为 store.getters 对象,以属性的形式访问这些值 -->
<h3>{{ $store.getters.doneTodos }}</h3>
<h3>{{ $store.getters.doneTodosCount }}</h3>
<!-- 通过方法访问 -->
<h3>{{ $store.getters.getTodoById(2) }}</h3>
回到浏览器中测试
6) Action
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
我们可以调用 context.commit 提交一个 mutation
或者通过 context.state 和 context.getters 来获取 state 和 getters在store.js中定义action属性
const actions = {
actionsAddCount(context, n = 0){
console.log(context)
return context.commit('mutationsAddCount', {
amount: 10
})
},
actionsReduceCount({ commit }, n = 0){
return commit('mutationsReduceCount',n)
}
}
定义两个按钮测试异步action
<div>异步操作</div>
<div>
<button @click="handleActionsAdd(10)">异步增加</button>
<button @click="handleActionsReduce(10)">异步减少</button>
</div>
定义click事件方法
Action 通过 store.dispatch 方法触发
handleActionsAdd(n){
this.$store.dispatch('actionsAddCount', n)
},
handleActionsReduce(n){
this.$store.dispatch('actionsReduceCount',n)
}
回到浏览器中测试
对于Action方法,第一篇文章链接中讲的比较详细,需要的可以看一下
7) Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
这里由于时间问题没有进行练习,大家可以根据第一篇文章讲解自行练习。
8) 简化写法
通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。但是自从有了对象展开运算符,我们可以极大地简化写法:
methods:{
...mapMutations({
handleAddClick: 'mutationsAddCount',
handleReduceClick: 'mutationsReduceCount'
}),
...mapActions({
handleActionsAdd: 'actionsAddCount',
handleActionsReduce: 'actionsReduceCount'
})
}