1.vuex是什么?怎么使用?哪种功能场景使用它?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex。
场景:多个组件共享数据或者是跨组件传递数据时
原理:实际上是通过实例化Vue来实现
流程(工作原理):页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation,mutation会修改state中对应的值。最后通过getter把对应值跑出去,在页面的计算属性中,通过,mapGetter来动态获取state中的值。(单向数据流,便于管控)
2.vuex有哪几种属性
有五种,分别是State , Getter , Mutation , Action , Module
state
:vuex的基本数据,用来存储变量geeter
:从基本数据(state)派生的数据,相当于state的计算属性mutation
:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。action
:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。modules
:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
4.异步请求代码应该写在组件的methods中还是vuex的actions中?
一、如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
二、如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。
5.mutation中能放异步操作吗?为什么?
最好不要。但不会报错。会造成状态改变的不可追踪。异步操作通过 Action 来提交 mutation实现,这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
这个只是规范,而不是逻辑的不允许,是为了让devtool工具能够追踪数据变化,另外方便我们更好的处理数据逻辑。
6.Vuex中actions和mutations的区别
Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
const store = createStore({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
Action 类似于 mutation,不同在于:
- Action 需要提交 mutation去变更状态,而不是直接变更状态。
- Action 可以包含任意异步操作。
- mutation是同步更新数据(内部会进行是否异步检测,严格模式会报错,实现检测方法是通过$watch)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
7. commit和dispatch,这两个有什么作用呢?
类似与在vue中通过click
事件,触发methods
中的方法。
当存在异步时,在vuex中需要dispatch
来触发actions
中的方法,actions
中的commit
可以触发mutations
中的方法。
同步,则直接在组件中commit
触发vuex中mutations
中的方法。
通过this.$store.state.属性
的⽅法来访问状态。
通过this.$store.commit(‘mutation中的⽅法’)
来修改状态。
8.双向绑定和vuex是否冲突?
当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model
会比较棘手。因为双向绑定修改状态时没有通过 mutation 函数, 这里会抛出一个错误。
9.Vuex可以直接修改state的值吗?
可以直接修改,但是极其不推荐。
当我们将vuex
的模式改成严格模式的时候,我们在通过直接修改state
的方式修改状态的时候,控制台会报错。
state
的修改必须在mutation
来修改,否则⽆法被devtool所监测,⽆法监测数据的来源,⽆法保存状态快照,也就⽆法实现时间漫游、回滚之类的操作。
简单来说,就是使用commit
来更改状态主要是为了状态能够很好的跟踪,开发者工具更好的处理状态变化,更好的调试体验。
10.什么情况下使⽤ Vuex?
如果应⽤够简单,最好不要使⽤Vuex ,⼀个简单的 Event Bus 就可实现跨组件通信(公共的vue实例)。
//使用中间vue实例实现子-子通信
//mid
Vue.prototype.$bus = new Vue()
//某子组件发消息
//....
methods: {
tellname () {
// 发出事件,传递数据,givename自定义事件
this.$bus.$emit('givename', this.mybfname)
}
}
//某子组件收消息
// 组件一加载就进行兄弟组件所发出的事件的监听
created () {
// vm.$on(vue自定义的事件, 处理函数)
// 处理函数有一个默认参数,就是其它组件所传递的数据
this.$bus.$on('givename', (data) => {
console.log(data);
this.mysbfname = data
})
}
需要构建⼀个中⼤型单页应⽤时,使⽤Vuex
能更好地在组件外部管理状态。
11.页面刷新后Vuex的state数据丢失怎么办?
Vuex只是在页面内存中保存状态,页面刷新后是必然会丢失状态。
当然可以使用localStorage
、sessionStorage
或cookie
进行存储。我们一般使用localStorage
做持久化(Cookie、sessionStorage、localStorage的区别)
初始化state
数据时可以直接从localStorage
中获取备用值,但是需要每次在修改状态时使用localStorage.setItem(key,val)
保存最新值,这样感觉不太优雅。
// 初始化
const store = createStore({
state(){
return {
count: localStorage.getItem('count')
}
},
mutations: {
// 更新值
updateCount(state, value){
state.count++
localStorage.setItem('count',state.count)
}
}
})
// 或者在调用时手动更新值
store.commit('updateCount')
localStorage.setItem('count', store.state.count)
存在问题:
- 不是所有的状态都需要持久化,所以需要区别对待,有一定心智负担。
- 如果需要保存的状态很多,每次手动重设缓存就比较繁琐,不够优雅。
解决方式:
1) 使用Vuex提供的Api --> subscribe
做统一处理。(订阅 store 的 mutation。handler
会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数),可以将处理函数封装为插件。
const unsubscribe = store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
if(mutation.type==='updateCount'){
localStorage.setItem('count', state.count)
}
})
// 你可以调用 unsubscribe 来停止订阅。
unsubscribe()
// 封装为插件
const myPlugin = (store) => {
// 当 store 初始化后调用
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
// mutation 的格式为 { type, payload }
})
}
// 使用插件
const store = createStore({
// ...
plugins: [myPlugin]
})
2) 可以使用开源的插件进行持久化,原理同上。插件如 vuex-persist、vuex-persistedstate等。
12.Vuex的缺点
Vuex 可以集中组件的公共状态,利用响应式,很方便我们做开发。但模块化这一块做得比较复杂,使用不是很方便,需要经常看文档去回顾。
另外,如果不打算开发⼤型应⽤,使⽤Vuex
可能是繁琐冗余的。Vuex是重量级的,对性能有一些影响。换句话说,Vuex其实不适合中小型应用。
1)模块使用比较繁琐,获取状态模式不统一,复杂度较高,增加心智负担,容易出错
// 使用插件
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
// 使用
store.state.b // -> moduleB 的状态
store.state.a // 要带上 moduleA 的 key(.a) ,内嵌模块的话会很长,代码阅读性不佳,不得不配合 mapState 使用
store.getters.c // moduleA 里的 getters ,没有 namespaced: true 时又变成了全局的
store.getters['a/c'] // namespaced: true 时需要加 path
store.commit('d') // 没有 namespaced 时又是全局的
store.commit('a/d') // namespaced: true 时也需要加 path,要使用mapMutations 的话也比较麻烦
2)对TS的支持不太友好,没有友好的类型支持和提示
虽然Vuex在后期版本通过定义类型化的 InjectionKey
使得类型支持有所改善,但使用会很不优雅。
3)体积较大,重量级,小型项目对性能有一定影响。
如今团队又推出了新一代的状态管理插件:Pinia,它使用 Vue 3 中的新反应系统来构建一个直观且完全类型化的状态管理库。其库容量和性能要优于Vuex。而且完全支持Ts。
https://code.zuifengyun.com/2022/07/2486.html
本文固定连接:https://code.zuifengyun.com/2020/06/1631.html,转载须征得作者授权。