2024.06.17~2024.06.21

senmu2024/06/21

Vue 中的 computed 属性

用法:

computed 属性支持 gettersetter 两个函数,如果直接写成函数形式则默认为 getter 函数,并且对于计算属性 Vue 会缓存其结果,也就意味着多次访问该属性返回的都是同样的结果。当然,计算属性也支持依赖响应式数据作为返回值,当响应式数据改变时会改变其结果。

场景:

计算属性一般用于复杂的响应式数据的处理,当响应式数据没改变的情况下可以极大地提高性能;但是,同样要注意,因为它会缓存结果,在计算属性中返回一个普通值那么该值永远不会被更新。

watch 相比:

它们的设计目的就不相同,computed 被设计作为计算响应式数据的复杂逻辑,且它是无副作用的纯函数;而 watch 被设计作为侦听响应式数据的变化并处理副作用逻辑。

原理:

  • 初始化:当一个计算属性被定义时,Vue会为其创建一个内部的观察者实例(Watcher)。
  • 依赖收集:在计算属性的函数第一次执行时,它会访问响应式数据,这时响应式数据会将该计算属性的观察者添加到它的依赖列表中。这个过程称为依赖收集。
  • 缓存:计算属性的结果会被缓存,只有当它的依赖发生变化时,缓存才会失效。下次访问计算属性时,如果缓存有效,则直接返回缓存结果;如果缓存失效,则重新计算。
  • 派生状态:当计算属性的依赖响应式数据发生变化时,依赖于该计算属性的 Watcher 会被通知,从而触发视图更新。

Vue 中虚拟节点/DOM 有哪些类型?

以下是在 XX 组件库中发现的逻辑,所以深入探索下。

<script>
const getNode = (children) => {
  return children && children.find(node => node && node.tag)
}

export default {
  name: 'xxComp',
  // ... 省略属性等等
  render() {
    return getNode(this.$slots.default)
  }
}
</script>

上面的 xxComp 子组件不支持纯文本的情况,因为纯文本节点的虚拟 DOM 没有 tag 属性。

Vue 源码中对于纯文本节点的创建:

// VNode 部分
class VNode {
  constructor(
    tag?: string,
    data?: VNodeData,
    children?: Array<VNode> | null,
    text?: string,
    elm?: Node,
    context?: Component,
    componentOptions?: VNodeComponentOptions,
    asyncFactory?: Function
  ) {}
}
export function createTextVNode(val: string | number) {
  return new VNode(undefined, undefined, undefined, String(val))
}

从上面源码片段就可以看出来纯文本不存在 tag 属性~

另外,从源码中看虚拟节点包括 elementcomponent

最近更新 2024-06-24 10:13:42