mini-vue3实现记录-渲染器

82 阅读1分钟

渲染器,顾名思义就是用来执行渲染任务的,通过为渲染器提供不同的渲染接口,实现框架对跨平台的支持。

首先思考一个问题:如何将渲染器与响应式系统相关联?换言之,如何实现响应式数据更新,页面的数据也随之更新?其实很简单,假设renderer函数是我们的渲染函数,定义一个ref对象count,我们将渲染函数传入count的副作用函数,这样当count响应式对象需要触发依赖时,渲染函数都会被重新执行,也就达到了页面更新的效果。

function renderer(content, container) {
    container.textContent = content
}
const count = ref(1)

effect(() => {
    renderer(`${count.value}`, document.getElementById("app"))
})
count.value ++

渲染器渲染相比,是一个更加宽泛的概念,渲染函数的职能仅仅是渲染,而渲染器还会执行诸如激活已有DOM元素等操作,还可以通过为渲染器传参来实现不同平台的渲染,因此我们不能只是简单的定义一个render函数,而需定义一个创建渲染器函数createRenderer.

createRenderer与不同渲染接口

我们提到,通过对createRenderer传参,可以实现提供不同平台的渲染接口,下面以canvas举例:

export function createRenderer(options) {
  const {
    createElement: hostCreateElement,
    patchProp: hostPatchProp,
    insert: hostInsert,
    remove: hostRemove,
    setElementText: hostSetElementText,
  } = options;
 ... 
 ...(){
     ...
     hostInsert(el, parent)
     hostRemove(el)
     ...
 }
}

// main.js内创建renderer对象,进行根元素挂载
const renderer = createRenderer({
  createElement(type) {
    if (type === "rect") {
      const rect = new PIXI.Graphics();
      rect.beginFill(0xff0000);
      rect.drawRect(0, 0, 100, 100);
      rect.endFill();

      return rect;
    }
  },
  patchProp(el, key, val) {
    el[key] = val;
  },
  insert(el, parent) {
    parent.addChild(el);
  },
});

renderer.createApp(App).mount(game.stage);

可以看到,我们为createRenderer提供了如创建元素、插入元素的渲染api,这些api会在renderer内部被调用。