这是问题看起来像的一个示例场景,
<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()
调度自定义事件来处理它,但是再次在设计方面,我可能需要在父组件和子组件上编写侦听器,这会使逻辑更加复杂,因为它也应该是响应式的。 / p>
有一个Github issue,并且所有提议的解决方案都没有用。
答案 0 :(得分:3)
我曾考虑通过使用$ dispatch()调度自定义事件来处理它,但随后在设计方面,我可能需要在父组件和子组件上编写侦听器,这会使逻辑更加复杂,因为它也应该是响应式的
这是问题的症结所在,为了进行父子和子母沟通,您需要使用事件。对于子级->父级,您将触发increment
和decrement
事件(将使用x-on:increment
和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>
在您介绍的情况下,通过使用与Alpine.js集成的全局存储(例如Spruce)可以更好地满足count
状态,在这种情况下,我们将阅读并更新父组件和子组件都订阅到的共享全局存储(请参见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>