开始使用Alpine.js
Alpine.js是一个坚固的、最小的工具,用于在你的标记中构成行为。可以把它看作是现代网络的jQuery。它和Vue一样是非常反应式的,而且非常轻量级。Alpine.js的使用和设置非常简单。它不需要用NPM进行任何安装,CDN版本就能发挥足够的魔力。
Alpine.js不是Vue、React或Angular等成熟框架的替代品。相反,它是一个更轻的框架,适用于需要最小的JavaScript的应用程序中的最简单的需求,通常是服务器端渲染的Web应用程序。
当你需要简单的组件,如下拉、搜索输入,以及视图中一些你想切换的元素时,Alpine.js就会大放异彩。它还提供了非常大的灵活性。你可以保持你的标记简单,就像它一样,并在任何你想要的地方洒下行为,不需要任何费用。
先决条件
要继续学习本教程,你将需要
- 一个好的浏览器,最好是[Chrome]。
- 一个文本编辑器,你可以使用[VSCode]。
- 基本的HTML、CSS、[Bootstrap]和Javascript知识。
目标
在本教程结束时,你应该熟悉。
- [什么是Alpine.js]。
- Alpine.js中的[事件处理]。
- Alpine.js中的[状态管理]。
- Alpine.js中的[模板制作]。
本文将展示如何建立一个主要的应用程序来存储TODO,说明Alpine.Js的一些功能。
Alpine.js的安装
要开始使用该应用程序,我们首先要安装所有需要的依赖项,Alpine.js和Bootstrap CSS。
要安装Bootstrap,从官方网站上获得启动模板。用这个模板编辑一下,有正确的标题和一个基本的卡片和列表(Todos)。
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
.bg-pink {
background: pink;
}
.bg-trans {
background: rgba(0, 0, 0, 0.1);
}
</style>
<title>Alpine Todo</title>
</head>
<body class="container bg-pink">
<main class="row justify-content-center my-5 py-5">
<div class="card col-lg-5 px-5 py-5 shadow-sm bg-trans">
<div class="d-flex justify-content-between align-items-center">
<h2>Todos</h2>
<div>
<span class="badge bg-primary rounded-pill">All</span>
<span class="badge bg-white text-black rounded-pill">Opened</span>
<span class="badge bg-danger rounded-pill">Cancelled</span>
<span class="badge bg-success rounded-pill">Completed</span>
</div>
</div>
<ul class="list-group mt-3">
<li class="list-group-item">
<input type="text" placeholder="Enter New Todo" class="form-control">
<small class="text-info">Hit Enter To Save</small>
</li>
<li class="list-group-item list-group-item-success">First Item</li>
<li class="list-group-item list-group-item-danger">First Item</li>
<li class="list-group-item">First Item</li>
</ul>
</div>
</main>
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</body>
</html>
在设计好一切后,让我们安装Alpine.js。
Alpine.js可以用多种方式安装,这与其他客户端的JavaScript库或框架类似。
<script defer src="https://unpkg.com/alpinejs@3.4.2/dist/cdn.min.js"></script>
或者,在你的其他项目中,你可以使用NPM安装Alpine.js。运行npm install 命令。
npm install alpinejs
安装后,你可以开始使用Alpine.js,无需配置。在你的主JavaScript文件中导入并初始化它。
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()
在这一点上,你的应用程序应该看起来像这样。
基于这个设计,我们有一个Todos的列表。我们必须创建并存储一些Todos,这些Todos可以作为列表项进行迭代,使这些Todos成为动态的。
Alpine.js的事件处理
使用我们的Todo应用程序,我们希望得到用户的输入。用户应该输入一个todo项目并按下'Enter'键来保存他们的todo。我们必须监听输入的keyup事件,以了解用户何时按下'Enter'键。
Alpine使监听浏览器事件并按你的意愿做出反应变得简单,并为我们提供了x-on指令来实现这一目标。这个指令让我们可以像我们使用普通的JavaScript一样监听事件。
为了看看这个指令是如何工作的,我们给第一个列表项添加一个点击监听器,每次点击都会发出 "Hi "的提示。
<li class="list-group-item list-group-item-success" x-data x-on:click="alert('Hi')">First Item</li>
先不要担心x-data 指令。
看看那是多么简单。
其他事件如变化、模糊和焦点也可以被快速监听。Alpine.js通过为x-on指令提供一个快捷方式进一步简化了事件处理。
这个快捷方式让你直接调用事件,只需在它前面加上@。前面的例子可以改写为。
<li class="list-group-item list-group-item-success" x-data @click="alert('Hi')">First Item</li>
然后,其他事件将使用@change 、@blur 、@focus 来调用。
Alpine.js并不限制你使用它的指令。它将JavaScript内置的事件对象作为一个神奇的属性$event来访问,这将在以后的应用程序中使用。
键盘事件
Alpine.js进一步简化了事件处理,它给出了可以附加到keyup事件的修改器。这些修饰符可以帮助我们对事件做出反应,甚至作为一个组合,如shift + enter 。为了在点击'Enter'时提醒我们HTML中输入的值,我们可以一起使用@keyup 指令和神奇的$event 属性,如下所示。
<input type="text" placeholder="Enter New Todo" class="form-control" x-data @keyup.enter="alert($event.target.value)">
现在,你知道如何处理事件了。你可以利用这些知识来获取用户在按下 "Enter "按钮时的输入。然而,用户的输入目前是没有用的,因为我们没有地方存储它,没有办法跟踪它的状态。
为了解决这个问题,Alpine.js让你在你的标记中直接声明数据(状态)。
Alpine.js的状态管理
数据是现代网络应用的中心,Alpine.js作为一个渐进式框架有其核心。在Alpine.js中,数据可以被提供给单个HTML元素、一大块HTML或全局。
x-data
这个指令让你在你的标记中直接声明数据。例如,为了存储某个元素的可见状态,你可以像这样声明它的状态。
<div x-data="{ show: false }"></div>
这个指令也可以被嵌套(存在于父元素和子元素中)。当嵌套时,父元素的数据可以在子元素中被访问,如果你有许多依赖一个变量的组件(HTML块),那么它就特别有用。
每个块都可以有自己的数据,并且仍然依赖于父元素中的主要数据。假设父元素有一个与子元素中的数据属性名称相同的数据属性。
在这种情况下,当从它内部访问时,它的数据属性被赋予优先权。一个数据嵌套的例子。
<div x-data="{ show: false }">
<div x-data="{ items: ['Apple', 'Ball'] }">
....
</div>
</div>
你经常不想存储任何数据,但仍然想访问Alpine.js的超级功能,正如上面的例子所说明的。添加x-data属性可以让你拥有这些功能。
全局状态
Alpine.js应用程序中的数据不必局限于单个组件或子组件。它们可以被存储在更大的范围内,以便可重复使用并被页面上的每个组件所访问。Alpine.data()可以让你声明可以在你的应用程序的组件中重复使用的数据。
Alpine.store()有助于使一些数据对你页面上的每个组件都可用。这些数据可以使用$store魔法属性来访问。这两个方法的区别可以在这个例子中得到检验。
Alpine.data('dropdown', () => ({
open: false,
}))
Alpine.store('tabs', {
current: 'first',
items: ['first', 'second', 'third'],
})
<div x-data="dropdown">
<span x-show="open">Content...</span>
</div>
<div x-data="dropdown">
<span x-show="open">Some Other Content...</span>
</div>
<div x-data>
<template x-for="tab in $store.tabs.items">
...
</template>
</div>
<div x-data>
<button @click="$store.tabs.current = 'first'">First Tab</button>
<button @click="$store.tabs.current = 'second'">Second Tab</button>
<button @click="$store.tabs.current = 'third'">Third Tab</button>
</div>
在这个例子中,创建一个dropdown 数据对象是为了可重复使用,而创建一个tabs 数据对象是为了全球可用。使用dropdown 的组件必须通过在他们的x-data 属性中传递它来说明它。使用标签的组件则使用其魔法属性来引用它。
在这一点上,你已经学会了Alpine.js的事件管理。你知道如何在按下 "Enter "按钮时获得用户的输入。你还学会了如何存储和访问这些数据。让我们把这些放在一起,以获得用户输入并存储它。
存储用户输入
将x-data 属性添加到ul 元素中,以存储其中创建的所有todos。
<ul class="list-group mt-3" x-data="{ todos: [] }">
现在可以填充todos数组,更新input 元素以响应点击事件,并推送到数组中。
<input
type="text"
placeholder="Enter New Todo"
class="form-control"
x-data
@keyup.enter="todos.push({
'name': $event.target.value,
'status': 'open'
})"
>
这段代码将一个todo对象推送到数组中。该对象的结构是这样的。
{
name: "Todo name",
status: "Todo status" // 'open', 'completed', 'cancelled'
}
console.log 为了确定todo确实被推送了,你可以在推送后查看todos 数组。
@keyup.enter="todos.push({
'name': $event.target.value,
'status': 'open'
}); console.log(todos)"
你应该在每次点击'Enter'时在控制台看到更新的todo列表。但是,为了获得更好的体验,有几件事情需要落实到位。你应该在提交后清空并退出输入。
@keyup.enter="todos.push({
'name': $event.target.value,
'status': 'open'
}); $event.target.value = ''; $event.target.blur()"
现在,我们可以获得用户的输入,将其作为一个对象存储在一个数组中。我们现在可以将这些todos显示为列表项。
Alpine.js的模板设计
Alpine.js的另一个显著特点是可以轻松地在网页上操作DOM。要在Alpine.js中输出一些文本,可以使用x-text指令。这个指令可以用来输出一个普通的字符串,一些存储的数据,甚至是一些JavaScript操作的结果。
<div x-data="{ greeting: 'Hello World' }">
<h1 x-text="'Hello world'"></h1> <!-- Outputs Hello World -->
<h1 x-text="'Hello world'">Not Hello World</h1> <!-- Outputs Hello World -->
<h1 x-text="greeting"></h1> <!-- Outputs Hello World -->
<h1 x-text="'Hello ' + 'World'"></h1> <!-- Outputs Hello World -->
<h1 x-text="3 + 2"></h1> <!-- Outputs Hello World -->
</div>
这个例子显示了x-text 指令的行为。它在它所传递的标签之间置换文本,并将算术操作的响应解析为要打印的字符串。
像x-text ,但用于输出HTML,x-html 让你在你的标记中直接显示丰富的文本。
<div x-data="{ title: '<h1>Start Here</h1>' }">
<div x-html="title"></div>
</div>
有条件地渲染模板
Alpine.js让你根据你设定的条件来渲染元素。这些条件是可切换的,以呈现隐藏的元素或隐藏已呈现的元素。x-if 和x-show 让你在一个条件为真时呈现一些标记。下面是一个例子,通过点击一个按钮,我的名字被显示和隐藏。
<div x-data="{ showName: false }">
<button @click="showName = !showName">Toggle Name</button>
<p x-show="showName">Zubair Idris Aweda</p>
</div>
同样的功能也可以用x-if ,像这样实现。
<div x-data="{ showName: false }">
<button @click="showName = !showName">Toggle Name</button>
<template x-if="showName">
<p>Zubair Idris Aweda</p>
</template>
</div>
请注意,x-if 的例子有一个额外的template 标签。这是因为x-if 利用了template 浏览器的行为。当showName 返回错误时,它可以从页面中删除该段落,或者当它返回真实时,将其添加到页面中。
x-if 和x-show 指令的另一个区别是,在使用x-show 时,你可以为元素的隐藏和显示添加一个过渡。这个过渡可以按照你的意愿来定制。
<div x-data="{ showName: false }">
<button @click="showName = !showName">Toggle Name</button>
<p x-show="showName" x-transition>Zubair Idris Aweda</p>
</div>
我们可以花点时间给我们的应用程序添加另一个修正。目前,"按回车键保存 "的文字就在那里。不如我们把它设置为只有在输入框被关注时才显示。更新包含输入字段的列表项,使之与之匹配。
<li class="list-group-item" x-data="{ showHint: false }">
<input
type="text"
placeholder="Enter New Todo"
class="form-control"
@focus="showHint = true"
@blur="showHint = false"
@keyup.enter="todos.push({
'name': $event.target.value,
'status': 'open'
}); $event.target.value = ''; $event.target.blur()"
>
<small x-show="showHint" class="text-info">Hit Enter To Save</small>
</li>
这个例子听从focus 和blur 事件来更新提示文本的状态。到这里,你一定已经看到了Alpine.js的反应性。
循环元素
除了能够在某些条件为真时渲染元素外,Alpine.js还能让你多次重复一个代码块,或显示一个数据列表。它根据列表中的数据来创建DOM元素。x-for 指令,像x-if 指令一样,必须与template 标签一起使用。例如,你可以使用1到10打印到你的屏幕上。
<ul x-data>
<template x-for="i in 10">
<li x-text="i"></li>
</template>
</ul>
你也可以像这样循环浏览一个简单的数组。
<ul x-data="{ colors: ['Red', 'Orange', 'Yellow'] }">
<template x-for="color in colors">
<li x-text="color"></li>
</template>
</ul>
了解了这些,我们就可以通过迭代存储的todos数组来显示我们的todos。将页面上的所有静态列表项替换成这样。
<template x-for="todo in todos" x-data>
<li
x-text="todo.name"
x-transition
class="list-group-item"
></li>
</template>
这应该是对todos数组的循环,但该数组目前是空的。所以,继续吧,输入一些你以后想做的事情,看着它们显示出来。

