马上2023年了,Vue还有人用吗?

时间:2022-12-05 17:02:45

Vue.js 是一个渐进式 MVVM 框架,目前被广泛使用,也成为目前前端技术中颇具代表性的一个框架。

按 Vue 作者的说法,Vue(及其生态)是一个渐进式 MVVM 框架,可以按照实际需要逐步进阶使用更多特性。

马上2023年了,Vue还有人用吗?

Vue 渐进式示意图

声明式渲染

简单来说,声明式渲染即希望开发者更多地表达 “想要什么”,而不用太关心想要的效果的实现细节。例如,我们希望页面上有一个 2x2 的表格,而命令式的实现方式是使用 Canvas 自己画:

// 获取画面和context
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

// 定义宽高和行列数
const width = 200, height = 100;
const colCount = 2, rowCount = 2;

// todo:定义画笔颜色

// 画横线
for(let i = 0; i <= rowCount; i++){
ctx.moveTo(0, height / rowCount * i);
ctx.lineTo(width, height / rowCount * i);
}

// 画竖线
for(let i = 0; i <= colCount; i++){
ctx.moveTo(width / colCount * i);
ctx.lineTo(width / colCount * i, height);
}

document.body.appendChild(canvas);

我们需要自己关心实现细节,例如每一条线的坐标、每一条表格线的绘制等等。所幸 HTML 为我们提供了 <table> 元素,可以让我们更简单地实现表格:

<table>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>

相比 Canvas 的表格,我们只需要说明需要多少行,每一行有多少个单元格即可,不用自己关注绘制细节。这个例子可以让我们对 “声明式渲染” 有一个更直观的认知。

而在 Vue 中,开发者可以直接通过模板指令来表达 “想要什么”,并不用关心它的底层实现。常见的指令如 v-ifv-forv-show 等都是同样的作用。此外 Vue 还可以声明式地表达对数据的渲染逻辑,例如用 {{message}} 来表示 “在此处显示变量 message 的值”,而不用关心 message 的变量是如何被填入 DOM 对象中。

组件系统

每一个程序员都知道 “高内聚 低耦合” 的编程原则,也都知道代码复用的重要性。但在前端代码中如何实现 “高内聚 低耦合”,以及前端代码复用,并不是一件容易的事情。对于 JavaScript,尚可以使用模块化来解决内聚和复用的问题,但一旦涉及到结构(HTML)和样式,事情就不容易了。

Vue 为开发者提供了 “组件” 的概念,一个组件即一组关联的结构和逻辑。组件内部可以方便地使用声明式渲染将逻辑和结构关联起来,实现组件的高内聚。例如 Vue 官方文档的一个组件例子:

Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

这个例子中,template 中定义了组件的结构,并且声明式地将 count 变量显示到 <button> 的内容中。在 <button> 被点击时改变 count 的值。可以看到,组件内部的结构和逻辑都是非常容易互相访问和操作的。而在组件外部,不管是 count 变量还是 <button> 结构,都无法直接进行访问和操作。如果需要外部进行访问和操作,则需要定义相应的接口或者事件。这非常符合 “高内聚 低耦合” 的思想。

组件一旦定义好之后即可被重复使用:

<div >
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>

从而很好地解决前端代码复用的问题。

客户端路由和状态管理

针对单页面应用,客户端路由的支持是必不可少的一个功能。通过客户端路由,开发者可以根据不同的 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 生态中的位置。