跳转至

从这里开始

在你的电脑上创建一个空白的 HTML 文件,命名为:i-love-alpine.html

使用文本编辑器,填入以下内容:

<html>
<head>
    <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/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-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:

→ 了解更多关于 x-on

响应变化

<span x-text="count"></span>

x-text 是一个 Alpine 指令,用于将元素的文本内容设置为某个 JavaScript 表达式的结果。

在这里,我们告诉 Alpine 始终保持这个 span 标签的内容反映 count 属性的值。

需要说明的是,x-text 和大多数指令一样,接受一个普通的 JavaScript 表达式作为参数。例如,你可以将其内容设置为 x-text="count * 2",这样 span 的文本内容将始终是 count 值的 2 倍。

→ 了解更多关于 x-text

构建下拉菜单

现在我们已经掌握了一些基本功能,让我们继续学习 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-datax-on 指令你应该已经从之前的示例中熟悉了,所以这里不再赘述。

切换元素

<div x-show="open" ...>内容...</div>

x-show 是一个极其强大的 Alpine 指令,用于根据 JavaScript 表达式的结果来显示或隐藏页面上的 HTML 块,这里的结果是 open

→ 了解更多关于 x-show

监听外部点击

<div ... @click.outside="open = false">内容...</div>

你会在这个示例中注意到一个新东西:.outside。Alpine 中的许多指令都支持"修饰符",它们用句点连接在指令的末尾。

在这里,.outside 告诉 Alpine 不要监听 <div> 内部的点击,而是只监听发生在 <div> 外部的点击。

这是 Alpine 内置的一个便捷辅助功能,因为这是一个常见需求,手动实现起来既麻烦又复杂。

→ 了解更多关于 x-on 的修饰符

构建搜索输入框

现在让我们构建一个更复杂的组件,同时介绍一些其他的指令和模式。

<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 的功能远不止这个简单的示例。

→ 了解更多关于 x-model

使用 getter 的计算属性

接下来我要请注意的是 x-data 指令中的 itemsfilteredItems 属性。

{
    ...
    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 更简洁的语法。

→ 了解更多关于 JavaScript 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)。

→ 了解更多关于 x-for

回顾

如果你已经读到这里,那么你已经接触到了以下 Alpine 指令:

  • x-data
  • x-on
  • x-text
  • x-show
  • x-model
  • x-for

这是一个很好的开端,但还有更多的指令等待你去探索。学习 Alpine 的最佳方式是通读本文档。无需逐字逐句地研究,但如果你至少浏览每一页,使用 Alpine 时将会更加得心应手。

祝你编码愉快!