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

Irf*_*fan 3 javascript alpine.js

This is kind of an example scenario what the problem looks like,

<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>
Run Code Online (Sandbox Code Playgroud)

It would be able to increase/decrease the data count from the child component. 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.

There was a Github issue, and none of the proposed solutions was working.

Hug*_*ugo 5

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

这是问题的关键,为了进行父子子父通信,您需要使用事件。在 child -> parent 的情况下,您将触发incrementdecrement事件(将在父组件中使用x-on:incrementand侦听x-on:decrement)。在父级 -> 子级的情况下,您需要在$watch每次更新时使用来触发更新count(我将使用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>
Run Code Online (Sandbox Code Playgroud)

在您提供的情况下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>
Run Code Online (Sandbox Code Playgroud)

应该提到的最终解决方案是删除嵌套组件意味着计数增量和减量将按预期工作。显然,这个例子可能是简化的并且是为了说明,所以这个解决方案在很多情况下可能不起作用。注意:唯一的区别是删除第二个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>
Run Code Online (Sandbox Code Playgroud)