Alpine.js 如何火起来的!比 React/Vue 如何?
大家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
前言
前端 JavaScript 框架的创新是这个时代最伟大的技术文化现象之一。Alpine 发音为 /??lpa?n/,中文为阿尔卑斯山、高山的、高山植物等,是近来名声大噪的框架之一。 Alpine 是一个极简主义的框架, 它以精简、易于掌握的方式提供强大的功能。
正如 Alpine.js 官方文档所描述的那样,Alpine 的 API 是一个包含 15 个 Attributes(x-data、x-bind、x-on、x-text、x-html、x-model、x-show、x-transition、x-for、x-if、x-init、x-effect、x-ref、x-cloak、x-ignore)、六个 Properties($store、$el、$dispatch、$watch、$refs、$nextTick) 和两个方法(Alpine.data、Alpine.store)的集合, 这是一个非常小的 API 配置文件。 极简主义目的是以整洁的格式提供反应性,并增加了一些相关细节,如事件和 store。
根据项目作者 Caleb Porzio 的说法:
Alpine.js以较低的成本为您提供了大型框架(如Vue或React)的反应性和声明性,开发者可以保留DOM,并按自己认为合适的方式进行处理!
总体来说,Alpine.js 是一个用于构建交互式用户界面的小型 JavaScript 框架。本文将带大家领略 Alpine.js,以便了解它提供的功能以及是否需要在项目中使用。
1.Alpine 的使用场景?
Alpine 适用于简单的静态网站或由其他后端框架提供支持的服务器渲染的应用程序,开发者需要做的就是向 UI 添加一些小的交互元素。 例如:模态框、下拉菜单、选项卡、带过滤器的列表等等。 另一个用例是在遗留项目中替换 jQuery,因为它涵盖了所有相同的功能,但库大小更小,语法更紧凑。
同时,如果应用程序是一个单页应用程序也是有意义的,这通常会将大部分逻辑放在前端,从而有相当大的组件树和大量状态通信。当然,在这种情况下,也许最好使用 Vue 或 React 等成熟的框架/库。但是,相比于 Vue 或 React,Alpine.js 也有一些自己的优势。
2.Alpine 提供极简 API 使用示例
看一个简单例子:
<html>
<head>
<script
src="https://unpkg.com/alpinejs@3.10.3/dist/cdn.min.js"
defer
></script>
<!-- 引入alpinejs数据 -->
</head>
<body>
<div x-data="">
<span x-text="'Text literal'"></span>
</div>
</body>
</html>
除了通过 CDN 引入 Alpine 包(您可以在此处了解延迟语义),这里仅有的两个与 Alpine 相关的东西是指令 x-data 和 x-text。
如果将其放入系统的 HTML 页面中并在浏览器中查看,您将看到消息输出“Text literal”。 虽然不是特别令人印象深刻,但这个应用程序展示了 Alpine 的两个有趣的方面。
首先,为了使用反应式,必须将标记包含在 x-data 指令中。 如果删除该指令,x-text 将不会生效。 本质上,x-data 指令创建了一个 Alpine 组件。 在此示例中,x-data 指令为空。 在实际使用中,你几乎总是有数据在那里; 毕竟,编写的组件的目的是响应数据。
要注意的第二件事是可以将任何有效的 JavaScript 放入 x-text 中。 所有的 Alpine 指令都是如此。
2.1 x-data 和 x-text 元素
以下面代码为例:
<!-- x-data定义数据 -->
<div x-data="{ message: 'When in the course of human events...' }">
<span x-text="message"></span>
<!-- x-text读取数据 -->
</div>
现在页面将输出 message 的内容。 您可以看到 x-data 定义了一个普通的 JavaScript 对象,它只有一个字段“消息”,其中包含 message 的内容。 x-text 指令引用了此对象字段。
2.2 Alpine.js 中的反应性
下面将使用反应性来修复声明中的错误,以下面代码为例:
<div x-data="{ pronoun: 'men' }">
<!-- 提供x-on:click指令 -->
<button x-on:click="pronoun = 'people'">Fix It</button>
<span x-text="`all ${pronoun} are created equal`"></span>
<!-- x-text读取数据 -->
</div>
这里新增了一个按钮,它有一个 x-on:click 指令。 此点击事件的处理程序将旧的默认 pronoun 替换为 people,反应性负责更新 x 文本中的引用。
2.3 数据中的函数
Alpine 中的数据属性 x-data 是功能齐全的 JavaScript 对象。可以考虑另一种方法来处理上述要求 。比如下面的示例:
<div
// 通过fixIn定义方法
x-data="{
pronoun: 'men',
fixIt: function(){
this.pronoun = 'people';
}
}"
>
// 添加点击事件
<button x-on:click="fixIt()">Fix It</button>
<span x-text="`all ${pronoun} are created equal`"></span>
</div>
可以看到 x-data 包含一个由点击处理程序调用的 fixIt 方法。另外,请注意,有时您会看到从 x-data 指令调用脚本标记中定义的函数的应用程序代码,这是个人偏好,它的运行方式与内联 x-data 完全相同:
<div x-data="myDataFunction()">...</div>
// x-data指定了一个方法
<script>
function myDataFunction() {
return {
foo: "bar"
}
}
</script>
2.4 远程数据
假设想从外部 API 加载 JSON 格式的数据,要做的第一件事是在页面加载时主动触发数据请求。 为此,可以使用 x-init 指令。
<div
x-data="{
presidents: []
}"
// 直接在x-init里面调用原生fetch
x-init="(
async () => {
const response = await fetch('https://raw.githubusercontent.com/hitch17/sample-data/master/presidents.json');
presidents = await response.json();
}
)"
>
<!-- 读取数据 -->
<span x-text="presidents"></span>
</div>
首先,x-data 指令应该很清楚:它只有一个带有空数组的 presidents 字段, span 元素中的 x-text 输出该字段的内容。
x-init 包含了一个自执行函数中。 这是因为 Alpine 需要一个函数,而不是函数定义。一旦获取到数据则赋值给 presidents 变量,Alpine 将其作为 x-data 对象的一部分。
注意:Alpine.js 使来自 x-data 的数据可用于同一上下文中的其他指令函数(如 x-init)。
2.5 Alpine.js 交互
上面的示例应用程序正在从远程提取数据并将其保存到状态中。 但是请注意,它输出的是 [Object]、[Object] 字符串,与预期不符合。这时候就要用到迭代指令,x-for:
<div x-data="...">
<ul>
<!-- x-for进行循环迭代 -->
<template x-for="pres in presidents">
<li>
<div x-text="pres.president"></div>
From: <span x-text="pres.took_office"></span> Until:
<span x-text="pres.left_office"></span>
<!-- x-text继续读取 -->
</li>
</template>
</ul>
</div>
代码示例包含普通的无序列表,包含 HTML 模板 template 元素,其中包含一个 x-for 指令。 该指令的运行方式与在其他响应式框架中看到的类似。 它允许指定一个集合、一个标识符。以上示例输出结果如下:
2.6 onClick 时显示/隐藏
修改页面模板如下:
<template x-for="pres in presidents">
<li><div x-text="pres.president" x-on:click="pres.show = ! pres.show"></div>
<div x-show="pres.show">
<!-- onclick和x-show进行显隐设置 -->
From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
</div>
</template>
以上示例在 div 上使用 x-show 指令, x-show 的值决定了内容是否可见。 例子是由 pres.show 字段决定的。要更改 pres.show 的值,可以将 x-on:click 处理程序添加到标头。 此处理程序只是切换 pres.show 的 true/false 值。
2.7 添加过渡动画
Alpine 包含可应用于显示/隐藏功能的内置过渡动画,可以直接使用:
<div x-show="pres.show" x-transition>
<!-- x-transition添加动画 -->
From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
</div>
带有 x-show 指令的元素现在也有一个 x-transition 指令。 默认情况下,Alpine 应用合理的转换。 在这种情况下,过渡是一种滑动和淡入淡出的效果。 您可以随意自定义过渡,包括将您自己的 CSS 类应用到动画的各个阶段。
2.8 绑定数据到 input
需要添加一个绑定到数据的 input 控件,然后根据该值过滤返回的数据集。
<div
x-data="{
filter: '',
presidents: [],
getPresidents: function(){
return this.presidents.filter(pres => pres.president.includes(this.filter) )
}
}"
...
<input
x-model="filter"
/>
<!-- input通过x-model读取数据 -->
<ul>
<template x-for="pres in getPresidents"></template>
<!-- x-for循环数据 -->
</ul>
请注意,x-data 对象现在有一个“filter”字段。 这是通过指向“过滤器”的 x-model 指令双向绑定到 input 元素的。
更改了模板 x-for 指令以引用新的 getPresidents() 方法,该方法在 x-data 对象上实现。 此方法使用标准的 JavaScript 语法根据元素是否在过滤字段中绝对。
3.Alpine.js vs. React vs. Vue
从 Github 数据来看,目前 Alpine.js 的 star 数据为 23k,比 React 的 203K 和 Vue 的 202K(Vue 3 有独立仓库,不算在里面)差距不少,但是考虑到 Alpine.js 项目创建才短短的 3 年时间,而 React 已经 11 年, Vue 已经 9 年,Alpine.js 能有这个数据已经非常不易。下面再看看周数据下载量:
目前 Alpine.js 的周下载量为 141k,React 为 19,694K,而 Vue 为 4,038K(除去 Vue3 数据)。从这点来看,目前 Alpine.js 和 React、Vue 也有一定的差距。但是,从这个周下载量数据来看,Alpine.js 的生产部署量应该也不小。
4.本文总结
Alpine.js 包括一些更高级别的功能,特别是中央 store 和事件系统,以及插件架构和生态系统。如果您有使用其他响应式框架的经验,Alpine 应该足够熟悉,可以很快上手。
Alpine.js 避免了组件之间的显式连接(例如,没有父子属性)。 相反,它通过 $dispatch 指令使用浏览器环境(即窗口)作为事件总线。 这符合 Alpine 的理念,即添加足够的功能来增强现有功能。因为篇幅有限,文章并没有过多展开,如果有兴趣,文末的参考资料提供了大量优秀文档以供学习。
参考资料
https://www.infoworld.com/article/3682135/intro-to-alpinejs-a-javascript-framework-for-minimalists.html
https://lightit.io/blog/when-to-use-alpine-js/
https://alpinejs.dev/