动态插入后台返回代码并设置指定样式(插入组件)
程序员文章站
2022-07-14 08:16:10
...
如果你对Vue render的使用方法不是很了解,则你需要先大概了解一下render,相信你阅读了解完之后,下面的内容将是很容易明白
一.首先先贴出整体代码
// styleConfig.vue文件
<script>
import CodeEditor from '@/lesson/component/CodeEditor.vue';
export default {
functional: true,
render: function(createElement, context) {
function _htmlToElement(html) { // 生成dom对象
var template = document.createElement('template');
html = html.trim();
template.innerHTML = html;
return template.content.childNodes;
}
function _styleConfiguration(elems) {
const children = [];
elems.forEach(ele => {
const tagName = ele.nodeName.toLocaleLowerCase();
const parentTagName = ele.parentNode.nodeName.toLocaleLowerCase();
if (ele.childNodes.length) { // 判断节点是否有子节点
if (tagName === 'code' && parentTagName === 'pre') { // 将code节点替换成CodeEditor组件
children.push(createElement(CodeEditor, {
props: {
code: ele.innerText
},
style: {
margin: '10px 0px',
borderRadius: '5px',
overflow: 'hidden'
}
}));
} else {
const domProps = {};
if (tagName === 'a') { // 处理a标签可能包含图片的类似情况
domProps.href = ele.href;
}
children.push(createElement(`${tagName}`, { domProps }, _styleConfiguration(ele.childNodes)));
}
} else {
if (tagName !== '#comment') { // 节点不是注释
if (tagName === '#text') { // 文本节点处理
if (ele.nodeValue) {
children.push(createElement('span', `${ele.nodeValue}`));
}
} else { // 普通节点
const domProps = {};
if (tagName === 'img') {
domProps.src = ele.src;
}
children.push(createElement(`${tagName}`, { domProps }, `${ele.nodeValue || ''}`));
}
}
}
});
return children;
}
return createElement('div', {
style: {
lineHight: '24px'
}
}, _styleConfiguration(_htmlToElement(context.props.html)));
}
};
</script>
二.接下来简单分析一下
我们所做的处理主要是面对后台返回数据是一段代码,我们需要动态的插入并配置样式,当然有的地方需要用特殊的组件来显示。
-------------------后台返回字符串如下----------------------
const htmlStr = "<h1>第一课左侧内容</h1>\n<h2>head2</h2>\n<h3>head3</h3>\n<h4>head4</h4>\n<h5>head5</h5>\n<h6>head6</h6>\n<p>中文的<em>斜体斜体</em> 和 <strong>粗体粗体</strong></p>\n<blockquote><p>引用</p>\n<blockquote><p>二级引用</p>\n<blockquote><p>三级引用</p>\n</blockquote>\n</blockquote>\n</blockquote>\n<p><code>inline code haahh</code> is not a code</p>\n<ul>\n<li>list item 1</li>\n<li>list item 2</li>\n<li>list item 3</li>\n</ul>\n<ol>\n<li>list item 1</li>\n<li>list item 2</li>\n<li>list item 3</li>\n</ol>\n<p>This is an <a href=\"http://example.com/\">example link</a>.</p>\n<p><img src=\"https://res.kaikeba.com/other/123/20200402095710-91462/Fl38h-qh66AihsAbIs7rMqlEH0hv.png\" alt=\"文字\" title=\"Title\"></p>\n\n<pre><code>a = 1\nb = 2\nc = 3\n\nprint('hello, world')</code></pre>\n"
1.将传回的字符串转成dom对象
function _htmlToElement(html) {
var template = document.createElement('template');
html = html.trim();
template.innerHTML = html;
return template.content.children;
}
2.遍历dom对象处理需要特殊处理的节点替换成指定的组件
function _styleConfiguration(elems) {
...
return children;
}
3.配置样式,返回的字符串转换成dom之后需要配置设计给定的样式,这个根据设计样式自行处理
a{}
h1,h2,h3,h4{}
p{}
...
4.引入使用
<styleConfig :html="htmlStr"></styleConfig>
5.效果实现
注意点
代码中之所以要处理文本节点是因为有如下的代码
<p><code>inline code haahh</code> is not a code</p>
代码inline code haahh部分是没有标签包含的文本节点
基本上就是以上处理,具体细节需看完整代码