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

How to access a property or a method of alpine.js parent component from a child component?

这是问题的示例场景,

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

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

有 Github issue,none 个提议的解决方案有效。

I thought of handling it through dispatching custom events using $dispatch() but then again in terms of design, I might need to write listeners on both parent and child component which make the logic more complex since it should be reactive as well.

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

在 child 组件的 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>

在您介绍的情况下,使用与 Alpine.js 集成的全局存储(例如 Spruce, in which case we'll read and update a shared global store to which both the parent and child components are subscribed (see the Spruce docs). You can find the working example in the following CodePen.

可能会更好地服务于 count 状态
<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>