渲染器,顾名思义就是用来执行渲染任务的,通过为渲染器提供不同的渲染接口,实现框架对跨平台的支持。
首先思考一个问题:如何将渲染器与响应式系统相关联?换言之,如何实现响应式数据更新,页面的数据也随之更新?其实很简单,假设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内部被调用。