15-实现初始化props

82 阅读2分钟

思考

Vue的 setup函数可以接收 props,并且能通过this.xx获取props的数据

  1. setup可以接收props
  2. render可以通过this.xx获取props的数据
  3. 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);
  }
}