Vue3的开发方式不再使用Vue2的选项式
这个时候数据来源以及修改就成了问题
我们可以创建一个最简单的实例来作为分析例子
const { createApp, ref } = Vue;
createApp({
setup() {
debugger;
const message = ref("Hello vue!");
return {
message,
};
},
created() {
console.log("created")
},
}).mount("#app");
针对setup函数打端点,通过堆栈回溯可以找到setupStatefulComponent
函数进行调用
其中可以看到首先从Component组件的模板中获得了Setup,然后通过callWithErrorHandling
函数来防止setup出错进行调用
const { setup } = Component;
if (setup) {
pauseTracking();
const setupContext = instance.setupContext = setup.length > 1 ? createSetupContext(instance) : null;
const reset = setCurrentInstance(instance);
const setupResult = callWithErrorHandling(
setup,
instance,
0,
[
shallowReadonly(instance.props) ,
setupContext
]
);
}
其中最后一部分是setup传入的参数,我们可以发现
其中组件的setup函数的props数据来自于实例的instance.props
通过一层shallowReadonly
做浅包裹
而contexnt来自于instance.setupContext包含了emit,expose,attrs,slots四个参数,但是如果setup的参数没有进行使用不会进行创建
我们继续往下走可以走到handleSetupResult
函数中
其中可以发现如果是函数则将作为render模板,而如果为对象则会设置到实例的setupState上
function handleSetupResult(instance, setupResult, isSSR) {
if (isFunction(setupResult)) {
{
instance.render = setupResult;
}
} else if (isObject(setupResult)) {
instance.setupState = proxyRefs(setupResult);
}
而我们混入的this属性,根据调试可以确定实例在this的_
属性上,由此可以推断出以下常见数据所在位置
//setup数据 this['_'].setupState
//data数据 this['_'].$data
//render数据 this['_'].render
//props数据 this['_'].props
关于修改数据,其中setupState
最简单,他是通过ref函数创建的,而ref最后创建的是RefImpl
的类实例对象,根据代码可知直接设置value属性即可
class RefImpl {
constructor(value, isShallow2) {
this.dep = new Dep();
this["__v_isRef"] = true;
this["__v_isShallow"] = false;
this._rawValue = isShallow2 ? value : toRaw(value);
this._value = isShallow2 ? value : toReactive(value);
this["__v_isShallow"] = isShallow2;
}
get value() {
{
this.dep.track({
target: this,
type: "get",
key: "value"
});
}
return this._value;
}
set value(newValue) {
const oldValue = this._rawValue;
const useDirectValue = this["__v_isShallow"] || isShallow(newValue) || isReadonly(newValue);
newValue = useDirectValue ? newValue : toRaw(newValue);
if (hasChanged(newValue, oldValue)) {
this._rawValue = newValue;
this._value = useDirectValue ? newValue : toReactive(newValue);
{
this.dep.trigger({
target: this,
type: "set",
key: "value",
newValue,
oldValue
});
}
}
}
}
需要注意的是,Vue3中data属性是选项式data函数所返回的,而setup返回的是setupState属性,二者不能混为一谈,由于data其修改方式类似,暂且就不表了
除此之外还有一个props属性,props只有最顶层的数据触发才能进行修改,不能单纯的修改某个属性内容,例如
instance.props.info={...instance.props.info,title:"123456"}
才可以成功触发数据响应
而render一般不推荐进行修改,暂且就不表了~
结语
撒花~