为了使事情更有趣,也为了说明问题,我们可以在数组中添加一些todos。现在,这个应用程序从一开始就有一些todos。添加三个具有三种可用状态的todos。更新ul 元素,以拥有这些新的todos。
<ul class="list-group mt-3" x-data="{ todos: [
{
'name': 'Eat breakfast',
'status': 'completed'
},
{
'name': 'Give my breakfast to the dogs',
'status': 'cancelled'
},
{
'name': 'Complete this article',
'status': 'open'
}
] }">

在这一点上,我们已经非常接近最初的设计了。然而,我们还不能让这些todos根据它们的状态看起来不同。
操纵HTML属性
为了操纵每个列表项的样式,我们可以使用Alpine.jsx-bind 指令。这个指令让我们把HTML属性设置为JavaScript表达式的结果。例如,设置一个图片的src 属性。
<div x-data="{ image_src: 'hero.png' }">
<img x-bind:src="image_src">
</div>
这个例子将图片src ,即 "hero.png"。
x-bind, 像x-on 有一个速记的语法。要使用这种语法使一个属性成为动态的,在属性名称前加一个冒号,: ,像这样。
<div x-data="{ placeholder: 'Enter text here' }">
<input type="text" :placeholder="placeholder">
</div>
了解了这一点,我们就可以更新我们的列表,根据每个项目的状态来设置它的背景。要做到这一点,我们要把当前存在于所有todos上的类提取到一个变量中,list_class 。然后,我们将其添加到基于状态的唯一类中。
<template x-for="todo in todos" x-data="{ list_class: 'list-group-item' }">
<li
x-text="todo.name"
x-transition
:class="todo.status === 'completed' ? list_class + ' list-group-item-success' : todo.status === 'cancelled' ? list_class + ' list-group-item-danger' : list_class"
></li>
</template>
这个例子使用三元运算符来确定要使用的适当的Bootstrap类。这应该会产生一个像这样的好看的列表。

