x-init 初始化 #
什么是 x-init? #
x-init 指令在 Alpine.js 组件初始化时执行代码。它常用于加载数据、设置初始状态或执行其他启动逻辑。
基本语法 #
html
<div x-data="{ ... }" x-init="初始化代码">
</div>
基本用法 #
执行简单代码 #
html
<div x-data="{ message: '' }" x-init="message = 'Hello!'">
<p x-text="message"></p>
</div>
调用方法 #
html
<div x-data="{
items: [],
loadItems() {
this.items = ['Item 1', 'Item 2', 'Item 3']
}
}" x-init="loadItems()">
<template x-for="item in items">
<p x-text="item"></p>
</template>
</div>
使用 init 方法 #
在 x-data 中定义 init 方法,会自动执行:
html
<div x-data="{
items: [],
init() {
this.items = ['Item 1', 'Item 2', 'Item 3']
}
}">
<template x-for="item in items">
<p x-text="item"></p>
</template>
</div>
异步初始化 #
加载远程数据 #
html
<div x-data="{
users: [],
loading: false,
error: null,
async init() {
this.loading = true
try {
const res = await fetch('/api/users')
this.users = await res.json()
} catch (e) {
this.error = e.message
} finally {
this.loading = false
}
}
}">
<div x-show="loading">加载中...</div>
<div x-show="error" x-text="error"></div>
<template x-for="user in users">
<p x-text="user.name"></p>
</template>
</div>
链式异步操作 #
html
<div x-data="{
data: null,
async init() {
const user = await this.fetchUser()
const posts = await this.fetchPosts(user.id)
this.data = { user, posts }
},
async fetchUser() {
const res = await fetch('/api/user')
return res.json()
},
async fetchPosts(userId) {
const res = await fetch(`/api/posts?userId=${userId}`)
return res.json()
}
}">
</div>
x-init vs init 方法 #
x-init 属性 #
html
<div x-data="{ count: 0 }" x-init="count = 10">
</div>
init 方法 #
html
<div x-data="{
count: 0,
init() {
this.count = 10
}
}">
</div>
两者区别 #
| 特性 | x-init 属性 | init 方法 |
|---|---|---|
| 位置 | HTML 属性 | x-data 内部 |
| 可读性 | 适合简单代码 | 适合复杂逻辑 |
| 复用 | 不易复用 | 可随组件复用 |
| 调试 | 较难调试 | 易于调试 |
同时使用 #
两者可以同时使用,x-init 先执行:
html
<div x-data="{
count: 0,
init() {
console.log('init 方法执行, count:', this.count)
}
}" x-init="count = 5; console.log('x-init 执行, count:', count)">
</div>
输出:
text
x-init 执行, count: 5
init 方法执行, count: 5
实用示例 #
从 localStorage 加载 #
html
<div x-data="{
theme: 'light',
init() {
const saved = localStorage.getItem('theme')
if (saved) {
this.theme = saved
}
},
setTheme(value) {
this.theme = value
localStorage.setItem('theme', value)
}
}">
<button @click="setTheme('light')">浅色</button>
<button @click="setTheme('dark')">深色</button>
<div :class="'theme-' + theme">
当前主题: <span x-text="theme"></span>
</div>
</div>
初始化表单 #
html
<div x-data="{
form: {
name: '',
email: '',
country: ''
},
countries: [],
async init() {
const res = await fetch('/api/countries')
this.countries = await res.json()
}
}">
<input x-model="form.name" placeholder="姓名">
<input x-model="form.email" placeholder="邮箱">
<select x-model="form.country">
<option value="">选择国家</option>
<template x-for="country in countries">
<option :value="country.code" x-text="country.name"></option>
</template>
</select>
</div>
设置定时器 #
html
<div x-data="{
time: null,
timer: null,
init() {
this.updateTime()
this.timer = setInterval(() => this.updateTime(), 1000)
},
updateTime() {
this.time = new Date().toLocaleTimeString()
},
destroy() {
if (this.timer) {
clearInterval(this.timer)
}
}
}">
当前时间: <span x-text="time"></span>
</div>
条件初始化 #
html
<div x-data="{
user: null,
mode: 'view',
init() {
const saved = localStorage.getItem('user')
if (saved) {
this.user = JSON.parse(saved)
this.mode = 'edit'
}
}
}">
<template x-if="user">
<div>
<p>欢迎回来, <span x-text="user.name"></span></p>
</div>
</template>
<template x-if="!user">
<div>
<p>请登录</p>
</div>
</template>
</div>
初始化计算值 #
html
<div x-data="{
items: [],
filteredItems: [],
filter: '',
init() {
this.items = [
{ id: 1, name: 'Apple', category: 'fruit' },
{ id: 2, name: 'Carrot', category: 'vegetable' },
{ id: 3, name: 'Banana', category: 'fruit' }
]
this.applyFilter()
},
applyFilter() {
if (!this.filter) {
this.filteredItems = this.items
} else {
this.filteredItems = this.items.filter(
item => item.category === this.filter
)
}
}
}">
<select x-model="filter" @change="applyFilter()">
<option value="">全部</option>
<option value="fruit">水果</option>
<option value="vegetable">蔬菜</option>
</select>
<template x-for="item in filteredItems" :key="item.id">
<p x-text="item.name"></p>
</template>
</div>
注册全局监听 #
html
<div x-data="{
scrollY: 0,
init() {
window.addEventListener('scroll', this.onScroll.bind(this))
},
onScroll() {
this.scrollY = window.scrollY
}
}">
滚动位置: <span x-text="scrollY"></span>px
</div>
初始化第三方库 #
html
<div x-data="{
editor: null,
init() {
this.$nextTick(() => {
this.editor = new Editor({
target: this.$refs.editor,
props: {
content: ''
}
})
})
}
}">
<div x-ref="editor"></div>
</div>
Alpine.data 中的 init #
在 Alpine.data 中定义 init 方法:
javascript
Alpine.data('userList', () => ({
users: [],
loading: false,
async init() {
await this.loadUsers()
},
async loadUsers() {
this.loading = true
const res = await fetch('/api/users')
this.users = await res.json()
this.loading = false
}
}))
html
<div x-data="userList">
<template x-for="user in users">
<p x-text="user.name"></p>
</template>
</div>
初始化时机 #
执行顺序 #
text
1. x-data 创建响应式数据
2. x-init 执行(如果存在)
3. init 方法执行(如果存在)
4. x-effect 执行(如果存在)
5. DOM 更新
$nextTick #
在 DOM 更新后执行代码:
html
<div x-data="{
items: [],
init() {
this.items = ['Item 1', 'Item 2']
this.$nextTick(() => {
console.log('DOM 已更新')
})
}
}">
</div>
注意事项 #
1. 避免阻塞 #
异步操作不会阻塞渲染:
html
<div x-data="{
data: null,
async init() {
this.data = await fetch('/api/data').then(r => r.json())
}
}">
<div x-show="!data">加载中...</div>
<div x-show="data">内容</div>
</div>
2. 错误处理 #
异步初始化应该处理错误:
html
<div x-data="{
data: null,
error: null,
async init() {
try {
this.data = await this.fetchData()
} catch (e) {
this.error = e.message
}
}
}">
</div>
3. 清理资源 #
使用 Alpine.effect 或手动清理:
html
<div x-data="{
timer: null,
init() {
this.timer = setInterval(() => {}, 1000)
},
destroy() {
clearInterval(this.timer)
}
}">
</div>
小结 #
x-init 指令要点:
- 在组件初始化时执行代码
- 可以使用属性或
init方法 - 支持异步操作
- 常用于加载数据和设置初始状态
- 注意错误处理和资源清理
下一章,我们将学习 x-ref 指令引用 DOM 元素。
最后更新:2026-03-28