Vue2. 4+ поведение компонента компиляции


Так что я недавно начал работать с Vue js. Я пытаюсь динамически добавлять и удалять узлы Vue. Это немного трудно описать проблему, поэтому я создал демо, чтобы проиллюстрировать ее.

Vue.component('context', {
  data() {
    return {
      test: '<context></context>', //Dummy recursive data to illustrate issue
      child: ''
    }
  },
  methods: {
    addChild() {
      this.child = this.test
    },
    removeChild() {
      this.child = ''
    }
  },
  computed: {
    dynamic() {
      return Vue.compile(this.child)
    },
    style() {
      return {
        'background-color': '#' + randHex(6)
      }
    }
  },
  template: `
        <div :style="style" @click="addChild" @click.shift="removeChild">
            <component :is="dynamic"></component>
        </div>
    `
})

new Vue({
  el: '#app'
})




function randHex(digits) {
  let hex = Math.floor(Math.random() * Math.pow(16, digits)).toString(16)
  return '0'.repeat(digits - hex.length) + hex
}
html,
body {
  height: 100%;
  overflow: hidden;
}

div {
  width: 90%;
  height: 90%;
}
<script src="https://unpkg.com/vue@2.4.3/dist/vue.js"></script>
<p>Click on the block to add, Shift-Click ro remove. Why does shift clicking always remove all inner blocks and not just the ones as children to the shift clicked block?</p>

<div id="app">
  <context></context>
</div>
Выше вы увидите, что щелчок по цветным прямоугольникам добавляет внутреннего ребенка, как и было задумано. Однако, когда вы нажимаете на прямоугольник, он удаляет не только своих детей, но и всех детей! (Даже те, которые являются родителями для текущего узел.)

Первоначально я думал, что событие щелчка "истекает" к нижним элементам, однако я создал немного более сложный тест, который смещал положение элементов, чтобы не быть выше друг друга, это все еще производило то же самое странное поведение.

Любая помощь в понимании / разрешении этого вопроса будет весьма признательна.

1 2

1 ответ:

Проблема в том, чтособытие пузырится : в то время как целевой ребенок получает щелчок и удаляет своих детей, как вы и предполагали, событие пузырится до всех родителей, которые делают то же самое по очереди.
К счастью, Vue предлагает легкий доступ к модификаторам событий , а именно .stop остановит дальнейшее распространение события.

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

Я обновил ваш пример кода с учетом вышеперечисленных проблем:

Vue.component('context', {
  data() {
    return {
      hasChild: false,
      style: {
        'background-color': '#' + randHex(6)
      }
    }
  },
  methods: {
    addChild() {
      this.hasChild = true
    },
    removeChild() {
      this.hasChild = false
    }
  },
  template: `
        <div :style="style" @click="addChild" @click.shift.stop="removeChild">
            <context v-if="hasChild"></context>
        </div>
    `
})

new Vue({
  el: '#app'
})

function randHex(digits) {
  let hex = Math.floor(Math.random() * Math.pow(16, digits)).toString(16)
  return '0'.repeat(digits - hex.length) + hex
}
html,
body {
  height: 100%;
  overflow: hidden;
}

div {
  width: 90%;
  height: 90%;
}
<script src="https://unpkg.com/vue@2.4.3/dist/vue.js"></script>

<div id="app">
  <context></context>
</div>