vue的初始化(vue项目初始化的一些配置有哪些)

平常在写 Vue 项目时,免不了要写一些 computed 来包装、计算一些数据。以方便我们使用。来看下 Vue3 中 computed 都做了什么。

先看一下文件的入口:
    export function computed<T>(  getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>) {  //初始化 getter、setter 和 副作用函数  const c = _computed(getterOrOptions as any)  //执行当前实例的副作用函数  recordInstanceBoundEffect(c.effect)  return c}

    代码位置:packages/runtime-core/src/apiComputed.ts

    _computed 用来初始化我们传入的 getter、setter,并生成 computed 的副作用函数。recordInstanceBoundEffect 方法用来执行副作用函数。
    // 第一种:const doubbleCount = computed(()=>num.value+1)// 第二种:const doubbleCount = computed({    get: () => num.value + 1,    set: val => num.value = val + 10})
    computed 接收两种传值方式。一种是传入「函数」,这个函数的主要作用是获取值,但并不能设置值。
    另一种方式是设置 get 和 set 方法,get 用来获取值,set 用来设置值。
    export function computed(getterOrOptions) {  //定义 getter 和 setter  let getter  let setter  //先判断是否是函数?  if (isFunction(getterOrOptions)) {    //把我们写的 computed函数 赋值给 getter    getter = getterOrOptions    //如果是开发环境赋值 一个包含错误信息的函数,如果是生产环境,赋值一个空函数    setter = __DEV__      ? () => {console.warn(\\\'Write operation failed: computed value is readonly\\\')}      : NOOP  } else {    //如果我们是以第二种方式传入的参数,那就直接赋值对应的 getter 和 setter    getter = getterOrOptions.get    setter = getterOrOptions.set  }  //返回一个类,收集依赖、派发事件  return new ComputedRefImpl(    getter,    setter,    isFunction(getterOrOptions) || !getterOrOptions.set  )}

    代码文件:packages/reactivity/src/computed.ts

    先定义 getter 和 setter 两个变量,然后通过判断是不是「函数」来区分我们采用的哪种 computed 写法。
    如果传入的是函数,那正好直接把我们的参数赋值给 getter,同时 setter 也会被赋值,如果是开发环境,会赋值「错误提示方法」向下继续执行流程,如果不是生产环境,会赋值 NOOP 。如果不是函数,那就是传入了自定义的 get 和 set,直接赋值就好。
    赋完值后,返回一个 ComputedRefImpl 类,类传入的参数带着我们的 getter 和 setter。
    class ComputedRefImpl<T> {  //缓存结果值  private _value!: T  //是不是脏数据?  private _dirty = true  public readonly effect: ReactiveEffect<T>  public readonly __v_isRef = true;  public readonly [ReactiveFlags.IS_READONLY]: boolean  constructor(    getter: ComputedGetter<T>,    private readonly _setter: ComputedSetter<T>,    isReadonly: boolean  ) {    //创建副作用函数    this.effect = effect(getter, {      //true 函数延迟执行      lazy: true,      //执行函数      scheduler: () => {        if (!this._dirty) {          this._dirty = true          //派发通知          trigger(toRaw(this), TriggerOpTypes.SET, \\\'value\\\')        }      }    })    this[ReactiveFlags.IS_READONLY] = isReadonly  }  get value() {    //如果是脏数据,则需要执行副作用函数    if (this._dirty) {      this._value = this.effect()      this._dirty = false    }    track(toRaw(this), TrackOpTypes.GET, \\\'value\\\')    return this._value  }  set value(newValue: T) {    //设置新值    this._setter(newValue)  }}

    代码文件:packages/reactivity/src/computed.ts

    在 ComputedRefImpl 类中,先声明了一些私有化属性。缓存了计算结果 _value,判断是否是脏数据,默认为 true。在 constructor 中生成 effect 副作用函数,该函数有两个参数,一个是 getter 函数,另一个是配置对象,lazy 表示需要延迟执行,scheduler 表示调试运行的方式。
    export function effect<T = any>(  fn: () => T,  options: ReactiveEffectOptions = EMPTY_OBJ): ReactiveEffect<T> {  //是否是副作用函数  if (isEffect(fn)) {    fn = fn.raw  }  //创建副作用函数  const effect = createReactiveEffect(fn, options)  //是否立即执行  if (!options.lazy) {    effect()  }  return effect}
    effect 最终会返回一个包装好的副作用函数,结束 computed 方法。当 _computed 函数执行赋值后,会看到 effect、_dirty 等属性。

    接下来就要去整理副作用函数了。为什么要整理呢?对于副作用函数来说,是有执行顺序的,computedEffect 的执行顺序是先于普通 effect 的。
    recordInstanceBoundEffect(c.effect)//方法export function recordInstanceBoundEffect(  effect: ReactiveEffect,  instance = currentInstance) {  if (instance) {    ;(instance.effects || (instance.effects = [])).push(effect)  }}
    此方法执行了一句,把 effect 添加到 instance.effects 里。下图可见到最终 effects 结果。

    这就是一个组件里 computed 执行要经历的步骤。
    点击关注公众号,查看更多 Vue 的内容

    图片授权基于 www.pixabay.com 相关协议

    原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34580.html

    (0)
    小道研究's avatar小道研究
    上一篇 2024年4月13日 下午10:14
    下一篇 2024年4月13日 下午10:16

    相关推荐

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注