vue3有关v-html渲染的bug

测试版本: vue@3.2.31 https://github.com/vuejs/core...

我们来看这样一个vue单文件组件的文件App.vue

<template>
  <pre data-type="js">
    <code v-html="'&lt;span&gt;show-it.&lt;/span&gt;'"/>
  </pre>
  <div class><span class></span><span class></span></div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'App',
});
</script>

完整案例可以在这里在线查看:https://stackblitz.com/edit/vue3-v-html-render-error

或者查看https://codesandbox.io/s/eager-paper-prv33s

该案例中,show-it是可以正常显示的,但如果我们去掉v-html中的英文点号.,则当前代码是无法正常显示的。经过测试,发现还有以下几种情况显示有问题:

  1. 【无法显示】去掉那个英文点号
<template>
  <pre data-type="js">
    <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
  </pre>
  <div class><span class></span><span class></span></div>
</template>
  1. 【正常显示】pre标签增加非html原生标签属性
<template>
  <pre a data-type="js">
    <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
  </pre>
  <div class><span class></span><span class></span></div>
</template>

3.【正常显示】去掉pre后面的兄弟标签,或者移除某个class属性

<template>
  <pre data-type="js">
    <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
  </pre>
  <div><span class></span><span class></span></div>
</template>
<template>
  <pre data-type="js">
    <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
  </pre>
</template>

4.【无法显示】div标签内增加第三个带class(html原生标签属性)的子元素

<template>
  <pre data-type="js">
    <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
  </pre>
  <div class><span class></span><span class></span><span class></span></div>
</template>

5.【正常显示】div标签内增加第三个带a(非html原生标签属性)的子元素

<template>
  <pre data-type="js">
    <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
  </pre>
  <div class><span class></span><span class></span><span a></span></div>
</template>

6.【正常显示】外部包裹一层带非html原生标签属性的元素

<template>
  <div a>
    <pre data-type="js">
      <code v-html="'&lt;span&gt;show-it&lt;/span&gt;'"/>
    </pre>
    <div class><span class></span><span class></span></div>
  </div>
</template>

这就很奇怪了:

  1. 如果他的显示和非html原生标签属性有关,那么例子1、3、4说不过去
  2. 如果他的显示和某些特殊符号.有关系,那么除了例子1以外的都说不过去

查了很久,不知道究竟错在了哪里,还是vue3本身解析语法树的问题,请求网络上的各位大神帮忙看看,也请各位帮我献计献策找找原因吧。

阅读 9k
1 个回答

简单看了下,感觉是bug,可以尝试去github上提个issue


我这边简单研究了下编译产物,基本可以确定是vue3在做静态树提升(Static Tree Hoisting)优化时在某些条件下错误的把v-html里的东西优化没了,导致表现出问题
在生成静态节点代码时,如果节点比较简单,就会用createTextVNode和createElementVNode去拼这个静态节点
如果静态节点比较复杂且满足一些其他不知道什么的条件时,vue3就会去调用createStaticVNode去生成静态节点(createStaticVNode接受一个字符串,字符串内容是html字符串)
产生问题的case就是命中了vue3使用createStaticVNode去生成静态节点的优化,而vue3生成的createStaticVNode的参数,即这个静态节点生成的html字符串有问题(此时其实因为有v-html接收参数不应该使用createStaticVNode去生成静态节点,而应该用createTextVNode和createElementVNode手动拼,官方的修复方案也是改了判断条件)
github上已经有人给出了workaround
https://github.com/vuejs/core...
就是在传给v-html的静态字符串外面加个括号,避免静态树提升优化

<code v-html="('&lt;span&gt;show-it&lt;/span&gt;')"></code>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