子级向其父级的父级发送事件。

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

sub child emit an event to the parent of its parent

问题

可以,子组件-3可以直接向其父组件-2的父组件-1发送事件。

component1.vue

<component-2 />
// 代码
created() {
    this.$root.$on('sort-completed', () => {
        // 处理事件的代码
    });
}

component2.vue

<component-3 />
// 代码

component3.vue

<button @click="doThis" />

<script>
methods: {
    doThis() {
        this.$root.$emit('sort-completed', update);
    }
}
</script>
英文:

can sub child emit an event to the parent of its parent directly ?

i.e possible to component-3 child of component-2 emit to component-1 who is the parent of component-2 ?

component1.vue

&lt;component-2 /&gt;
//code
ceated(){
    this.$root.$on(&#39;sort-completed&#39; =&gt; {
}

component2.vue

&lt;component-3 /&gt;
//code

component3 .vue

&lt;button 
@click=&quot;doThis&quot; /&gt;

&lt;script&gt;
doThis(){
this.$root.$emit(&#39;sort-completed&#39;, update);
}
&lt;/script&gt;```


</details>


# 答案1
**得分**: 0

这是不可持续的,也不建议使用。你可以根据事件总线来操作,以下是有关事件总线的信息:

https://gist.github.com/tachibana-shin/d3139d3f24f51d81cf890439d3a05d0c

<details>
<summary>英文:</summary>

this is not sustainable and not recommended you can use event bus according to event bus i below:

https://gist.github.com/tachibana-shin/d3139d3f24f51d81cf890439d3a05d0c

</details>



# 答案2
**得分**: 0

这是您提供的代码段的翻译:

这将子组件和祖父组件紧密耦合,这几乎总是不好的风格,特别是因为它会混淆发射链。某人(可能是未来的您)将会想知道为什么父组件上的监听器在父组件中没有被调用,但仍然被触发,他们会感到不满...

----------

不过,组件实例可以通过[`$parent`](https://vuejs.org/api/component-instance.html#parent)属性访问父组件。使用这个属性,你可以向祖父组件发射事件:
```javascript
methods: {
  emitToGrandparent(){
    this.$parent.$emit('my-event')
  }
}

你可以进行链式调用,例如 this.$parent.$parent.$emit('my-event')


在组合式 API 中,你可以通过调用getCurrentInstance()来获取组件实例,返回的对象具有parentemit属性(没有$前缀):

setup(){
  const instance = getCurrentInstance()
  const notifyGrandparent = () => {
    instance.parent.emit('my-event')
  }
}

以下是代码片段的翻译:

但是,这是一种不好的做法。如果你必须传递未声明的事件监听器,考虑至少明确地执行它,类似这样:

<child v-bind="$attrs"/>

希望这些翻译对您有帮助。如果您需要更多信息,请随时提问。

英文:

This tightly couples child and grandparent, which is pretty much always bad style, particularly as it obfuscates the emit chain. Someone (probably future you) is going to find themselves wondering why the listener on the parent is not called in the parent, but triggered nonetheless, and they won't be happy...


That said, the component instance has access to the parent component through the $parent property. With this, you can emit an event to the grandparent:

methods: {
  emitToGrandparent(){
    this.$parent.$emit(&#39;my-event&#39;)
  }
}

You can chain this, i.e. call this.$parent.$parent.$emit(&#39;my-event&#39;)


In Composition API, you get the component instance by calling getCurrentInstance(), the returned object has parent and emit properties (without the $):

setup(){
  const instance = getCurrentInstance()
  const notifyGrandparent = () =&gt; {
    instance.parent.emit(&#39;my-event&#39;)
  }
}

Here it is in a snippet:
<!-- begin snippet: js hide: true console: false babel: false -->

<!-- language: lang-js -->

const { createApp, getCurrentInstance } = Vue;

const child = {
  template: `
  &lt;div class=&quot;frame&quot;&gt;
    Child
    &lt;button @click=&quot;notifyGrandparent&quot;&gt;Notify Grandparent&lt;/button&gt;
  &lt;/div&gt;
  `,
  setup(){
    const instance = getCurrentInstance()
    const notifyGrandparent = () =&gt; {
      instance.parent.emit(&#39;notify&#39;, &#39;Child was clicked&#39;)
    }
    return {notifyGrandparent}
  }
}

const parent = {
  components: {child},
  template: `
  &lt;div class=&quot;frame&quot;&gt;
    Parent
    &lt;child /&gt;
  &lt;/div&gt;
  `
}

const grandparent = {
  components: {parent},
  template: `
  &lt;div class=&quot;frame&quot;&gt;
    Grandparent (notified {{counter}} times)
    &lt;parent @notify=&quot;incrementCounter&quot;/&gt;
  &lt;/div&gt;
  `,
  data(){
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter(){
      this.counter++
    }
  },
}

createApp(grandparent).mount(&#39;#app&#39;)

<!-- language: lang-css -->

.frame{
  border: 1px solid grey;
  margin: 8px;
  padding: 4px;
}

<!-- language: lang-html -->

&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;
&lt;script src=&quot;https://unpkg.com/vue@3/dist/vue.global.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->


But again, this is poor form. If you must pass on undeclared event listeners, consider at least doing it explicitly, something like:

&lt;child v-bind=&quot;$attrs&quot;/&gt;

<!-- begin snippet: js hide: true console: false babel: false -->

<!-- language: lang-js -->

const { createApp, getCurrentInstance } = Vue;

const child = {
  template: `
  &lt;div class=&quot;frame&quot;&gt;
    Child
    &lt;button @click=&quot;notify&quot;&gt;Notify&lt;/button&gt;
  &lt;/div&gt;
  `,
  emits: [&#39;notify&#39;],
  methods: {
    notify(){
      this.$emit(&#39;notify&#39;)
    }
  }
}

const parent = {
  components: {child},
  template: `
  &lt;div class=&quot;frame&quot;&gt;
    Parent
    &lt;child v-bind=&quot;$attrs&quot;/&gt;
  &lt;/div&gt;
  `
}

const grandparent = {
  components: {parent},
  template: `
  &lt;div class=&quot;frame&quot;&gt;
    Grandparent (notified {{counter}} times)
    &lt;parent @notify=&quot;incrementCounter&quot;/&gt;
  &lt;/div&gt;
  `,
  data(){
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter(){
      this.counter++
    }
  },
}

createApp(grandparent).mount(&#39;#app&#39;)

<!-- language: lang-css -->

.frame{
  border: 1px solid grey;
  margin: 8px;
  padding: 4px;
}

<!-- language: lang-html -->

&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;
&lt;script src=&quot;https://unpkg.com/vue@3/dist/vue.global.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月25日 19:59:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76550284.html
匿名

发表评论

匿名网友

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

确定