文档
Alpine.js 入门教程:给你的 HTML 添加超能力
一、Alpine.js 是什么?
Alpine.js 的口号是"像写 Tailwind CSS 一样写 JavaScript"。它让你用简单的 HTML 属性为页面添加交互,无需构建工具、无需虚拟 DOM,只有 15 个属性 + 6 个魔法方法 + 1 个全局状态。非常适合后端开发者给模板引擎(Laravel Blade、Django Templates、Rails ERB 等)添加交互,或为静态网站注入轻量级动态行为。
二、核心指令速览
| 指令 | 作用 | 示例 |
|---|---|---|
x-data |
定义组件作用域和数据 | x-data="{ open: false }" |
x-model |
双向数据绑定 | <input x-model="name"> |
@click / x-on: |
事件绑定 | <button @click="open = !open"> |
x-show |
条件显示(display:none) | <div x-show="open"> |
x-if |
条件渲染(移除DOM) | <template x-if="open"> |
x-for |
循环渲染 | <template x-for="item in items"> |
x-text |
输出文本(防XSS) | <span x-text="name"> |
x-html |
输出HTML(慎用) | <div x-html="raw"> |
x-bind: |
属性绑定 | <img :src="url"> |
x-effect |
监听变化执行回调 | <div x-effect="fetch(url)"> |
x-ref |
组件内部引用 | <div x-ref="myDiv"> |
x-init |
组件初始化钩子 | <div x-init="fetchData()"> |
三、魔法方法
<!-- $store - 全局状态 -->
<span x-text="$store.theme.darkMode"></span>
<!-- $dispatch - 事件分发 -->
<button @click="$dispatch('custom-event', { data: 42 })">
<!-- $watch - 监听数据变化 -->
<div x-init="$watch('count', val => console.log(val))">
<!-- $refs - 访问 DOM -->
<div x-ref="input" x-init="$refs.input.focus()">
<!-- $nextTick - 下一个 tick -->
<div x-init="$nextTick(() => console.log('DOM 已更新'))">
<!-- $el - 当前 DOM 元素 -->
<div x-init="console.log($el.tagName)">
四、分步实战:Todo 应用
第一步:基础结构
<div x-data="{
todos: [],
newTodo: '',
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({ id: Date.now(), text: this.newTodo, done: false });
this.newTodo = '';
}
},
removeTodo(id) {
this.todos = this.todos.filter(t => t.id !== id);
}
}">
第二步:表单与列表
<form @submit.prevent="addTodo">
<input x-model="newTodo" placeholder="输入任务..." />
<button type="submit">添加</button>
</form>
<template x-for="todo in todos" :key="todo.id">
<li>
<span :class="{ 'line-through': todo.done }" x-text="todo.text"></span>
<button @click="todo.done = !todo.done">✓</button>
<button @click="removeTodo(todo.id)">✕</button>
</li>
</template>
第三步:持久化到 localStorage
<div x-data="{ todos: [] }"
x-init="todos = JSON.parse(localStorage.getItem('todos') || '[]');
$watch('todos', val => localStorage.setItem('todos', JSON.stringify(val)))">
五、全局状态(Alpine.store)
<script defer src="...alpine.min.js"></script>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('theme', {
dark: false,
toggle() { this.dark = !this.dark; }
});
});
</script>
<!-- 任意组件中使用 -->
<div :class="$store.theme.dark ? 'bg-black' : 'bg-white'">
<button @click="$store.theme.toggle()">切换主题</button>
</div>
六、最佳实践
- x-data 对象保持简单——复杂逻辑抽到外部 JS 文件
- x-if 用 template 标签——避免残留 DOM 节点
- 列表必加 :key——性能关键
- $dispatch 实现父子组件通信——松耦合
七、思考题
- Alpine.js 和 Vue.js 的
v-model有什么区别? - 如何在 Alpine 组件间共享状态?(提示:$store / $dispatch / 自定义事件)
- 为什么 Alpine.js 适合"渐进增强"而 React 不太适合?