A. *_*Lau 4 javascript vue.js vuejs2
我来自 JSX 的反应背景,所以使用类似
var test = <div>i am a div</div>
设置一些东西的 html 是很常见的。我知道您可以使用 v-html 实现相同的目的,但想知道根据我的以下代码,这是否是最好/最安全的方法:
组件
<template src="./templates/General.html"></template>
<script>
export default {
name: 'guide-general',
data: function() {
return {
guides: [
{
title: "first",
description: "First description"
},
{
title: "second",
description: "second description"
},
{
title: "third",
description: `<ul>
<li>
test
</li>
</ul>`
}
]
}
},
methods: {
}
}
</script>
<style scoped>
</style>
Run Code Online (Sandbox Code Playgroud)
html模板
<article>
<div v-for="guide in guides">
<h4>{{ guide.title }}</h4>
<div v-html="guide.description">
</div>
</div>
</article>
Run Code Online (Sandbox Code Playgroud)
如果您想包含从 vue 属性呈现 HTML 的功能,您将需要使用v-html. 如果您允许用户修改 HTML 可能来自的属性,那么您将遇到 XSS 漏洞的安全问题,在这种情况下,您需要在将数据发送回时清理您的输入服务器(我强烈建议您为此使用信誉良好的外部库)。如果用户不会修改您的数据,那么使用完全没有安全问题v-html。
每当您允许用户修改任何类型的数据时,您就会面临潜在的安全问题。您只需要预测这些问题是什么并解决它们。
2021 年 6 月更新
澄清一点,如果您不需要动态 HTML 渲染,而只需要处理渲染某些预定 HTML 模板的条件情况,那么您可以简单地在 Vue 模板中包含条件渲染。一个示例可能如下所示:
<script>
export default {
name: 'guide-general',
data: function() {
return {
guides: [
{
title: "first",
description: "First description",
as_list: false
},
{
title: "second",
description: "second description",
as_list: false
},
{
title: "third",
description: "test",
as_list: true
}
]
}
},
methods: {
}
}
</script>
<article>
<div v-for="guide in guides">
<h4>{{ guide.title }}</h4>
<div v-if="guide.as_list">
<ul>
<li>{{guide.description}}</li>
</ul>
</div>
<div v-else>{{guide.description}}</div>
</div>
</article>
Run Code Online (Sandbox Code Playgroud)
简而言之,如果您不需要动态HTML 呈现而只需要条件HTML 呈现,则v-if在适用的情况下使用并构建您的数据以允许条件呈现正确运行。否则使用v-html,甚至可能构造 JSON 数据来递归生成预定义的组件<component :is="component.name">(这相当复杂,所以我不会在这个答案中详细介绍)。
对于任何寻求渲染仅限于一组标签的 hmtl 的方法的人来说,解决方案是解析 html 字符串并使用渲染函数以编程方式构建模板。通过这种方法,您可以创建自己的安全 html 渲染器并避免使用v-html外部库。以下是此类 html 视图组件的一个小示例:
HtmlView.vue
<script>
import { h } from "vue";
export default {
props: {
html: {
type: String,
required: true,
},
tags: {
/** @type {import("vue").PropType<String[]>} */
type: Array,
default: () => ["b"]
},
},
setup(props) {
const html = parseHTML(props.html);
// return the render function
return () => {
const output = [];
html.childNodes.forEach(childNode => {
output.push(renderNode(childNode, props.tags));
});
if (output.length == 1) {
return output[0];
} else if (output.length == 0) {
return "";
}
return output;
};
}
};
const parseHTML = (html) => {
var template = document.createElement("template");
template.innerHTML = html;
return template.content;
};
/**
*
* @param {Node} node
* @param {String[]} tags
*/
const renderNode = (node, tags) => {
const nodeType = node.nodeType;
if (nodeType == 1) {
const nodeName = node.nodeName.toLocaleLowerCase();
if (tags.includes(nodeName)) {
const children = [];
node.childNodes.forEach(childNode => {
children.push(renderNode(childNode, tags));
});
return h(nodeName, children);
}
}
return node.textContent;
};
</script>
Run Code Online (Sandbox Code Playgroud)
组件的属性tags限制了支持的标签集。在此示例中,默认情况下仅<b>支持标签。
请注意,上面的示例将仅渲染类型 1 ( ) 的DOM 节点ELEMENT_NODE,并且还将省略节点的任何属性,但它可以轻松扩展以支持所需的属性。
我在这里创建了一个工作示例。
| 归档时间: |
|
| 查看次数: |
8868 次 |
| 最近记录: |