思考
Vue的 setup函数可以接收 props,并且能通过this.xx获取props的数据
- setup可以接收props
- render可以通过this.xx获取props的数据
- props是只读的 接下来根据这3点逐步实现
实现setup接收props
重构实例对象中,新增props对象
/*
* @Author: Lin zefan
* @Date: 2022-03-21 22:08:11
* @LastEditTime: 2022-03-26 10:21:08
* @LastEditors: Lin zefan
* @Description: 处理组件类型
* @FilePath: \mini-vue3\src\runtime-core\component.ts
*
*/
function createComponentInstance(initVNode) {
return {
vnode: initVNode,
type: initVNode.type,
proxy: null,
setupState: {},
props: {},
};
}
在setupComponent函数中,初始化props
function setupComponent(instance, container) {
// 初始化props
initProps(instance);
// other code
}
initProps
/*
* @Author: Lin zefan
* @Date: 2022-03-26 10:02:13
* @LastEditTime: 2022-03-26 10:11:02
* @LastEditors: Lin zefan
* @Description: 初始化props
* @FilePath: \mini-vue3\src\runtime-core\componentProps.ts
*
*/
export function initProps(instance) {
/** 初始化props
* 1. 前面通过h函数去创建我们的节点,它的第二个参数可以接收props
* 2. h的返回格式 { type: component|string , props:{} , children:[]}
* 3. 前面又通过createComponentInstance函数去重构实例,所以是通过instance.vnode.props取得当前props
*/
instance.props = instance.vnode.props || {};
}
// 初始化setup返回值
function setupStatefulComponent(instance, container) {
// other code
const { setup } = component;
if (setup) {
/**
* 1. setup接收props
* 2. 执行setup
*/
const setupResult = setup(instance.props);
handleSetupResult(instance, setupResult);
}
}
实现props注册到this
componentPublicInstanceProxyHandlers.ts
/*
* @Author: Lin zefan
* @Date: 2022-03-23 17:52:57
* @LastEditTime: 2022-03-26 10:18:06
* @LastEditors: Lin zefan
* @Description:
* @FilePath: \mini-vue3\src\runtime-core\componentPublicInstanceProxyHandlers.ts
*
*/
import { hasOwn } from "../shared/index";
export const PublicInstanceProxyHandlers = {
get({ _: instance }, key) {
let { setupState, props } = instance;
// 获取 setup 返回的数据
if (hasOwn(setupState, key)) {
return setupState[key];
}
// 获取props数据
if (hasOwn(props, key)) {
return props[key];
}
// other code
},
};
shared/index
export function hasOwn(val, key) {
return Object.prototype.hasOwnProperty.call(val, key);
}
实现props只读
props只读vue内部做的是表层只读,用的是shallowReadonly,前面已经实现过shallowReadonly了,我们直接套用即可
// component.ts
// 初始化setup返回值
function setupStatefulComponent(instance, container) {
const { setup } = component;
if (setup) {
/**
* 1. setup接收props
* 2. 执行setup
*/
const setupResult = setup(shallowReadonly(instance.props));
handleSetupResult(instance, setupResult);
}
}