前端组件化开发的 7 条经验总结
2021年10月 · 预计阅读时间: 10 分钟
自从 2010 年第一份工作接触了前后端半分离的开发方式之后,在后面的这些年里,对前端的组件化开发有了更全面一点的认识,组件化在我们的前端开发中,对提高开发效率、代码的可维护性和可复用性有很大帮助,甚至对跟设计师沟通的效率和企业的品牌形象都有着深刻的影响。这篇文章就把我在开发中总结的一些组件化开发经验分享一下。示例中的所有代码都是伪代码,你可以按照实际情况应用到 React 或 Vue 的项目中。
前端组件化发展历史
在讨论组件化开发之前,我们先看看前端组件化开发的发展历史。网页开发刚起步时,并没有『前端』这个概念,更不用提组件化了。当时,网页只是作为可以在浏览器中浏览的富文本文件,开发网页就是使用一些标签让浏览器解析并显示。受制于 HTML 只是描述式的语言,网页中的代码没有办法复用,即使是类似的页面,都需要复制粘贴大量的重复代码:
<!-- index.html -->
<nav>
<!-- 导航 -->
</nav>
<main>
<!-- 内容 -->
</main>
<footer>
<!-- 页脚 -->
</footer>
<!-- blogPost.html -->
<nav>
<!-- 相同的导航 -->
</nav>
<main>
<!-- 不同的内容 -->
</main>
<footer>
<!-- 相同的页脚 -->
</footer>
后来随着模板引擎的出现,可以把网页的代码分割成片段(Fragments)或模板(Templates),例如导航,内容,页脚等等,之后在需要的地方,使用引入(Include)语法,把这些片段引入进来,从而避免重复代码,这样形成了组件化的雏形,常见的动态脚本语言都有自己的模板引擎,例如 PHP、ASP 和 JSP:
<!-- nav.jsp -->
<nav>
<!-- 导航 -->
</nav>
<!-- index.jsp -->
<jsp:include page="nav.jsp" />
只是这些片段在数据管理方面仍然会比较麻烦,还是需要使用客户端 JavaScript 脚本,手动控制数据和 HTML 视图的同步。而对于样式,也还是存在全局污染的问题。 再后来,有些高级的开发语言,例如 Java, 推出了基于服务器的组件化开发技术,例如 JSF (JSP 的后继),基于 MVC 设计模式,通过 Java Class (POJO) 定义数据模型(Model),为 JSF 页面模板提供数据。JSF 的数据模型中有事件和生命周期相关的方法,而模板和数据模型通信的方式是 Ajax,通过使用 JSF facelets 组件的方式,可以直接发送 Ajax 请求,调用模型中的方法:
<!-- index.xhtml -->
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
>
<h:commandButton id="submit" value="Submit">
<f:ajax event="click" />
</h:commandButton>
<h:outputText id="result" value="#{userNumberBean.response}" />
</html>
// UserNumberBean.java
@Named
@RequestScoped
public class UserNumberBean implements Serializable {
/* 其它代码省略 */
public String getResponse() {
if ((userNumber != null)
&& (userNumber.compareTo(dukesNumberBean.getRandomInt()) == 0)) {
return "Yay! You got it!";
}
if (userNumber == null) {
return null;
} else {
return "Sorry, " + userNumber + " is incorrect.";
}
}
}
代码来源:Jarkarta EE 官方示例 不过这种方式严格限定了编程语言,例如要用 JSF 技术就必须要使用 Java,并且样式污染的问题和客户端数据管理的问题仍然没有解决。 随着 Node.js 的普及,JavaScript 可以脱离浏览器运行了,并且带来了 npm 包管理器,基于 npm 庞大的工具链,可以 Node.js 的代码打包成浏览器中能够运行的代码。而这期间,产生了像 React、Vue 和 Angular 这样的、适合大型前端项目开发的库和框架。
React 和 Vue 目前的流行程度比较高一些,它们都是纯客户端的、组件化的 JS 库,不依赖任何后端编程语言,让程序员都能够快速上手。不过,随着项目规模的扩大,如何利用好这些库进行组件化开发,成了前端工程师必须要掌握的课题。
什么是组件
那么到底什么是组件呢?你想一下日常生活中,电脑上的硬件,例如显卡、内存、CPU,或者汽车的零部件:轮胎、发动机、方向盘等,这些都属于组件,它们组合起来能形成一个完整可用的产品,对于遵循了设计规范的组件,只要型号匹配,无论品牌、样式,都可以互相兼容。 我们 前端工程师其实就当于是一个工厂,我们需要按照一定的规范,产生出合格的网页组件,利用它们组装成完整的页面。组件一般包含 HTML 模板、CSS 样式和 JavaScript 数据逻辑,自成一体,可以直接在其它组件中使用,组件本身的模板、样式和数据不会影响到其它组件。组件还包含一系列可配置的属性,动态的产生内容。
常见的基础组件有按钮、导航、提示框、表单输入控件、对话框、表格、列表等,我们在它们的基础上又能组合出更复杂的组件,那么对于前端中的组件的定义就非常广泛了,小到一个按钮,大到一个页面都可以形成一个组件,例如两个相似的页面,可以复用一个页面组件,只需要通过修改组件的属性,来形成一个新的页面。
为什么要组件化开发
你可能也知道,React 和 Vue 其实也可以完全按照传统的网页开发方式进行开发,最多是把网页大体分成几个部分,放到单独的几个文件里就好了,对于简单的网站来说没什么问题,但是如果开发的是大型的应用,例如网页版的 QQ 音乐、微信、邮箱等,它们有大量的、细小的组件,并且重复出现,这时如果针对每个页面编写 HTML 和样式,那么就会造成太多冗余代码了。
<!-- playlist.html -->
<div class="card">
<div class="card__title"></div>
<div class="card_content"></div>
</div>
<!-- homepage.html -->
<div class="card">
<div class="card__title"></div>
<div class="card_content"></div>
</div>
<!-- user.html -->
<div class="card">
<div class="card__title"></div>
<div class="card_content"></div>
</div>
如果使用组件化的方式,我们可以把重复出现的页面内容定义成组件,这样就不用复制粘贴同样的代码了,减少代码的体积:
<!-- 伪组件 -->
<!-- Card.comp -->
<div class="card">
<div class="card__title"></div>
<div class="card_content"></div>
</div>
<!-- playlist.html -->
<Card />
<!-- homepage.html -->
<Card />
<!-- user.html -->
<Card />
当某个页面内容是复合组件时,那么可以直接把基础组件直接拿过来应用:
<Card>
<Title></Title>
<Button></Button>
</Card>