欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动态插入后台返回代码并设置指定样式(插入组件)

程序员文章站 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部分是没有标签包含的文本节点

基本上就是以上处理,具体细节需看完整代码