Alpine.js 知识点

老牛浏览 966评论 0发表于

1. 在组件方法中访问 x-data 返回的数据

html
<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.messagethis.messageDisplay

2. 「window 事件总线」Alpine.js 组件通信模式

「windows 事件总线」是如何工作的:

  1. 当我们向另一个组件发送(自定义)事件时,使用 $dispatch('event-name', { data: 'properties' })

  2. 在接收事件的组件中,我们使用 .window.document 修饰符注册一个监听器。

html
<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 读取它。

html
<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>

3. 从外部访问 Alpine.js 组件状态、数据

Alpine.js 在初始化时,会运行 x-data 中的内容,将其包装成代理(允许视图更新交互),并存储在组件的根节点上。事实上,由于 Alpine.js 没有虚拟 DOM 或者其他可以存储这些信息的抽象层,它将作为 __x.$data 属性存储在根节点上,我们可以使用 __x.getUnobservedData() 函数访问它。

4. 在行内指令和函数、组件方法中访问魔术属性

4.1 在模板中访问魔术属性

Alpine.js 没有官方的模板定义,我将根节点中的所有元素称之为模板。

在模板中,可以直接访问魔术属性。

例如:

html
<div x-data="{}" x-init="console.log($el)">
    <button @click="$dispatch('toggle')">Toggle</button>
</div>

4.2 在函数组件中通过 this 访问魔术属性

函数组件就是使用函数来定义 x-data 的组件,它允许在 script 标签中定义组件逻辑。

与之相对的是,使用行内的对象定义 x-data,如 x-data={ isOpen: false } ,以及行内指令如 @click="isOpen = !isOpen"

html
<div x-data="{ isOpen: false }">
    <p x-show="isOpen">
         What you can toggle
    </p>
    <button @click="isOpen = !isOpen">
        Toggle
    </button>
</div>

我们使用函数组件重写:

html
<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 上不可用。

指令

this 可访问的魔术属性

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)。

4.3 通过在模板的 x-init 中传递 $dispatch 来访问魔术属性

我们可以从模板传递 $dispatch 到函数中,然后使用它。

html
<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>

4.4 通过在模板的 x-on 中传递 $event 和 $dispatch 来访问它

注意从模板中传递 $dispatch 的方式也适用于其他指令,x-on 最有可能使用 $dispatch。

html
<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>

参考资料:

点赞
收藏
暂无评论,快来发表评论吧~