vue中通过watch监听数据变化,带来的性能优化
问题背景为什么要用 vuex?在使用 Vue 进行组件化开发时,组件通信是一个十分重要的部分。在 Vue 中,父子组件的关系可以总结为父子组件通信:父组件通过 props 向下传递数据给子组件子父组件通信:子组件通过 events 给父组件发送消息使用 $on(eventName) 监听事件使用 $emit(eventName) 触发事件非父子组件通信:使用...
问题背景
为什么要用 vuex?
在使用 Vue 进行组件化开发时,组件通信是一个十分重要的部分。在 Vue 中,父子组件的关系可以总结为
- 父子组件通信:父组件通过 props 向下传递数据给子组件
-
子父组件通信:子组件通过 events 给父组件发送消息
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
- 非父子组件通信:使用一个空的 Vue 实例作为中央事件总线
父子,子父 组件之间的通信是很轻松的,通过 props 和 events 即可实现;但是往往我们的应用可能不只有这么简单的层级关系,在多层跨级组件如果通过 props 去传递,那意味着一层一层的往子组件传递,最终你可能不知道当前组件的数据最终来自哪个父组件(当然你可以逆着方向一层一层往上找),通过 events 事件机制显然也存在着类似的问题。如果你觉得这样也可以接受,你可能不需要 Vuex;但如果你在想有没有什么好的模式优雅的去解决,你可以继续阅读下面的部分。
状态管理
我们通过发送 action,提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutations。
- actions:操作行为处理模块。负责处理 Vue Components 接收到的所有交互行为。包含同步/异步操作,向后台 API 请求的操作就在这个模块中进行,包括触发其他 action 以及提交 mutation 的操作。该模块提供了 Promise 的封装,以支持 action 的链式触发。
- mutations:状态改变操作方法。是 Vuex 修改 state 的唯一推荐方法,其他修改方式在严格模式下将会报错。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些 hook 暴露出来,以进行 state 的监控等。
- state:页面状态管理容器对象。集中存储 Vue components 中 data 对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用 Vue 的细粒度数据响应机制来进行高效的状态更新。
- getters:state 对象读取方法。Vue Components 通过该方法读取全局 state 对象。
数据流转
用 getters 将 state 数据映射到当前组件,在 vue component 中发送 action,在 action 中请求数据,并调用 mutations,mutationg 改变 state 的数据,从而实现数据更新导致的页面更新。
问题描述
在正在做的项目中遇到这样一个问题,当页面进行分页请求时,连续点击当前页会一直发送请求,极大的降低了性能,于是决定减少请求次数,只有 pageNum 发生变化时才去请求。
实现过程
vue 中有 watch 这个 api 它可以监听对象及对应值的变化从而在数据发生变化时调用 action,于是写了如下代码
实现分页操作的绑定事件
@redirect="handlePageRedirect"
发送 action 将点击的 pageNum 存储在 state 里 监听 pageNum 的变化来发送 action 来请求数据,当然还需通过 computed 将 state 里需要监听的数据映射到当前组件
发现数据并没有被监听,并尝试打印监听的数据,代码如下
watch: {
'aList.pageNum'(newVal, oldVal) {
console.log(newVal,oldVal);
}
}
问题定位
打开调试工具,发现 state 数据中并没有 pageNum 这个数据,但在文件 state.js 中是有默认值的,查找发现,在 mutations 中将原本 state 的默认值覆盖 state.js 中监听的数据 在 mutations 中将 state 数据覆盖代码,代码如下
state.aList = {
list: data.list,
total: data.total,
pageSize: data.pageSize
}
查阅资料了解到 mutation 改变 state 数据只需要将新值加入到原来对象,而不是覆盖它,代码如下
故修改代码为
state.aList = {
...state.aList,
...data
}
总结知识
watch 监听的方式
- 对象中属性的 watch
watch: {
'aList.pageNum'(newVal, oldVal) {
console.log(newVal,oldVal);
}
}
- 某个对象的 watch tips: 只要 bet 中的属性发生变化(可被监测到的),便会执行 handler 函数;如果想监测具体的属性变化,如 pokerHistory 变化时,才执行 handler 函数,则可以利用计算属性 computed 做中间层。 如果想监测具体的属性变化,如 pokerHistory 变化时,才执行 handler 函数,则可以利用计算属性 computed 做中间层。 注意 deep: true 必须加。
- 监听url的变化发送请求(可获取url上参数)
watch: {
$route({ query }) {
this.searchUser([
{},
{
appId: query.appId
}
]);
}
}
- mutations 中改变数据的方式,将新值与容器中的值合并,并不是直接覆盖。
- watch 暂且写到这里,欢迎大家来补充留言。
更多推荐
所有评论(0)