作为本教程的总结,我们应该按照顶部列出的状态来过滤这些项目。
按状态过滤
按状态过滤待办事项包括几个步骤。
首先,点击顶部的丸子应该更新一些状态。这个状态将告诉你当前正在查看哪个类别。要做到这一点,需要给药丸添加事件监听器,并给一个父级div添加一个数据属性,也许是body 。
<body class="container bg-pink" x-data="{ viewing: 'all' }"></body>
添加一个查看状态,以了解当前正在查看的状态。
<div>
<span class="badge bg-primary rounded-pill" @click="viewing = 'all'">All</span>
<span class="badge bg-white text-black rounded-pill" @click="viewing = 'open'">Opened</span>
<span class="badge bg-danger rounded-pill" @click="viewing = 'cancelled'">Cancelled</span>
<span class="badge bg-success rounded-pill" @click="viewing = 'completed'">Completed</span>
</div>
现在,当其中任何一个被点击时,viewing 状态会发生变化。为了响应这些变化,我们必须能够实际检测这些变化。Alpine.js为我们准备了一个魔法属性。$watch 魔法属性监控一个数据属性,并在它发生变化时执行一些动作。在这个例子中,我们要更新每个列表项的显示状态。
<li
x-text="todo.name"
x-data="{ will_show: viewing === 'all' }"
x-init="$watch('viewing', value => will_show = value === 'all' || value === todo.status )"
x-transition
x-init="$watch('viewing', value => will_show = value === 'all' || value === todo.status )"
x-show="will_show"
:class="todo.status === 'completed' ? list_class + ' list-group-item-success' : todo.status === 'cancelled' ? list_class + ' list-group-item-danger' : list_class"
></li>
在这个例子中,我们首先声明一个will_show 状态,决定列表项的显示状态。我们希望每个项目在点击'all'时都能显示,根据这个值进行初始化。
然后,引入一个新的指令,x-init 。这个指令让你在DOM中创建模板时运行一些代码。在这个例子中,我们观察viewing 状态的变化。然后,如果项目的状态与选择的类别相同,我们通过更新will_show状态来响应这些变化。
最后,通过使用x-show 指令的一些过渡来切换显示。

总结
在本教程中,我们已经了解了什么是Alpine.js。我们还学习了如何有效地使用它的许多功能和指令来构建快速和轻量级的单页Web应用程序。
编码愉快!