第一天
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函数式编程了