Vuex的subscribe和getter有什么区别?为何更适配SSR数据渲染场景?
Vuex
subscribe 与 computed+getter 的运行逻辑差异 1. computed 包裹 getter 的运行逻辑
computed是Vue原生的懒执行响应式计算属性,仅当它内部依赖的响应式变量发生变更时,才会触发重新计算返回新值。- 原有业务流程下的触发链路是:路由
ProductID变化 → 触发watch回调执行异步loadProductaction → 接口请求完成后提交mutation更新store →getter关联的state变更后,computed才会重新计算更新Product的值。 - 存在的天然时序问题:
- 首次加载时store中商品数据是初始空值,要等异步action执行完成才会更新,所以
Product初始值为空 - 路由跳转时,新的异步action未完成前,
getter读取的还是旧state,所以Product会先保留旧商品数据,直到新mutation提交才更新 - SSR场景下,服务端渲染是同步输出HTML的,
computed的响应式更新走Vue的微任务更新队列,优先级低于同步执行逻辑,很容易错过服务端渲染窗口期,导致返回的HTML直接使用旧值/空值渲染。
- 首次加载时store中商品数据是初始空值,要等异步action执行完成才会更新,所以
2. store.subscribe 的运行逻辑
$store.subscribe是Vuex内置的mutation订阅钩子,会在每一次mutation提交完成后同步触发,优先级高于Vue组件层的响应式更新通知。- 修改后的逻辑中,只要store有mutation提交,回调会第一时间把最新的store商品数据赋值给
Product这个ref,不需要等待Vue的响应式依赖追踪、计算属性重算的流程,没有额外的更新延迟。
为什么subscribe在SSR场景表现更好
SSR的核心要求是所有状态更新必须在HTML输出前完成,否则会出现服务端返回内容和客户端hydration不匹配的问题:
computed+getter的更新属于组件侧的响应式副作用,执行时机晚于同步代码,服务端渲染时如果异步action完成的时机晚于HTML输出时机,就会拿到旧数据。- 而
subscribe的回调是mutation提交的同步钩子,只要在服务端正确等待loadProduct这个异步action执行完成再触发渲染,subscribe更新的Product值一定是mutation提交后的最新值,完全不会出现旧数据问题。
内容的提问来源于stack exchange,提问作者volume one
相关产品推荐
相关产品推荐

