渲染器
7.渲染器的设计
7.1渲染器与响应系统的结合
利用响应式系统,可以让渲染过程自动化:
const count = ref(1)
effect(() => {
renderer(`<h1>${count.value}</h1>`, document.getElementById('app'))
})
count.value++ // 页面会自动更新
7.2渲染器的基本概念
渲染器的作用是把虚拟DOM渲染为特定平台上的真实元素。
渲染器把虚拟DOM节点渲染为真实DOM节点的过程叫作挂载(mount),Vue组件中的mounted钩子会在挂载完成时触发,所以在mounted钩子中可以访问真实DOM元素。
render函数的基本实现如下:
function createRenderer() {
function render(vnode, container) {
if (vnode) {
patch(container._vnode, vnode, container)
} else {
if (container._vnode) {
container.innerHTML = ''
}
}
container._vnode = vnode
}
return {
render
}
}
7.3自定义渲染器
在浏览器平台上,渲染器可以利用DOM API完成DOM元素的创建、修改和删除。为了让渲染器不直接依赖浏览器平台特有的API,将这些操作抽象成可配置的对象。用户可以在调用createRenderer函数创建渲染器的时候指定自定义的配置对象,从而实现自定义的行为。
function createRenderer(options) {
const {
createElement,
insert,
setElementText
} = options
function mountElement(vnode, container) {
const el = createElement(vnode.type)
if (typeof vnode.children === 'string') {
setElementText(el, vnode.children)
}
insert(el, container)
}
function patch(n1, n2, container) {
if (!n1) {
mountElement(n2, container)
} else {
// ...
}
}
function render(vnode, container) {
if (vnode) {
patch(container._vnode, vnode, container)
} else {
if (container._vnode) {
container.innerHTML = ''
}
}
container._vnode = vnode
}
return {
render
}
}
const renderer = createRenderer({
createElement(tag) {
console.log(`创建元素${tag}`)
return { tag }
},
setElementText(el, text) {
console.log(`设置${JSON.stringify(el)}的文本内容:${text}`)
el.textContent = text
},
insert(el, parent, anchor = null) {
console.log(`将${JSON.stringify(el)}添加到${JSON.stringify(parent)}下`)
parent.children = el
}
})
const vnode = {
type: 'h1',
children: 'hello'
}
const container = {
type: 'root'
}
renderer.render(vnode, container)
结果如下: