Vue v-for: динамически заполнять HTML обработчиком событий (@change) из массива в шаблон компонента - PullRequest
0 голосов
/ 27 мая 2020

Это моя текущая настройка:

HTML

<question
   v-for="question in questions"
   v-bind:id="question.id"
   v-bind:title="question.title"
   v-bind:statement="question.statement"
   v-bind:interaction="question.interaction"
   @onchange-vg="onChangeVg"/>
</question>

Определение <question>

var questionComponent = Vue.component('question', {
   props: ['id', 'title', 'statement', 'interaction', 'currentQuestion'],
   template: `
      <div :id="'question-' + id">
         <div class="flex my-3">
            <div class="py-0"><span>{{ id }}</span></div>
            <div>
               <p>{{ title }}</p>
               <div :class="{'hidden':(id !== this.$parent.currentQuestion), 'block':(id === this.$parent.currentQuestion)}">
                  <p>{{ statement }}</p>
                  <span v-html="interaction"></span>
               </div>
            </div>
         </div>
      </div>
     `
});

Vue

var app = new Vue({
   el: '#app',
   data()  {
      return {
         vg: null,
         currentQuestion: 1,

         questions: [
            { 
               id: 1, 
               title: 'Question 1',
               statement: 'Details for question 1',
               interaction: `
                  <select ref="vb-art" @change="$emit('onchange-vg')">
                     <option disabled value="" selected>Make a choice</option>
                     <option value="red">Red</option>
                     <option value="blue">Blue</option>
                  </select>
               `
            },
            {
               title: 'Question 2',
               statement: 'Details for question 2',
               interaction: `
                  <select ref="vb-art" @change="$emit('onchange-vg')">
                     <option disabled value="" selected>Make a choice</option>
                     <option value="black">Black</option>
                     <option value="white">White</option>
                  </select>
               `
            },
         ], 

      }
   },

   methods: {
      onChangeVerguetungsart() {
         console.log("Value: " + event.target.value);
         currentQuestion++;
      },
   },
});

Все нормально рендерится. Моя проблема в том, что обработчик событий @change в <select ref="vb-art" @change="$emit('onchange-vg')"> не срабатывает.

Когда я заменяю <span v-html="interaction"></span> на весь <select ref="vb-art" @change="$emit('onchange-vg')">...</select> код из interaction, все работает нормально.

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

Как я могу решить эту проблему, чтобы <span v-html="interaction"></span> принимал обработчик событий из фрагмента кода, который доставляется массивом значение?

1 Ответ

1 голос
/ 27 мая 2020

Вам следует избегать v-html. v- html bind просто HTML, а не Vue директивы.

Для вас случай v- html не нужен. Сделайте массив параметров из свойства взаимодействия и сгенерируйте разметку по шаблону vue.

interaction: [
  {value: 'red', label: 'Red'},
  {value: 'blue', label: 'Blue'}
]

и в вашем компоненте

<select ref="vb-art" @change="$emit('onchange-vg')">
  <option disabled value="" selected>Make a choice</option>
  <option v-for="{value, label} in interaction" :key="value" :value="value">{{ label }}</option>
</select>

update: ЕСЛИ у вас есть динамическое c содержимое, тогда слот - ваш друг. (Дополнительные примеры см. В документации https://vuejs.org/v2/guide/components-slots.html)

Ваш компонент:

<div>
   <p>{{ title }}</p>
   <div>
      <p>{{ statement }}</p>
      <slot />
   </div>
</div>

И использование

<question
   v-for="question in questions"
   v-bind:id="question.id"
   v-bind:title="question.title"
   v-bind:statement="question.statement"
   v-bind:interaction="question.interaction"
 >
  <select ref="vb-art" @change="onChangeVg">
     <option disabled value="" selected>Make a choice</option>
     <option value="red">Red</option>
     <option value="blue">Blue</option>
   </select>
</question>

Бонус в том, что вы не нужно ничего испускать.

Кстати, используя this. $ parent тоже не лучшая идея. Ваш компонент связан с родителем. Вместо этого используйте реквизит.

...