Vue - доступ к вложенным дочерним элементам с помощью ссылки

У меня есть компонент vue, который я использую внутри себя - данные могут иметь массив с подэлементами, и я использую этот массив для их рендеринга в цикле, а также на следующем уровне, следующем уровне и т. Д. В соответствии с уровнем вложенности.

Теперь я хотел бы запустить дочерний метод от родителя, а затем - если операторы в порядке, также вызовите его дочернему, следующему уровню и т. Д.

я использую

    <mycomponent
            ref="myFirstLevelRefName"
            (...)
    ></mycomponent>

а потом:

this.$refs.myFirstLevelRefName 

вызвать детей первого уровня. Но как насчет дочерних узлов? Я использую их таким образом:

    <mycomponent
            v-for="(subElement, index) in getSubelements()"
            ref="???"
            v-bind:data="subElement"
            v-bind:key="index"
    ></mycomponent>

Я попытался отправить this. $ Refs с дочернего уровня на консоль, но он пуст.

Как мне установить имя ссылки во вложенных элементах, а затем вызвать их из родительского элемента?


person lukasamd    schedule 05.04.2018    source источник


Ответы (1)


Хотя технически возможно получить доступ к $refs вложенным дочерним элементам ...

Vue.component('mycomponent', {
    template: "#mycomponent",
});

new Vue({
  el: '#app',
  mounted() {
    console.log(
      'Second level <input>\'s value:',
      this.$refs.myFirstLevelRefName.$refs.mySecondLevelRefName.value
    )
  }
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>

<template id="mycomponent">
    <div>
        <input ref="mySecondLevelRefName" value="Hello">
    </div>
</template>

<div id="app">
  <mycomponent ref="myFirstLevelRefName"></mycomponent>
</div>

Для простых сценариев одним из способов взаимодействия между родителями и глубокими потомками или глубокими предками и братьями и сестрами является использование концентратора событий. (Для сложных сценариев см. Vuex.)

Вы бы создали глобальную переменную:

var eventHub = new Vue(); // use a Vue instance as event hub

Чтобы генерировать события, которые вы должны использовать в любом компоненте:

eventHub.$emit('myevent', 'some value');

Тогда вы бы в любом другом компоненте прослушали это событие. Действие этого события может быть любым, включая вызов метода (что вам и нужно):

eventHub.$on('myevent', (e) => {
    console.log('myevent received', e)
    // this.callSomeMethod();
});

Демо:

var eventHub = new Vue(); // use a Vue instance as event hub

Vue.component('component-first', {
    template: "#component-1st",
    methods: {
      myMethod() {
        eventHub.$emit('myevent', 'some value');
      }
    }
});
Vue.component('component-second', {template: "#component-2nd"});
Vue.component('component-third', {
  template: "#component-3rd",
  created() {
    eventHub.$on('myevent', (e) => {
      this.check();
    });
  },
  methods: {
    check() {
      console.log('check method called at 3rd level child');
    }
  }
})

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>

<template id="component-1st">
    <div>
        1st level component
        <button @click="myMethod">Trigger event at 1st level component that will call 3rd level child's method</button>
        <hr>
        <component-second></component-second>
    </div>
</template>
<template id="component-2nd">
    <div>
        <component-third></component-third>
    </div>
</template>
<template id="component-3rd">
    <div><h1>3rd level child</h1></div>
</template>

<div id="app">
  <component-first></component-first>
</div>

Примечание. Если создание выделенного экземпляра в качестве концентратора событий является чем-то сложным в вашей среде, вы можете заменить eventHub на this.$root (внутри своих компонентов) и использовать свой собственный экземпляр Vue в качестве концентратора.

person acdcjunior    schedule 05.04.2018
comment
Я знаю, что это относительно старый пост, но только что столкнулся с проблемой, когда событие создавалось несколько раз при повторном рендеринге компонентов. Просто нужно добавить eventHub.$off('myevent') или this.$root.$off('myevent') в хук beforeDestroy для компонента. - person Rixcy; 14.03.2019
comment
@HamendraSunthwal Не могли бы вы задать новый вопрос и лучше сформулировать вашу проблему? - person acdcjunior; 06.06.2020