Vue组件的实现原理详细分析

2023-01-04 09:53:00
目录
渲染组件组件更新父子组件setup函数emit 实现

渲染组件

一个组件内部必须要使用>

这是一个最简组件实例

const MyComponent = {
  // 组件名称,可选
  name: "MyComponent",
  // 组件的渲染函数,其返回值必须为虚拟 DOM
  render() {
    // 返回虚拟 DOM
    return {
      type: "div",
      children: `我是文本内容`,
    };
  },
};

渲染器中的 mountComponent 函数完成组件的渲染

function mountComponent(vnode, container, anchor) {
  // 通过 vnode 获取组件的选项对象,即 vnode.type
  const componentOptions = vnode.type;
  // 获取组件的渲染函数 render
  const { render } = componentOptions;
  // 执行渲染函数,获取组件要渲染的内容,即 render 函数返回的虚拟
  const subTree = render();
  // 最后调用 patch 函数来挂载组件所描述的内容,即 subTree
  patch(null, subTree, container, anchor);
}

组件更新

组件初始化步骤:

    取得>render 函数内将 this 指向 state,并将 state 作为第一个参数传入 render 函数

    将渲染任务包装到一个副作用函数 effect 里面,即可实现响应式更新数据

    若要使每次响应式数据修改后,effect 仅执行一次,则需要引入调度器概念

    这是书中给出的最简调度器实例

    即先把 effect 放入微任务队列,等执行栈清空再调出来执行

    // 任务缓存队列,set可以自动去重
    const queue = new Set();
    // 一个标志,代表是否正在刷新任务队列
    let isFlushing = false;
    // 创建一个立即 resolve 的 Promise 实例
    const p = Promise.resolve();
    // 调度器的主要函数,用来将一个任务添加到缓冲队列中,并开始刷新队列
    function queueJob(job) {
      // 将 job 添加到任务队列 queue 中
      queue.add(job);
      // 如果还没有开始刷新队列,则刷新之
      if (!isFlushing) {
        // 将该标志设置为 true 以避免重复刷新
        isFlushing = true;
        // 在微任务中刷新缓冲队列
        p.then(() => {
          try {
            // 执行任务队列中的任务
            queue.forEach((job) => job());
          } finally {
            // 重置状态
            isFlushing = false;
            queue.clear = 0;
          }
        });
      }
    }
    

    父子组件

    这是一个简单的父子组件代码

    // 子组件
    <template>
      <MyComponent :title="title" />
    </template>
    // 父组件
    const vnode = {
      type: MyComponent,
      props: {
        title: 'A Big Title'
      }
    }
    

    父组件更新导致子组件更新(被动更新)过程:

      父组件自更新渲染器检查 subTree 发现存在 vnode,则调用 patchComponent 实现子组件更新

      setup函数

      setup>

      他有如下两种返回值形式

      // 返回函数
      const comp = {
        setup() {
          return () => {
            return {
              type: "div",
              children: "give up for vuejs",
            };
          };
        },
      };
      // 返回对象
      const comp = {
        setup() {
          const count = ref(0);
          return {
            count,
          };
        },
        render() {
          return {
            type: "div",
            children: `count is ${this.count}`,
          };
        },
      };
      

      setup 接收两个参数,分别是 props 以及 setupContext

      setupContext 包含以下四个主要对象

        slots 插槽emit 自定义事件attrs 自定义属性expose 暴露

        emit>

        只需要实现一个 emit 函数并将其添加到 setupContext 对象中

        到此这篇关于Vue组件的实现原理详细分析的文章就介绍到这了,更多相关Vue组件实现原理内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!