x-data
返回的数据<div x-data="greet()">
<button @click="showMessage()">Greet Me</button>
<div>Message: <span x-text="messageDisplay"></span></div>
</div>
<script>
function greet() {
return {
message: 'Hello Alpine.js',
messageDisplay: '',
showMessage() {
this.messageDisplay = this.message;
}
}
}
</script>
Alpine.js 一个很酷的地方在于,x-data
对象的任何方法、函数中的 this
都会被绑定到组件实例,通过它可以访问 x-data
中的所有数据。
也就是说,在 showMessage()
中我们可以访问 this.message
和 this.messageDisplay
。
「windows 事件总线」是如何工作的:
当我们向另一个组件发送(自定义)事件时,使用 $dispatch('event-name', { data: 'properties' })
。
在接收事件的组件中,我们使用 .window
或 .document
修饰符注册一个监听器。
<div x-data="{ isOpen: false }">
<!-- this component can be shown/hidden using a `toggle` event -->
<div
x-show="isOpen"
x-on:toggle.window="isOpen = !isOpen"
role="alert"
>
<p>This alert is toggled when `toggle` events are dispatched.</p>
<button @click="isOpen = false">close alert</button>
</div>
</div>
<div x-data="{}">
<p>The button in this component can toggle the "alert".</p>
<button @click="$dispatch('toggle')">Toggle alert</button>
</div>
<div x-data="{}">
<p>The button in this component can <strong>also</strong> toggle the "alert".</p>
<button @click="$dispatch('toggle')">Toggle alert 2</button>
</div>
如果要在使用「window 事件总线」模式时传递数据,我们可以在分发事件时使用 detail
参数,然后在监听的组件中使用 $event.detail
读取它。
<div x-data="{ msg: '', level: '' }">
Flash Component
<template x-on:flash.window="msg = $event.detail.msg; level = $event.detail.level;"></template>
<template x-if="msg && level">
<div role="alert" class="mt-2">
<div class="text-white font-bold rounded-t px-4 py-2 capitalize" :class="{'bg-red-500': level === 'error', 'bg-blue-500': level === 'info'}" x-text="level"></div>
<div class="border border-t-0 rounded-b px-4 py-3" :class="{'bg-red-100 text-red-700 border-red-400': level === 'error', 'bg-blue-100 text-blue-700 border-blue-400': level === 'info'}">
<p x-text="msg"></p>
</div>
</div>
</template>
</div>
<div x-data="{}">
Trigger 1
<button @click="$dispatch('flash', { level: 'info', msg: 'This is an info message' })" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Flash Info
</button>
</div>
<div x-data="{}">
Trigger 2
<button @click="$dispatch('flash', { level: 'error', msg: 'This is an error message' })" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
Flash Error
</button>
</div>
<div x-data="{}">
Trigger 3
<button @click="$dispatch('flash', { level: '', msg: '' })" class="font-bold py-2 px-4 rounded">
Clear Flash
</button>
</div>
Alpine.js 在初始化时,会运行 x-data
中的内容,将其包装成代理(允许视图更新交互),并存储在组件的根节点上。事实上,由于 Alpine.js 没有虚拟 DOM 或者其他可以存储这些信息的抽象层,它将作为 __x.$data
属性存储在根节点上,我们可以使用 __x.getUnobservedData()
函数访问它。
Alpine.js 没有官方的模板定义,我将根节点中的所有元素称之为模板。
在模板中,可以直接访问魔术属性。
例如:
<div x-data="{}" x-init="console.log($el)">
<button @click="$dispatch('toggle')">Toggle</button>
</div>
this
访问魔术属性函数组件就是使用函数来定义 x-data
的组件,它允许在 script
标签中定义组件逻辑。
与之相对的是,使用行内的对象定义 x-data
,如 x-data={ isOpen: false }
,以及行内指令如 @click="isOpen = !isOpen"
。
<div x-data="{ isOpen: false }">
<p x-show="isOpen">
What you can toggle
</p>
<button @click="isOpen = !isOpen">
Toggle
</button>
</div>
我们使用函数组件重写:
<div x-data="component()">
<p x-show="isOpen">
What you can toggle
</p>
<button @click="toggle()">
Toggle
</button>
</div>
<script>
function component() {
return {
isOpen: false,
toggle() {
this.isOpen = !this.isOpen;
}
}
}
</script>
表格表明:
在 x-data
函数中所有魔术属性都不可用,因为 x-data
在组件上下文(this
)存在前就运行了。
对于其他的指令函数(x-init, x-text, x-html, x-bind, x-show, x-on):$el, $refs, $nextTick, $watch 在 this
上可用。$event 和 $dispatch 在 this
上不可用。
指令 |
|
|
---|---|---|
x-data | 无 | $el, $refs, $event, $dispatch, $nextTick, $watch |
x-init | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-text | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-html | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-bind | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-show | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-on | $el, $refs, $nextTick, $watch | $event, $dispatch |
举例来说,可以在 x-init 函数中使用魔术属性 $watch:this.$watch('foo', (val) => console.log(val))
;在其他指令的函数中通过 this
访问魔术属性(this.$el, this.refs, this.$nextTick, this.$watch)。
x-init
中传递 $dispatch 来访问魔术属性我们可以从模板传递 $dispatch 到函数中,然后使用它。
<div x-data="page()" x-init="init($dispatch)">
<p x-text="output"></p>
</div>
<script>
function page() {
return {
output: '',
init($dispatch) {
// this.$dispatch is **not** defined in x-init handler
this.output += "Calling $dispatch";
$dispatch('test');
this.output += "\nCalled $dispatch";
},
};
}
</script>
x-on
中传递 $event 和 $dispatch 来访问它注意从模板中传递 $dispatch 的方式也适用于其他指令,
x-on
最有可能使用 $dispatch。
<div x-data="page()">
<p x-text="output"></p>
<button @click="handleClick($event, $dispatch)" value="button-value">
Get $event and $dispatch on click
</button>
</div>
<script>
function page() {
return {
output: '',
handleClick(e, $dispatch) {
// this.$event and this.$dispatch are **not** defined in x-on handler
this.output += `\nevent.target.value: "${e.target.value}"`;
this.output += "\nCalling $dispatch";
$dispatch("test2");
this.output += "\nCalled $dispatch";
},
};
}
</script>
参考资料: