《Vue.js设计与实现》 第七章 渲染器的设计

7.1 渲染器与响应系统的结合

最简单的渲染器及其使用

// 渲染器
function renderer(domString, container) {
  container.innerHTML = domString
}

// 使用
let count = 1
renderer(`<h1>${count}</h1>`, document.getElementById('app'))

渲染器与响应式系统结合

const count = ref(1)
effect(() => {
  renderer(`<h1>${count.value}</h1>`, document.getElementById('app'))
})
count.value++

7.2 渲染器的基本概念

renderer 来表达“渲染器”
render 来表达“渲染”
mount(挂载):渲染器把虚拟 DOM 节点渲染为真实 DOM 节点的过程。

patch:render() 函数里 执行patch,patch() 既可以用来打补丁,也可以用来执行挂载。

7.3 自定义渲染器

最简单的渲染器的使用

const vnode = {
  type: 'h1',
  children: 'hello'
}
// 创建一个渲染器
const renderer = createRenderer()
// 调用 render 函数渲染 vnode
renderer.render(vnode, document.querySelector('#app'))

渲染器的定义

function createRenderer() {
  function patch(n1, n2, container) {
    // to-do 渲染逻辑
  }

  function render(vnode, container) {
    if (vnode) {
      patch(container._vnode, vnode, container)
    } else {
      if (container._vnode) {
        container.innerHTML = ''
      }
    }
    container._vnode = vnode
  }
  return {
    render
  }
}

渲染器逻辑

function patch(n1, n2, container) {
  // 挂载-n1不存在
  if (!n1) {
    mountElement(n2, container)
  } else {
    // 打补丁-n1存在
    // to-do 打补丁逻辑
  }
}

挂载节点

function mountElement(, container) {
  // 创建 DOM 元素
  const el = document.createElement(vnode.type)
  // 处理子节点,如果子节点是字符串,代表元素具有文本节点
  if (typeof vnode.children === 'string') {
    // 因此只需要设置元素的 textContent 属性即可
    el.textContent = vnode.children
  }
  // 将元素添加到容器中
  container.appendChild(el)
}

如果要设计成不依赖于浏览器平台的通用渲染器,可以将document.createElement、el.textContent 以及 appendChild 等浏览器特有的API,抽离出来。使用时传入特定平台的方法即可。

posted @ 2024-04-15 20:40  Better-HTQ  阅读(10)  评论(0编辑  收藏  举报