Атрибут Vue.js в сгенерированном html

149
29 декабря 2021, 07:20

Мне нужно сделать обработчик события click для html элемента, который динамически генерируется с помощью vue.js(v-html). Каким образом это реализовать? Когда пишу один из атрибутов @click="названиеМетода", то после генерации этот атрибут не работает. Есть ли рабочая альтернатива?

Answer 1

Разметка подставленная через атрибут v-html не обрабатывается как шаблон (поэтому, в ней не будут работать атрибуты и директивы Vue).

И прямое назначение обработчиков DOM-элементам внутри Vue-приложения, является костылем.

Vue-way решение

Динамическое создание компонента, и его отображение через <component>:

const vm = new Vue({
  el: '#app', 
  data: {
    dynamic: null
  }, 
  methods: {
    setDynContent() {
      this.dynamic = Vue.component('dyn-cmpnt', { template: `
        <div class="dyn">
          Lorem <span @click="$emit('my-evt', 'foo'); $parent.logClick($event);">ipsum</span> dolor sit amet
        </div>
      `}); 
    }, 
    logClick(e)   { console.log(e.target.outerHTML); }, 
    onMyEvt(data) { console.log('Данные события: ' + data); }
  }
}); 
.dyn { margin: 1rem 0 0 0; }
.dyn > span { color: #47f; }
<div id="app">
  <button @click="setDynContent">Динамический контент</button>
  <component :is="dynamic" @my-evt="onMyEvt"></component>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>

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

Несмотря на то что указание метода/свойства родителя через $parent выглядит короче и проще - лучше выпускать кастомные события через $emit, так как обращение через $parent является источником потенциальных ошибок.

К тому же, родительский экземпляр может подписываться на события выборочно... А при обращении напрямую через $parent - такой возможности нет: в этом случае получается что дочерний экземпляр "управляет" родительским (и это абсолютно нелогично).

Третья, не показанная тут возможность обмена данными - через действия и мутации Vuex. В больших приложениях это наиболее удобный способ, но он за рамками вопроса.

А когда разметка шаблона генерируется асинхронно - нужно использовать асинхронную фабрику компонента.

Answer 2

Обработка событий не vue компонентов сгенерированных динамически с помощью v-html может производится с помощью обычного js используя ссылку ref на элементы! Пример ниже:

var app = new Vue({ 
  el: '#app', 
  data() { 
    return { 
      myHtml: '<a href="#">click me</a>' 
    } 
  }, 
  mounted() { 
    this.$refs['mydiv'].firstChild.addEventListener('click', function(event) { 
      event.preventDefault(); 
      console.log('clicked: ', event.target); 
    }) 
  } 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> 
<div id="app"> 
    <div v-html="myHtml" ref="mydiv"></div>  
</div>

READ ALSO
Направление движения свайпа

Направление движения свайпа

Я начал делать меню, чтобы при свайпе влево, открывалось меню, а при свайпе вправо закрывалосьНо я не понимаю, как мне определять продолжительность...

121
Достать геоданные асинхронно

Достать геоданные асинхронно

есть фрагмент кода, который возвращает геоданные пользователя(широта, долгота) в таком варианте:

216
Uncaught TypeError: Cannot read property &#39;checked&#39; of undefined [закрыт]

Uncaught TypeError: Cannot read property 'checked' of undefined [закрыт]

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском

178