小彭看vue源码-第一天

107 阅读3分钟

第一天

vue源码选择了monorepo,选择的是package中的reactivity包

入口文件

这个是一个文件夹,其实是要看package.json中的main字段,没有就会直接报错的,模块化的最后一步了 src下面的index.js

'use strict'

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./dist/reactivity.cjs.prod.js')
} else {
  module.exports = require('./dist/reactivity.cjs.js')
}

这个地方应该是配置的区分环境,要看打包之后的结果,就不看了 直接看ref和reactive了

src目录下面的 ref.ts响应式数据 reactive.ts响应式数据 effect.ts 副作用 effectScope.ts 副作用应该是隔离的作用 dep.ts收集依赖 operation.ts定义操作文件,应该是用于diff那块 compute.ts计算属性 warnning.ts警报文件 就是自定义console.log

baseHandler.ts 不知道,应该是绑定处理函数的作用 collectioinHandlers.ts 不知道,猜测一下应该是收集handler,在diff的时候来执行 deferredCompute.ts 不知道,猜测一下应该是用来处理compute的引用 基本英语知识点。可能会有问题

dep

trackRefValue(this)

toRaw(this)得到了ref 然后就去trackEffects(ref.dep || ref.dep = createDep());这个写法真不错,惰性函数

triggerRefValue(this,value)

toRaw(this)得到了ref 还要得到dep = ref.dep 还是要看这个dep是不是存在 然后去triggerEfects(dep)

effect

export let activeEffect: ReactiveEffect | undefined
export let shouldTrack = true

ref

ref在99行会经过createRef来创建一个ref的对象 shallowRef createRef(value,true) ref createRef(value,false)

createRef函数

这个函数的参数有2个,一个是代理的数据,深度代理的函数Boolean数值

这个函数会判断这个数据是不是被代理过来,用的isRef函数

然后真正的创建函数来了new RefImpl(value,boolean)

isRef

我在看这个的时候,还以为会去判断 value instaceof RefImpgl, 结果没有,哈哈哈哈

就是去判断,这个属性是不是存在,或者是去看这个对象的isRef=true吗

RefImpl构造函数

private _value:T private _rawValue:T public dep?Dep = undefined *public reaonly __v_is_ref = true *

这个属性就在构造的时候

然后这个构造函数就有意思了 深度响应式value是__v_isShallow 为真,就是直接返回value了 shallowRef()就会直接得到数据 为假就会直接 value = toReactive(value) rawValue=toRaw(value)就完成了响应式数据了

使用ref,就必须加上value(不包括模板中)

  • track 绑定
  • trigger 触发

get value

ref不能去解构的,而且必须去加上value,在script中,因为就只给value 给了访问器,去调用 traceRefValue(this),这里还返回了this._value

set value

会去判断 this.__v_isShallow存在吗,然后会去判断 isShallow(newVal) || isReadonly(newVal)

然后在这里 得到新数据 newval = ? newval :toRaw(newVal) 然后使用Object.is方法来判断两个对象是不是一致,学到了 然后就给_rawValue设置为newvalue 然后根据之前的判断的useDetieve,给value赋值属性,重新生成ToReactive 这个地方会不会有响应式数据,应该会有一些更新合并吧?一个是compiler会做的吧 然后触发triggerRefValue(this,newVal)

数据的__v_isShallow为true表示ref 数据的__v_isShallow为true表示shallowRef

export function isReadonly(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_READONLY])
}

export function isShallow(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_SHALLOW])
}

直接返回Boolean数据!!a(小知识点,哈哈哈哈) 标识符reactiveFlags

export const enum ReactiveFlags {
  SKIP = '__v_skip',
  IS_REACTIVE = '__v_isReactive',
  IS_READONLY = '__v_isReadonly',
  IS_SHALLOW = '__v_isShallow',
  RAW = '__v_raw'
}

vue2采用object.defineproperty vue3采用proxy 其实还有有问题,但是proxy给整体都拦截,就解决数组的问题 ToRaw才是去实现响应式数据的关键

set value(newVal) 就得到了新的数值

明天我去试试看一看能不能去修改这个属性。

reactive

这个才是vue响应式数据的生成者 调用createReactiveObject函数

createReactiveObject

reactive

readonly

shallowReadonly

toRaw

第一次进来应该是raw为false,所以走走observed 要是这个属性存在,就一直递归,一直到退出来

export function toRaw<T>(observed: T): T {
  const raw = observed && (observed as Target)[ReactiveFlags.RAW]
  return raw ? toRaw(raw) : observed
}

ref,reactive其实就是vue2时期的observed,想到了rx.js函数式编程了