01_Vue3设计与实现之设计思路

451 阅读2分钟

vue的重要概念:①声明式描述UI;②渲染器;③组件;④模板。

一、声明式UI

声明式UI使用与HTML标签一致的方式描述DOM元素,组件其实就是JavaScript对象,也就是虚拟DOM,怎么从虚拟DOM转换成真正的DOM呢,是通过渲染器也就是render函数实现的

二、渲染器

vue通过render函数将我们写的虚拟DOM转换成真正的DOM image.png

  • 渲染器主要做了哪些事呢(虚拟DOM→真实DOM)?
    • 1、创建元素|组件
    • 2、为元素添加属性和事件
    • 3、处理子元素,也就是调用子元素的render函数
  • 渲染函数的简单实现
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="./渲染器.js"></script>
  <script>
    const vnode = {
      tag: 'div',
      props: {
        onClick: () => {
          alert('hello world')
        }
      },
      children: '点我呀'
    }
    render(vnode, document.body)
  </script>
</body>
</html>
// 渲染元素
function mountElement(vNode, container) {
  const { tag, props, children } = vNode
  const el = document.createElement(tag)

  for (const key in props) {
    // 以on开头说明是事件,添加事件
    if (/^on/.test(key)) {
      el.addEventListener(key.substr(2).toLowerCase(), props[key])
    }
  }
  // 如何子级是String类型,说明是个文本类型的节点,创建并追加到el元素上
  if (typeof children === 'string') {
    el.appendChild(document.createTextNode(children))
  } else if (Array.isArray(children)) {
    // 如果子级是数组需要遍历渲染元素
    children.forEach(child => {
      render(child, el)
    })
  }

  container.appendChild(el)
}
// 渲染组件
function mountComponent(vNode, container) {
  const { tag } = vNode
  const subtree = tag.render()
  render(subtree, container)
}

// 渲染函数
function render(vNode, container) {
  if (typeof vNode === 'string') {
    mountElement(vNode, container)
  } else if (typeof vNode === 'object') {
    mountComponent(vNode, container)
  }
}

三、组件

组件就是一组DOM元素的封装,可以是函数也可以是对象,需要有render函数来指定描述的内容

四、模板

vue中有两种写组件的方式,一种是上面提到的渲染函数,另外一种就是模板了,也就是<template>,template是怎么显示到页面上的呢,首先他需要通过编译器把模板编译成渲染函数,然后再通过渲染函数把虚拟DOM转换成真正的DOM image.png