如何以符合惯用方式在Vue 3中触发兄弟组件上的效果?

huangapple go评论78阅读模式
英文:

How can I trigger effect on sibling component in vue3 in an idiomatic way?

问题

我有2个组件Sibling1Sibling2,它们并排放置。我想在Sibling1上按下按钮,触发Sibling2上的效果。

  • 这个逻辑只存在于父组件内部,所以不需要将其设置为全局
  • 将此效果从组件中取出并放置在父组件上并不容易

我考虑的一种方法如下:

// App.vue(父组件)
const trigger = ref(null)
function setTrigger() {
  trigger.value = Symbol('new trigger')
}
</script>

<template>
    <SiblingOne @on-click="setTrigger" />
    <SiblingTwo :trigger="trigger" />
</template>

// Sibling1.vue
<script setup>
const emit = defineEmits(['on-click'])
</script>

<template>
  <button @click="emit('on-click')">update</button>
</template>

// Sibling2.vue
<script setup>
import { watch } from 'vue'
const props = defineProps({ trigger: null })

watch(
  () => props.trigger,
  () => console.log(new Date())
)
</script>
<template>Nothing to see here, check console</template>

我曾经看到过上面的模式,但也许有更好的替代方法。在Vue 3中,有什么好的方法可以做到这一点呢?

英文:

I have 2 components Sibling1 and Sibling2 that are placed side by side. I want to press a button on Sibling1 and trigger an effect on Sibling2.

  • This logic lives only inside the parent component, so no need to make it global
  • It's not easy to take out this effect outside of the component and put it for instance on the parent

One way I thought of doing it is like this:


// App.vue (parent)
const trigger = ref(null)
function setTrigger() {
  trigger.value = Symbol(&#39;new trigger&#39;)
}
&lt;/script&gt;

&lt;template&gt;
    &lt;SiblingOne @on-click=&quot;setTrigger&quot; /&gt;
    &lt;SiblingTwo :trigger=&quot;trigger&quot; /&gt;
&lt;/template&gt;



// Sibling1.vue
&lt;script setup&gt;
const emit = defineEmits([&#39;on-click&#39;])
&lt;/script&gt;

&lt;template&gt;
  &lt;button @click=&quot;emit(&#39;on-click&#39;)&quot;&gt;update&lt;/button&gt;
&lt;/template&gt;

// Sibling2.vue
&lt;script setup&gt;
import { watch } from &#39;vue&#39;
const props = defineProps({ trigger: null })

watch(
  () =&gt; props.trigger,
  () =&gt; console.log(new Date())
)
&lt;/script&gt;
&lt;template&gt;Nothing to see here, check console&lt;/template&gt;

I've seen the pattern above some times but maybe there are better alternatives. What would be a good way of doing this in vue3?

答案1

得分: 1

希望我推荐使用一个包是可以的。

我使用tiny-emitter来实现这个目的。它非常轻量级,并且正好可以满足你的需求。

只需记住也要关闭发射监听器。

英文:

I hope it's okay that I recommend a package to use.

I use tiny-emitter for this purpose. It's lightweight and does exactly what you need it to do.

Just remember to turn the emit listener off as well.

答案2

得分: 1

以下是翻译好的部分:

"trigger" 变量的必要性表明这是回调函数的情况。Sibling2 应该公开它,Sibling1 应该调用它:

App.vue

<script setup>
const siblingTwo = ref(null);
</script>

<template>
    <SiblingOne @click="siblingTwo?.trigger" />
    <!-- 或者 -->
    <SiblingOne @click="siblingTwo.trigger()" />

    <SiblingTwo ref="siblingTwo" />
</template>

Sibling2.vue

<script setup>
import { defineExpose } from 'vue'

defineExpose({
  trigger() {
    console.log(new Date())
  }
})
</script>
英文:

The necessity for trigger variable suggests this is the case for a callback. Sibling2 is supposed to expose it, Sibling1 is supposed to call it:

App.vue

&lt;script setup&gt;
const siblingTwo = ref(null);
&lt;/script&gt;
&lt;template&gt;
&lt;SiblingOne @click=&quot;siblingTwo?.trigger&quot; /&gt;
&lt;!-- or --&gt;
&lt;SiblingOne @click=&quot;siblingTwo.trigger()&quot; /&gt;
&lt;SiblingTwo ref=&quot;siblingTwo&quot; /&gt;
&lt;/template&gt;

Sibling2.vue

&lt;script setup&gt;
import { defineExpose } from &#39;vue&#39;
defineExpose({
trigger() {
console.log(new Date())
}
})
&lt;/script&gt;

huangapple
  • 本文由 发表于 2023年8月9日 13:58:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76864940-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定