如何从子组件访问 alpine.js 父组件的属性或方法?

Posted

技术标签:

【中文标题】如何从子组件访问 alpine.js 父组件的属性或方法?【英文标题】:How to access a property or a method of alpine.js parent component from a child component? 【发布时间】:2020-10-18 02:06:26 【问题描述】:

这是问题看起来的一个示例场景,

<div x-data=" count : 0 ">
    <div x-data>
        <span x-text="count"></span>
        <button x-on:click="count++">Increment</button>
        <button x-on:click="count--">Decrement</button>         
    </div>
</div>

它将能够增加/减少来自子组件的数据count。 我曾想过通过使用$dispatch() 调度自定义事件来处理它,但在设计方面,我可能需要在父组件和子组件上编写侦听器,这使得逻辑更加复杂,因为它也应该是反应式的。

有一个 Github issue,但建议的解决方案都不起作用。

【问题讨论】:

【参考方案1】:

我曾想过通过使用 $dispatch() 调度自定义事件来处理它,但在设计方面,我可能需要在父组件和子组件上编写侦听器,这使得逻辑更加复杂,因为它也应该是反应式的.

这是问题的症结所在,为了进行父子子父通信,您需要使用事件。在 child -> parent 的情况下,您将触发 incrementdecrement 事件(将在父组件中使用 x-on:incrementx-on:decrement 监听)。在父 -> 子的情况下,您需要在 count 更新时使用 $watch 来触发更新(我将使用 new-count 事件名称),这将在 window 上收听子组件使用x-on:new-count.window

这是完整的工作解决方案(以CodePen 形式查看):

<div
  x-data=" count : 0 "
  x-init="$watch('count', val => $dispatch('new-count', val))"
  x-on:increment="count++"
  x-on:decrement="count--"
>
  <div>In root component: <span x-text="count"></span></div>
  <div
    x-data=" count: 0 "
    x-on:new-count.window="count = $event.detail"
  >
    <div>In nested component <span x-text="count"></span></div>
    <button x-on:click="$dispatch('increment')">Increment</button>
    <button x-on:click="$dispatch('decrement')">Decrement</button>
  </div>
</div>

在您介绍的情况下,count 状态可能通过使用与 Alpine.js 集成的全局存储(例如 Spruce)更好地服务,在这种情况下,我们将读取和更新共享的全局存储父组件和子组件都订阅了(请参阅 Spruce 文档)。您可以在以下CodePen 中找到工作示例。

<div x-data x-subscribe="count">
  <div>In root component: <span x-text="$store.count"></span></div>
  <div x-data x-subscribe="count">
    <div>In nested component <span x-text="$store.count"></span></div>
    <button x-on:click="$store.count ++">Increment</button>
    <button x-on:click="$store.count--">Decrement</button>
  </div>
</div>
<script>
  Spruce.store('count', 0);
</script>

最后应该提到的解决方案是,移除嵌套组件意味着计数的递增和递减将按预期工作。显然,这个例子可能是简化的并且是为了说明,所以这个解决方案在很多情况下可能不起作用。注意:唯一的区别是删除第二个x-data

<div x-data=" count : 0 ">
    <div>
        <span x-text="count"></span>
        <button x-on:click="count++">Increment</button>
        <button x-on:click="count--">Decrement</button>         
    </div>
</div>

【讨论】:

以上是关于如何从子组件访问 alpine.js 父组件的属性或方法?的主要内容,如果未能解决你的问题,请参考以下文章

从子 ui-view 组件访问父控制器

如何在 Reactjs 中将数据从子组件传递到父组件? [复制]

从子组件访问父组件。使用服务? @ContentChildren 呢?

如何在Angular中将表单数据从子组件传输到父组件

如何将变量的值从子组件发送到父组件?

我可以从子组件获取计算数据到父组件吗?