跳转至

Alpine.data

Alpine.data(...) 提供了一种在你的应用中复用 x-data 上下文的方式。

以下是一个示例的 dropdown 组件:

<div x-data="dropdown">
    <button @click="toggle">...</button>

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

<script>
    document.addEventListener('alpine:init', () => {
        Alpine.data('dropdown', () => ({
            open: false,

            toggle() {
                this.open = ! this.open
            }
        }))
    })
</script>

如你所见,我们将通常直接在 x-data 中定义的属性和方法提取到了一个单独的 Alpine 组件对象中。

从 bundle 中注册

如果你选择为 Alpine 代码使用构建步骤,应按以下方式注册你的组件:

import Alpine from 'alpinejs'
import dropdown from './dropdown.js'

Alpine.data('dropdown', dropdown)

Alpine.start()

这假设你有一个名为 dropdown.js 的文件,内容如下:

export default () => ({
    open: false,

    toggle() {
        this.open = ! this.open
    }
})

初始参数

除了直接通过名称引用 Alpine.data 提供者(如 x-data="dropdown"),你还可以将其作为函数引用(x-data="dropdown()")。通过直接作为函数调用,你可以传入额外的参数用于创建初始数据对象,如下所示:

<div x-data="dropdown(true)">
Alpine.data('dropdown', (initialOpenState = false) => ({
    open: initialOpenState
}))

现在,你可以根据需要传入不同的参数来复用 dropdown 对象。

Init 函数

如果你的组件包含 init() 方法,Alpine 会在渲染组件之前自动执行它。例如:

Alpine.data('dropdown', () => ({
    init() {
        // 此代码将在 Alpine 初始化组件其余部分之前执行
    }
}))

Destroy 函数

如果你的组件包含 destroy() 方法,Alpine 会在清理组件之前自动执行它。

一个典型的使用场景是在 Alpine 无法提供的第三方库或浏览器 API 中注册事件处理器时。请看以下示例代码,了解如何使用 destroy() 方法清理此类处理器。

Alpine.data('timer', () => ({
    timer: null,
    counter: 0,
    init() {
      // 注册一个引用了组件实例的事件处理器
      this.timer = setInterval(() => {
        console.log('Increased counter to', ++this.counter);
      }, 1000);
    },
    destroy() {
        // 移除处理器,避免内存和副作用泄漏
        clearInterval(this.timer);
    },
}))

组件被销毁的一个示例是在 x-if 中使用组件时:

<span x-data="{ enabled: false }">
    <button @click.prevent="enabled = !enabled">Toggle</button>

    <template x-if="enabled">
        <span x-data="timer" x-text="counter"></span>
    </template>
</span>

使用魔法属性

如果你想从组件对象中访问魔法方法或属性,可以通过 this 上下文来实现:

Alpine.data('dropdown', () => ({
    open: false,

    init() {
        this.$watch('open', () => {...})
    }
}))

使用 x-bind 封装指令

如果你希望复用的不仅仅是组件的数据对象,你可以使用 x-bind 封装整个 Alpine 模板指令。

以下是一个使用 x-bind 提取之前下拉菜单组件模板细节的示例:

<div x-data="dropdown">
    <button x-bind="trigger"></button>

    <div x-bind="dialogue"></div>
</div>
Alpine.data('dropdown', () => ({
    open: false,

    trigger: {
        ['@click']() {
            this.open = ! this.open
        },
    },

    dialogue: {
        ['x-show']() {
            return this.open
        },
    },
}))