文章目录
Vuex
速查表
Vuex 操作 | 代码 |
---|---|
获取状态 | this.$store.state.变量名 |
同步修改状态 | this.$store.commit("命名空间/Mutations 中定义的方法名") |
异步修改状态 | this.$store.dispatch("命名空间/Actions 中定义的方法名") |
杂谈
最近出差去深圳了,所以没太多的经历去写博客,提升自己,摸鱼实在是太爽了,不过兄弟们我还是回来了,咕咕咕!
让我慢慢总结这个吧,毕竟还是重要的东西,之前写项目也在这里绊过跟头,所以这次想在弄懂一些!
简介
我们来看一个比较抽象的概念哈
Vuex
是一个专为Vue.js
应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化。
说的比较抽象,其实可以理解为,保存全局状态的地方,改变值得话会有行为记录
比方说,我的登录状态,此状态会贯穿我使用此 app
的所有过程吧?所以这个状态就最好存在 Vuex
中
再比方说,我登录成功了,此时我要去改变 Vuex
中的变量的状态,然而,我不能直接去修改,而是发出修改的指令,动作!
优点
- 统一管理状态,保证一致性
- 服务端重构开发
- 可预测性能:让程序更健壮,出了问题能够反查
安装
vuex
也是个插件,可以通过 vue add vuex
来安装它
安装完成之后可以看到新添加了些东西啊。
其中的 store
文件夹下的 index.js
的内容如下,我们以后要把变量放在这里的!
使用
定义变量
还是用举例的方式吧,我现在要管理一个登录的状态,那么我就在 state
里设置个变量
获取变量
一般都是在 vue
文件中获取,比较简单
// 这是在 vue 文件中获取,如果是 html 里就可以 this 省去
this.$store.state.变量名
这里再讲一下其他地方获取
如果想在其他文件中获取状态,可以先引入
store
,然后再获取,比方说下面这个例子:我在全局路由守卫中获取
首先需要在 js
中导入一下 store
然后尝试在路由中获取,获取的方法 store.state.变量名
,并且写了写逻辑,刷新页面,打印一下!
成功获取!
修改状态 Mutations
我们不能直接修改变量值,会报错的,而是通过通知 vuex
一个动作,也就是 mutations
提供的方法,去修改状态
这样的好处上文已经说过,便于统一管理,排查错误。
首先在 mutations
中定义登录、登出的方法
然后再登录的时候调用该方法:
最后执行一下看看,成功改变了 vuex
中的变量值(这个打印 islogin
我是放到了全局守卫里了)
异步调用 actions
我们先在 actions
中定义好方法,如下图所示,然后通过 dispatch
去调用方法
我们还是举例子,详细的说明请看下图
再来个动图:
是不是清晰了些!
最佳实践
这标题夸张???行吧
模块化
其实上面改的状态都是属于用户的状态,那我可不可以单独提取出来,变成一个子模块呢?
让我们来提取一下:
之后的获取、修改变量需要变化一下
获取变量:
派发事件的方式:
至于为什么这么修改的,我们可以在官网上找到些蛛丝马迹
映射方法
探究问题
可以看一下我们修改完之后的获取
点的实在是太深了,对于我这种懒人,不太友好,有没有较好的处理办法呢?有的,那就是映射出来!
初步认识 mapState()、mapMutation()、mapAction()
这就要接触一下这几个东西了
mapState()/mapMutation()/mapAction()
通过这些映射方法可以让大家少敲几个字,避免对 $store
直接访问
使用方法
获取变量:
主要是配合 computed
钩子
修改变量:
// 这两个都行
...mapActions('user', ['login']),
...mapActions(['user/login']),
通过 mapActions
引出,展开,并注册在 methods
里,然后就可以通过 this
来调用了
整体思路如下
抛出问题
既然 mutations
和 actions
可以写同名函数,那么都引用进来,会调用谁的呢?还是老样子啊,想想之后,实验一下!
实验动图如下:
也就是说,同名的方法会被覆盖掉,用最底下的方法。
派生方法 getters
类似 vuex
的计算属性,下面来个欢迎语的实践
下面是动图:
严格模式
严格模式下,无论何时发生了状态变更且不是由 mutation
函数引起的,将会抛出错误。这能保证所有 的状态变更都能被调试工具跟踪到。
开启严格模式 strict: true
再看一下报错的情况,虽然说是报错,但是 username
的状态还是改变了。
插件
简介
Vuex
的 store
接受 plugins
选项,这个选项暴露出每次 mutation
的钩子。Vuex
插件就是一个函数,它接收 store
作为唯一参数。
也就是说,每次 mutation
中的方法被调用的时候,都会运行插件里的函数
为什么要用插件
因为vuex 只是处理窗台的地方,而不是写逻辑的地方
实例:登录永久化
首先需要知道一些比较重要的
const myPlugin = store => {
// 当 store 初始化后调用
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
// mutation 的格式为 { type, payload }
})
}
然后可以阅读一下官网,还是比较全面,vuex 官方说明插件
之后再看一下这个逻辑
最后看一下动图吧:
// 插件源码
import router from '../../router'
/**
* 永久化保存
* - 判断本地缓存是否存在
* - 如果有的话就去设置一下
*/
export default (store) => {
console.log('使用了预处理插件')
if (localStorage) {
const user = JSON.parse(localStorage.getItem('user'))
if (user) {
store.commit('user/login', user)
}
}
store.subscribe((mutation, state) => {
console.log('store.subscribe:>>', mutation)
if (mutation.type === 'user/login') {
localStorage.setItem('user', JSON.stringify(state.user))
} else if (mutation.type === 'user/logout') {
localStorage.removeItem('user')
router.push('/login')
}
})
}