可以通过下面的链接查看问题,template里面的html与v-html是一样的代码,但是表现差异巨大
DEMO
可以通过下面的链接查看问题,template里面的html与v-html是一样的代码,但是表现差异巨大
DEMO
在使用 Vue.js 的 v-html
指令时,你确实可能会遇到与直接在模板中编写 HTML 不同的表现。这通常是因为 v-html
会直接渲染原始的 HTML 字符串,而 Vue 模板中的 HTML 会经过 Vue 的编译和虚拟 DOM 的处理。这种差异可能由以下几个原因引起:
v-html
插入的 HTML 可能不会(除非这些样式是全局的或具有足够的选择器优先级来覆盖)。v-html
插入的 HTML 是静态的,它不会响应 Vue 实例的数据变化。而模板中的 HTML 可以包含 Vue 指令(如 v-if
、v-for
等),这些指令会根据 Vue 实例的数据变化来动态地更新 DOM。v-html
插入不受信任的 HTML 可能会带来 XSS(跨站脚本攻击)的风险,因为它会执行 HTML 中的 JavaScript 代码。而直接在模板中编写的 HTML 则是安全的,因为 Vue 会对其进行适当的转义。为了规避这些差异,你可以考虑以下策略:
v-html
插入的 HTML 使用的样式与组件内部或全局样式一致。你可以通过检查 CSS 选择器的优先级和范围来实现这一点。v-html
:如果可能,尽量避免使用 v-html
。相反,使用 Vue 的数据绑定和指令来动态渲染内容。这不仅可以提高安全性,还可以保持代码的清晰和可维护性。综上所述,通过确保样式一致性、使用 Vue 组件、清理和过滤 HTML 以及避免使用 v-html
,你可以规避 v-html
与直接在模板中编写 HTML 之间的表现差异。
和编写 tempalte
和 v-html
没有关系。
只是因为你的 viewBox
拼写错了,修改成 viewBox
就行了。
<script setup>
const html = `<section><section><section style="margin: 10px auto; display: flex; justify-content: center; padding-bottom: 5px; box-sizing: border-box;"><section style="display: flex; flex-direction: column;"><section class="assistant" style="width: 35px; margin-left: auto; box-sizing: border-box;"><img src="https://oss.tccms.cn/1sqnkqGnuBk" draggable="false" class="assistant" style="width: 100%; display: block; vertical-align: baseline; box-sizing: border-box; max-width: 100% !important;"></section><section style="display: flex; flex-direction: column; margin: 0px 20px; z-index: 3;"><section style="font-size: 16px; color: rgb(255, 255, 255); text-align: center; z-index: 4;"><strong>Haha</strong></section><section style="width: 150px; margin: -43px auto 0px; box-sizing: border-box;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 219 81" xml:space="default" style="display: block;"><g id="图层_2"><g id="图层_1-2"><polygon points="212 9 207 0 18 9 9 10 0 59 18 81 207 81 219 22 211.91 9 212 9" style="fill: rgb(112, 204, 251); fill-rule: evenodd;"></polygon><path d="M13.71,47.59a5,5,0,1,1-5,5A5,5,0,0,1,13.71,47.59Z" style="fill: rgb(255, 255, 255); fill-rule: evenodd;"></path><path d="M16.71,31.59a5,5,0,1,1-5,5A5,5,0,0,1,16.71,31.59Z" style="fill: rgb(255, 255, 255); fill-rule: evenodd;"></path><path d="M19.71,15.59a5,5,0,1,1-5,5A5,5,0,0,1,19.71,15.59Z" style="fill: rgb(255, 255, 255); fill-rule: evenodd;"></path></g></g></svg></section></section><section style="width: 140px; margin-top: -40px; box-sizing: border-box;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 254.17 85.67" xml:space="default" style="display: block;"><g id="图层_2"><g id="图层_1-2"><path d="M16,0A16.28,16.28,0,0,0,0,16.53C0,25.66,16,42,16,42S32,25.66,32,16.53A16.27,16.27,0,0,0,16,0Zm0,22.91a7.72,7.72,0,1,1,7.68-7.72A7.69,7.69,0,0,1,16,22.91Z" style="fill: rgb(255, 216, 96); fill-rule: evenodd;"></path><path d="M17,42S-15.36,88.39,76,68c57.05-12.73,111.36-8.48,89,5-27,16.29,34.67,17.14,89-3" style="fill: none; stroke: rgb(51, 51, 51); stroke-dasharray: 6, 4;"></path></g></g></svg></section></section></section></section><section><p><br></p></section></section>`
</script>
<template>
<section><section><section style="margin: 10px auto; display: flex; justify-content: center; padding-bottom: 5px; box-sizing: border-box;"><section style="display: flex; flex-direction: column;"><section class="assistant" style="width: 35px; margin-left: auto; box-sizing: border-box;"><img src="https://oss.tccms.cn/1sqnkqGnuBk" draggable="false" class="assistant" style="width: 100%; display: block; vertical-align: baseline; box-sizing: border-box; max-width: 100% !important;"></section><section style="display: flex; flex-direction: column; margin: 0px 20px; z-index: 3;"><section style="font-size: 16px; color: rgb(255, 255, 255); text-align: center; z-index: 4;"><strong>Haha</strong></section><section style="width: 150px; margin: -43px auto 0px; box-sizing: border-box;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 219 81" xml:space="default" style="display: block;"><g id="图层_2"><g id="图层_1-2"><polygon points="212 9 207 0 18 9 9 10 0 59 18 81 207 81 219 22 211.91 9 212 9" style="fill: rgb(112, 204, 251); fill-rule: evenodd;"></polygon><path d="M13.71,47.59a5,5,0,1,1-5,5A5,5,0,0,1,13.71,47.59Z" style="fill: rgb(255, 255, 255); fill-rule: evenodd;"></path><path d="M16.71,31.59a5,5,0,1,1-5,5A5,5,0,0,1,16.71,31.59Z" style="fill: rgb(255, 255, 255); fill-rule: evenodd;"></path><path d="M19.71,15.59a5,5,0,1,1-5,5A5,5,0,0,1,19.71,15.59Z" style="fill: rgb(255, 255, 255); fill-rule: evenodd;"></path></g></g></svg></section></section><section style="width: 140px; margin-top: -40px; box-sizing: border-box;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 254.17 85.67" xml:space="default" style="display: block;"><g id="图层_2"><g id="图层_1-2"><path d="M16,0A16.28,16.28,0,0,0,0,16.53C0,25.66,16,42,16,42S32,25.66,32,16.53A16.27,16.27,0,0,0,16,0Zm0,22.91a7.72,7.72,0,1,1,7.68-7.72A7.69,7.69,0,0,1,16,22.91Z" style="fill: rgb(255, 216, 96); fill-rule: evenodd;"></path><path d="M17,42S-15.36,88.39,76,68c57.05-12.73,111.36-8.48,89,5-27,16.29,34.67,17.14,89-3" style="fill: none; stroke: rgb(51, 51, 51); stroke-dasharray: 6, 4;"></path></g></g></svg></section></section></section></section><section><p><br></p></section></section>
<div v-html="html" />
</template>
至于为什么,看起来是因为 v-html
给你的 svg
元素添加HTML属性时,使用 setAttribute() 方法导致的。该方法会将其属性名称自动转换为全小写形式这样来设置目标元素的 HTML 属性,正好规避掉了你的 viewbox
大小写错误的问题。
从当前表现来看使用v-html
的内容渲染是正确的viewBox
属性。
而在template
中编辑的内容渲染的是错误的viewbox
属性。
按照 @42 的提醒。检查了一下使用 innerHTML
时浏览器会自动识别并处理 svg
元素的 XML
属性,把拼写错误的 viewbox
转换成正确的 viewBox
。
而使用 template
中的 svg
内容会按照编写时错误的 viewbox
保持拼写错误拼写作为 props
值传递下去在创建 VNode
时作为 HTML attributes 值使用。
但浏览器不会自动处理 svg
元素的属性名称大小写错误。 因为 svg
也不是 HTML 元素 setAttribute
方法也不会自动处理转换成小写。
这两处的自动处理没有统一我倒是挺意外的。
8 回答5.8k 阅读✓ 已解决
9 回答9.2k 阅读
6 回答4.7k 阅读✓ 已解决
5 回答3.5k 阅读✓ 已解决
4 回答7.9k 阅读✓ 已解决
7 回答9.8k 阅读
5 回答7.1k 阅读✓ 已解决
将 vue 模板中 svg 的
viewbox
属性修改为viewBox
即可渲染一致