实现 ref 函数

未匹配的标注

特点

ref 函数经常用来包装基本类型,也可以用来包装一个对象(不常用)
底层用的其实就是 Object.defineProperty

第 1 步

packages/reactivity/src/ref.ts

import { toReactive } from './reactive'
import { isTracking, trackEffects, triggerEffects } from './effect'
import { Dep } from './dep'

class RefImpl<T> {
  public dep?: Dep = undefined
  public __v_isRef = true
  public _value: T

  constructor(public _rowValue: T) {
    // 如果 _rowValue 传进来的是一个对象,那么需要将对象转换成响应式
    this._value = toReactive(_rowValue)
  }

  // 取值的时候进行依赖收集
  get value() {
    // 依赖收集
    if (isTracking()) {
      trackEffects(this.dep || (this.dep = new Set()))
    }
    return this._value
  }

  // 修改的时候触发依赖更新
  set value(newValue) {
    // 判断新值和老值是否相等,不相等再更改
    if (newValue !== this._rowValue) {
      this._rowValue = newValue
      // 由于传的值可能是对象,所以在这里将其转换成 reactive
      this._value = toReactive(newValue)
      triggerEffects(this.dep!)
    }
  }
}

function createRef(value: unknown) {
  return new RefImpl(value)
}

export function ref(value: unknown) {
  return createRef(value)
}

packages/reactivity/src/index.ts

export { effect } from './effect'
export { reactive } from './reactive'
export { computed } from './computed'
// --------------------------新增 start------------------------
export { ref } from './ref'
// --------------------------新增 end--------------------------

packages/reactivity/example/ref.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script src="../dist/reactivity.global.js"></script>
<script>
  const { effect, ref } = VueReactivity
  const state = ref(0)
  effect(() => {
    console.log(state.value)
  })
  console.log(state)
  setTimeout(() => {
    state.value++
  })
</script>
</body>
</html>

效果如下:

实现 ref 函数

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~