vuejs 2 v-for: ключ не работает, html заменяется?

#vue.js

#vue.js

Вопрос:

Я рендерю некоторый HTML в v-for

Но каждый раз, когда я изменяю какие-либо данные, весь мой html заменяется (поля ввода теряют свои значения)

Я пытался присвоить :ключу всевозможные значения

У меня не было этой проблемы в vue v1, только в v2

http://jsbin.com/jomuzexihu/1/edit?html , js, вывод

Ответ №1:

Я немного поиграл с этим, и оказалось, что Vue не перерисовывает весь список при использовании <input /> или если вы используете component , но это происходит с v-html . Вот скрипка для сравнения:

https://jsfiddle.net/cxataxcf/

Ключ на самом деле здесь не нужен, потому что список не переупорядочивается, поэтому ваша проблема связана не с :key , а скорее с v-html . Вот что говорится в документах о v-html :

Содержимое вставляется как обычный HTML — привязки данных игнорируются. Обратите внимание, что вы не можете использовать v-html для создания частичных элементов шаблона, поскольку Vue не является шаблонизатором на основе строк. Вместо этого компоненты предпочтительнее в качестве основной единицы для повторного использования пользовательского интерфейса и композиции.

Итак, я думаю, в этом и заключается проблема.

Возможно, стоит поднять вопрос на странице github Vue, чтобы узнать, является ли это ожидаемым поведением для v-html , но Vue 2.0 гораздо более ориентирован на компоненты, чем vue 1.x, и, похоже, не рекомендует использовать v-html , поэтому, возможно, вам просто нужно перефакторизовать свой код, чтобы использовать компоненты вместо этого.

Редактировать

Решение этой проблемы — просто обернуть код в компонент и передать HTML в качестве реквизита:

 Vue.component('unknown-html', {
  props: {
    html: ""
  },
  template: '<div><div v-html="html"></div>'
})
  

Разметка:

   <unknown-html :html="thing.html"></unknown-html>
  

И модель представления:

 var app = new Vue({
  el: '#app',
  data: {
    numInputs: 1,
    stuff: [{
      'html':'<input />'
    }, {
      'html':'<button>Foo</button>'
    }]
  }
})
  

Вот JSFiddle:https://jsfiddle.net/wrox5acb /

Комментарии:

1. Мне нужен v-html, потому что внешние плагины могут определять свой собственный html для отображения в моем списке. Раньше я использовал {{{myHtml}}} , но это было обесценено. HTML не является повторно используемыми компонентами, это просто произвольная строка html. Каковы ваши лучшие предложения о том, как я могу заставить его работать, вернуться к vue v1? хех

2. Если вам нужно отобразить HTML, вы можете просто обернуть его в компонент, передав его как prop. Вот JSFiddle: jsfiddle.net/wrox5acb

3. <unknown-html> Компонент выглядит так, как будто он будет работать для меня, спасибо!

Ответ №2:

Вы пытаетесь внедрить необработанный HTML непосредственно в DOM. Вероятно, это было возможно в более ранних версиях Vue.js , но это определенно не рекомендуемый способ.

Вместо этого вы можете создать массив объектов и привязать его к html, как показано в этом jsFiddle:https://jsfiddle.net/43xz6xqz /

Vue.js версия: 2.0.3

В приведенном выше примере vue.js отвечает за создание input элементов, а также за привязку этих input элементов к используемым значениям объекта v-model .

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

Ответ №3:

Я думаю, для оптимизации производительности, когда ключ не меняется, Vue не будет повторно отображать dom, но обновит импорт данных с помощью директивы.Итак, когда ваш элемент ввода импортируется с помощью директивы (v-html), он будет повторно отображаться каждый раз, когда что-то меняется.

Из-за того, что vue — это не движок шаблонов строк, а шаблон, основанный на dom, поэтому в случае с примером @craig_h , чтобы использовать исходный html в шаблоне строк в компоненте:

 Vue.component('unknown-html', {
   props: {
     html: ""
   },
   template: '<div><div v-html="html"></div>'
})  

view:
<unknown-html :html="thing.html"></unknown-html>
  

Поэтому, когда материал меняется, он не будет повторно отображать объявление шаблона в строке, поскольку vue не является механизмом шаблонов строк.