从这里开始
在你的电脑上创建一个空白的 HTML 文件,命名为:i-love-alpine.html
使用文本编辑器,填入以下内容:
<html>
<head>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<h1 x-data="{ message: 'I ❤️ Alpine' }" x-text="message"></h1>
</body>
</html>
在浏览器中打开该文件,如果你看到了 I ❤️ Alpine,就说明你已经准备好开始探索了!
现在你已经完成了基本设置,让我们通过三个实用示例来学习 Alpine 的基础知识。完成本练习后,你将完全有能力独立开始构建项目。我们开始吧!
构建计数器
让我们从一个简单的"计数器"组件开始,演示 Alpine 中状态和事件监听这两个核心功能。
在 <body> 标签中插入以下内容:
<div x-data="{ count: 0 }">
<button x-on:click="count++">增加</button>
<span x-text="count"></span>
</div>
现在你可以看到,通过在这段 HTML 中加入了三个 Alpine 指令,我们创建了一个交互式的"计数器"组件。
让我们简要地解析一下这里发生的事情:
声明数据
<div x-data="{ count: 0 }">
Alpine 中的一切都始于 x-data 指令。在 x-data 中,你用纯 JavaScript 声明一个 Alpine 将追踪的数据对象。
该对象中的每个属性都将在此 HTML 元素内的其他指令中可用。此外,当某个属性发生变化时,所有依赖它的部分也会随之更新。
大多数 Alpine 指令正常工作都需要在父元素上使用
x-data。
接下来看看 x-on 如何访问和修改上方的 count 属性:
监听事件
<button x-on:click="count++">增加</button>
x-on 是一个用于监听元素上任何事件的指令。这里我们监听的是 click 事件,所以写法是 x-on:click。
你可以监听其他任何事件。例如,监听 mouseenter 事件就是 x-on:mouseenter。
当 click 事件发生时,Alpine 会执行关联的 JavaScript 表达式,这里是 count++。如你所见,我们可以直接访问 x-data 表达式中声明的数据。
你经常会看到
@替代x-on:。这是更简短、更友好的写法,很多人更喜欢这种形式。从现在开始,本文档将主要使用@替代x-on:。
响应变化
<span x-text="count"></span>
x-text 是一个 Alpine 指令,用于将元素的文本内容设置为某个 JavaScript 表达式的结果。
在这里,我们告诉 Alpine 始终保持这个 span 标签的内容反映 count 属性的值。
需要说明的是,x-text 和大多数指令一样,接受一个普通的 JavaScript 表达式作为参数。例如,你可以将其内容设置为 x-text="count * 2",这样 span 的文本内容将始终是 count 值的 2 倍。
构建下拉菜单
现在我们已经掌握了一些基本功能,让我们继续学习 Alpine 中的一个重要指令:x-show,通过构建一个简单的"下拉菜单"组件。
在 <body> 标签中插入以下代码:
<div x-data="{ open: false }">
<button @click="open = ! open">切换</button>
<div x-show="open" @click.outside="open = false">内容...</div>
</div>
如果你加载这个组件,应该会看到"内容..."默认是隐藏的。点击"切换"按钮可以在页面上显示或隐藏它。
x-data 和 x-on 指令你应该已经从之前的示例中熟悉了,所以这里不再赘述。
切换元素
<div x-show="open" ...>内容...</div>
x-show 是一个极其强大的 Alpine 指令,用于根据 JavaScript 表达式的结果来显示或隐藏页面上的 HTML 块,这里的结果是 open。
监听外部点击
<div ... @click.outside="open = false">内容...</div>
你会在这个示例中注意到一个新东西:.outside。Alpine 中的许多指令都支持"修饰符",它们用句点连接在指令的末尾。
在这里,.outside 告诉 Alpine 不要监听 <div> 内部的点击,而是只监听发生在 <div> 外部的点击。
这是 Alpine 内置的一个便捷辅助功能,因为这是一个常见需求,手动实现起来既麻烦又复杂。
构建搜索输入框
现在让我们构建一个更复杂的组件,同时介绍一些其他的指令和模式。
在 <body> 标签中插入以下代码:
<div
x-data="{
search: '',
items: ['foo', 'bar', 'baz'],
get filteredItems() {
return this.items.filter(
i => i.startsWith(this.search)
)
}
}"
>
<input x-model="search" placeholder="搜索...">
<ul>
<template x-for="item in filteredItems" :key="item">
<li x-text="item"></li>
</template>
</ul>
</div>
默认情况下,所有的"items"(foo、bar 和 baz)都会显示在页面上,但你可以通过在文本输入框中输入内容来过滤它们。随着你输入,列表项会实时变化以反映搜索内容。
这里有很多新内容,让我们逐段分析一下。
多行格式
首先需要指出的是,现在的 x-data 比以前复杂多了。为了让代码更容易编写和阅读,我们在 HTML 中将其分成了多行。这不是必须的,稍后我们会讨论如何彻底避免这个问题,但现在我们先将所有 JavaScript 代码直接放在 HTML 中。
绑定到输入框
<input x-model="search" placeholder="搜索...">
你会注意到一个我们之前没见过的指令:x-model。
x-model 用于将输入元素的值与数据属性"绑定"——这里是与 x-data="{ search: '', ... }" 中的 "search" 属性绑定。
这意味着每当输入框的值发生变化时,"search" 的值也会随之更新。
x-model 的功能远不止这个简单的示例。
使用 getter 的计算属性
接下来我要请注意的是 x-data 指令中的 items 和 filteredItems 属性。
{
...
items: ['foo', 'bar', 'baz'],
get filteredItems() {
return this.items.filter(
i => i.startsWith(this.search)
)
}
}
items 属性不言自明。这里我们将 items 设置为一个包含 3 个不同项目(foo、bar 和 baz)的 JavaScript 数组。
这段代码中比较有趣的是 filteredItems 属性。
由属性前面的 get 关键字可知,filteredItems 是这个对象中的一个"getter"属性。这意味着我们可以像访问普通属性一样访问 filteredItems,但在底层,JavaScript 会执行提供的函数并返回结果。
完全可以不使用 get,而将其定义为一个可以在模板中调用的方法,但有些人更喜欢 getter 更简洁的语法。
现在让我们看看 filteredItems getter 内部,确保我们理解它的工作原理:
return this.items.filter(
i => i.startsWith(this.search)
)
这是纯 JavaScript 代码。我们首先获取 items 数组(foo、bar 和 baz),然后使用提供的回调函数 i => i.startsWith(this.search) 进行过滤。
通过将这个回调传递给 filter,我们告诉 JavaScript 只返回以某个字符串开头的项目,这个字符串就是 this.search——正如我们在 x-model 中看到的,它将始终反映输入框的值。
你可能注意到了,到目前为止,我们还没有使用 this. 来引用属性。但是,由于我们现在直接在 x-data 对象内部工作,必须使用 this.[property] 而非直接使用 [property] 来引用任何属性。
由于 Alpine 是一个"响应式"框架,任何时候 this.search 的值发生变化,模板中使用 filteredItems 的部分都会自动更新。
循环元素
现在我们已经理解了组件的数据部分,让我们看看模板中是如何在页面上循环遍历 filteredItems 的。
<ul>
<template x-for="item in filteredItems">
<li x-text="item"></li>
</template>
</ul>
首先要注意的是 x-for 指令。x-for 表达式的形式为 [item] in [items],其中 [items] 是任意数据数组,[item] 是每次迭代中分配给当前项的变量名。
另外请注意,x-for 是声明在 <template> 元素上,而不是直接在 <li> 上。这是使用 x-for 的要求。它让 Alpine 能够利用浏览器中 <template> 标签的现有行为。
现在,<template> 标签内的任何元素都会为 filteredItems 中的每个项目重复渲染,并且在循环内评估的所有表达式都可以直接访问迭代变量(这里是 item)。
回顾
如果你已经读到这里,那么你已经接触到了以下 Alpine 指令:
- x-data
- x-on
- x-text
- x-show
- x-model
- x-for
这是一个很好的开端,但还有更多的指令等待你去探索。学习 Alpine 的最佳方式是通读本文档。无需逐字逐句地研究,但如果你至少浏览每一页,使用 Alpine 时将会更加得心应手。
祝你编码愉快!