VueJS:使用 v-html 来 appendChild 不起作用,为啥?

Posted

技术标签:

【中文标题】VueJS:使用 v-html 来 appendChild 不起作用,为啥?【英文标题】:VueJS: Using v-html to appendChild not working, why?VueJS:使用 v-html 来 appendChild 不起作用,为什么? 【发布时间】:2020-04-17 06:36:36 【问题描述】:

在这个简单的codesandbox demo 中,html 元素存储在一个数据数组中,v-html 绑定到一个 div 以将这些元素呈现为该 div 的子元素。但它不起作用,当添加新元素时,元素不会被渲染,而是显示[object HTMLParagraphElement]

应用程序.vue
<template>
  <div id="app">
    <child />
  </div>
</template>

<script>
import child from "./components/child";

export default 
  name: "App",
  components: 
    child
  
;
</script>

孩子.vue
<template>
  <div>
    <button @click="addNewEl">Add New Element</button>
    <div v-for="el in elList" v-html="el"></div>
  </div>
</template>

<script>
export default 
  name: "Child",
  data() 
    return 
      elList: []
    ;
  ,
  methods: 
    addNewEl() 
      var para = document.createElement("P"); // Create a <p> node
      var t = document.createTextNode("This is a paragraph."); // Create a text node
      para.appendChild(t); // Append the text to <p>
      this.elList.push(para);
    
  ,
  created() 
    this.addNewEl();
  
;
</script>

谁能告诉我我做错了什么,并展示将孩子附加到父母身上的正确 Vue 方式。

谢谢。

【问题讨论】:

【参考方案1】:

在 Vue 中直接向 DOM 添加元素不是必需的,而且是非常糟糕的做法。这是“Vue方式”的做法:

<template>
  <div>
    <button @click="addNewPara">Add New Para</button>
    <div>
     <p v-for="(p, index) in para" :key="index"> p </p>
    </div>
  </div>
</template>

<script>
export default 
  name: "Child",
  data() 
    return 
      para: ['This is a paragraph 1', 'This is a paragraph 2'],      
    ;
  ,
  methods: 
    addNewPara() 
      this.para.push(`This is a paragraph $this.para.length + 1`)
    
  
;
</script>

【讨论】:

【参考方案2】:

您可以使用以下方法修改方法:

addNewEl() 
  this.elList.push("<p>This is a paragraph.</p>");

【讨论】:

【参考方案3】:

由于v-html 期望将字符串解析为 HTML,因此在以编程方式呈现 HTML 元素时不能使用此指令。

改用元素的outerHTML 属性。 Reference

<template>
  <div>
    <button @click="addNewEl">Add New Element</button>
    <div v-for="el in elList" v-html="el.outerHTML"></div>
  </div>
</template>

【讨论】:

您好,感谢您的回答。通过el.outerHTML 添加el 实际上会删除附加到该元素的所有eventListener(从现有元素中删除并添加/推送到elList 数组时。有没有办法在以vue 方式进行时保留eventListeners。谢谢 @appu 你能展示你如何添加事件监听器的代码吗? 这里是使用v-html=el.outerHTML 的实际问题的demo。在演示中,图像是由Vue2Dropzone 在 childZones 中手动添加的。 fileWasAdded(event) 在 img 添加到 dropzone 时触发。在这里,我创建了一个新的 elem,将 dropzones file.previewTemplate 添加到它并将 elem 添加到数据数组中,导致 previewElements 计算进行评估(这种方式会丢失原始点击事件)。另一种方法是 appendsChild 'file.previewTemplate' 直接到 DOM $refs.childZoneRef (preserve click binding, but this isnt vue way). See slide-template.vue` 您有没有机会阅读我的最后一条评论或查看此demo。如果可以的话,请帮忙。再次感谢。

以上是关于VueJS:使用 v-html 来 appendChild 不起作用,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

vuejs v-html图像标签不解析src

VueJS根据for循环中的变量加载SVG文件,使用v-html给出[object Module]

VueJS 中的 v-html 不起作用(空页面)

在 vuejs2 数据中动态插入子组件(无需 $compile 或滥用 v-html)

[vue] - v-html解决Vue.js渲染过程中html标签不能被解析

VueJS - 清理输出以防止跨站点脚本攻击