作为前端开发者,对Html、css、JavaScript应该再熟悉不过了,它们曾被成为前端三大件,在差不多十年以前,掌握这三兄弟就不愁没工作了。但随着互联网时代的发展和技术的进步,掌握基本的三大件已不能满足前端工作。一方面是计算机和智能设备的普及,让页面在满足单一功能性的基础上,又增加了很多对于交互性的要求,这使得原生开发来实现所需要的成本增加;第二个是React(2013)、Vue(2014)等前端框架(库)的出现,也就是在这些框架出现之后,前端领域开始了翻天覆地的变化。
框架/库本质
像盖房子一样,不管最终的效果多么富丽堂皇,多么漂亮,其底层一定还是水泥、钢筋、木材等。同样,以上这些技术之所以叫框架,也就是因为他们只不过就是在原生开发的基础上做了一层包装,将常用功能封装,从而提高其可维护性、可扩展性等,提高开发人员开发效率。
小知识:用框架搭建项目的工具被称为脚手架,和盖房子时搭建的基础设施平台名称相同。
这样我们就明白,不论其具有这样特殊的使用方法,底层一定还是操作 DOM,将其渲染到页面上,也就是说无论如何根本绕不过去『原生渲染』的这一步。
渲染方式
前面说了无论哪种方式,都绕不开原生开发的渲染阶段,目前主流的调用原生渲染的方式大概分为两种:「声明式和命令式」
- 声明式:神说要有光,于是就有了光
顾名思义,声明式的方式就是发起声明,只关心结果,不关心过程,至于底层是怎样实现的,关我何事,用代码表示为:
<template> <button @click="alert('click!')">Click me!</button> </template>
- 命令式
即按照步骤一步一步进行,可以比喻成做菜,首先洗菜,然后切菜,点火、倒油、炒菜、放盐…,每一步都需要明确,原生代码就是典型的命令式编码:
const button = document.createElement('button') button.onclick = function() { alert('click') } document.body.append(button)
那框架是如何实现命令式的呢,这就是这篇文章要要讨论的问题。
模板(Template)
一套类似与html标签的表示页面结构的字符串,如:
const str = ` <template> <div>let's go</div> </template> `
可以看得出除了类型是 string 之外,长得和我们认识的 HTML 简直一模一样,但以上代码片段只为 vue 识别的内容,浏览器并不知道它是什么,所以需要通过编译器将其转换成浏览器识别的内容。
编译器(Compiler)
vue 并不是直接将模板字符串作为页面元素直接生成,而是需要一个编译器来将模板字符串编译成虚拟 DOM(VNode),再由渲染函数来生成真实 DOM 并渲染到页面上:
虚拟DOM,即一个用来描述真实 DOM 的 JS 对象,也可以是函数,如果是函数,要在执行后返回符合规则的对象
// 调用 Compiler 编译得到树形结构的数据对象 VNode(虚拟 DOM) const VNode = Compiler(htmlStr)
上面我们看到,通过Compiler函数将模板字符串转换成了VNode,简化后的具体内容如:
const VNode = { tag: 'div', children: "let's go" }
剩下最后一步,就是由渲染函数来进行渲染。
渲染函数(Render)
调用h函数的渲染函数,将虚拟 DOM 转化成真正的 DOM 渲染到页面上
// 调用渲染函进行渲染页面 render(VNode, document.body)