Vue.js 是一个渐进式 MVVM 框架,目前被广泛使用,也成为目前前端技术中颇具代表性的一个框架。
按 Vue 作者的说法,Vue(及其生态)是一个渐进式 MVVM 框架,可以按照实际需要逐步进阶使用更多特性。
声明式渲染
简单来说,声明式渲染即希望开发者更多地表达 “想要什么”,而不用太关心想要的效果的实现细节。例如,我们希望页面上有一个 2x2 的表格,而命令式的实现方式是使用 Canvas 自己画:
我们需要自己关心实现细节,例如每一条线的坐标、每一条表格线的绘制等等。所幸 HTML 为我们提供了 <table> 元素,可以让我们更简单地实现表格:
相比 Canvas 的表格,我们只需要说明需要多少行,每一行有多少个单元格即可,不用自己关注绘制细节。这个例子可以让我们对 “声明式渲染” 有一个更直观的认知。
而在 Vue 中,开发者可以直接通过模板指令来表达 “想要什么”,并不用关心它的底层实现。常见的指令如 v-if、v-for、v-show 等都是同样的作用。此外 Vue 还可以声明式地表达对数据的渲染逻辑,例如用 {{message}} 来表示 “在此处显示变量 message 的值”,而不用关心 message 的变量是如何被填入 DOM 对象中。
组件系统
每一个程序员都知道 “高内聚 低耦合” 的编程原则,也都知道代码复用的重要性。但在前端代码中如何实现 “高内聚 低耦合”,以及前端代码复用,并不是一件容易的事情。对于 JavaScript,尚可以使用模块化来解决内聚和复用的问题,但一旦涉及到结构(HTML)和样式,事情就不容易了。
Vue 为开发者提供了 “组件” 的概念,一个组件即一组关联的结构和逻辑。组件内部可以方便地使用声明式渲染将逻辑和结构关联起来,实现组件的高内聚。例如 Vue 官方文档的一个组件例子:
这个例子中,template 中定义了组件的结构,并且声明式地将 count 变量显示到 <button> 的内容中。在 <button> 被点击时改变 count 的值。可以看到,组件内部的结构和逻辑都是非常容易互相访问和操作的。而在组件外部,不管是 count 变量还是 <button> 结构,都无法直接进行访问和操作。如果需要外部进行访问和操作,则需要定义相应的接口或者事件。这非常符合 “高内聚 低耦合” 的思想。
组件一旦定义好之后即可被重复使用:
从而很好地解决前端代码复用的问题。
客户端路由和状态管理
针对单页面应用,客户端路由的支持是必不可少的一个功能。通过客户端路由,开发者可以根据不同的 URL 加载不同的前端组件(有时候也称为 “页面”),也可以允许用户通过跳转的形式在不同的前端组件之间跳转。
要支持客户端路由,首先需要对当前 URL 进行解析,获取当前访问的页面地址以及参数等信息,然后根据开发者定义的路由与组件的对应关系(路由表)找到页面地址对应的组件,并负责加载和运行组件。
Vue 官方的客户端路由被放到一个独立的库 vue-router 中。开发者也可以根据需要选用。
随着应用复杂度的上升,页面的数据会越来越多,且同一个数据关联多个组件的情况会越来越多。此时数据如何组织、如何定义与组件的关联关系、如何确保变更会同步到每一个关联的组件中就变得非常重要。此时可能就需要使用 “状态管理” 的库来辅助开发者进行页面状态的管理。
状态管理库会提供全局的状态(state)对象,并定义一系列读写状态的方法。组件中只要使用状态管理提供的读写方法读写状态即可。
Vue 官方也提供了状态管理库 vuex,可供复杂应用使用。
编译 / 构建工具
借助构建工具的力量,Vue 还可以提供更好的开发体验。例如基于 webpack 强大的 loader 机制,style-loader 和 css-loader 可以允许开发者在 JS 文件中直接引入 CSS 文件。
借鉴这一思路,Vue 推出了单文件组件(Single File Component,简称 SFC)格式.vue,即允许开发者将同一组件的结构、样式、逻辑全部写在同一个文件中,然后由 vue-loader 在编译阶段将结构和逻辑都编译成 JS 文件,将 CSS 部分借用上述 style-loader 和 css-loader 同样的机制挂载到页面中。
单文件组件的推出使得 Vue 的文件组织又上一个台阶,我们可以更明确地在文件层面就定义好组件,同时由于 vue-loader 的支持,组件也可以通过各种机制(例如 npm)在不同项目间得以复用。
除了单文件组件之外,Vue 也推出了 CLI 工具 vue-cli,方便开发者更好地初始化项目、搭建项目开发环境并完成构建工作。
总结
通过上述说明,希望大家能更好地理解 “Vue 是一个渐进式的 MVVM 框架” 的含义,它允许我们只用声明式渲染这一点点特性,也允许我们最后加上客户端路由和状态管理来支持大型项目。正因为这样的设计,使得 Vue 上手也非常容易,不用一次学习所有特性的使用。
了解 Vue 渐近式的含义,也可以让我们在后续的源码解读中能清楚地知道每一章的源码在 Vue 生态中的位置。