zoukankan      html  css  js  c++  java
  • 根据json数据和HTML模板,渲染嵌套的HTML

    2020-12-22 11:53:23 星期二

    场景, HTML模板是多个div嵌套, 里边有列表, 也有键值对, 与之匹配的有一个json数据, 需要根据json去渲染这个HTML DOM

    示例截图:

    1. HTML模板

     1     <div id="test">
     2         <div>{aa}</div>
     3         <div>{bb}</div>
     4         <div>{mm}</div>
     5         <div>
     6             <div class="cc">{n} : {v} : {mm}</div>
     7         </div>
     8         <div class="dd">
     9             <div>{d1}</div>
    10             <div>{d2}</div>
    11             <div>{mm}</div>
    12             <div class="d3">{x} : {y} : {mm}</div>
    13         </div>
    14     </div>

    2. json数据 (注意mm, 这个键在内外层都有)

     1 {
     2     'aa' : 'aa',
     3     'bb' : 'bb',
     4     'mm' : '1',
     5     'cc' : [
     6         {'n': 'n1', 'v' : 'v1', 'mm' : '2' },
     7         {'n': 'n2', 'v' : 'v2', 'mm' : '2' },
     8         {'n': 'n3', 'v' : 'v3', 'mm' : '2' },
     9     ],
    10     'dd' : [
    11         'd1' : 'd1',
    12         'd2' : 'd2',
    13         'd3' : [
    14             {'x' : 'x1', 'y': 'y1', 'mm': '4'},
    15             {'x' : 'x2', 'y': 'y2', 'mm': '4'},
    16             {'x' : 'x3', 'y': 'y3', 'mm': '4'},
    17         ],
    18         'mm' : '3'
    19     ]
    20 };

    3. 渲染方法 (注意, 适用了递归, 先渲染内层的数据, 再渲染外层数据, 防止内外层有相同的键导致覆盖)

     1     /**
     2         * @param node HTML DOM节点, 注意不是string
     3         * @param arr json数组 注意是数组类型
     4         * @return string 返回HTML字符串, 注意不是DOM节点
     5         */
     6         function repeatNode(node, arr) {
     7 
     8             let out = [];
     9             for (let i=0; i<arr.length; i++) {
    10                 let tmp = node.outerHTML;
    11                 console.log(tmp);
    12                 tmp = tmp.replace(/s/g, ' '); //去掉回车换行, 减少空白符
    13 
    14                 let map = arr[i];
    15                 console.log(map);
    16 
    17                 //先渲染内层的数组
    18                 for (let j in map) {
    19                     if (map[j] instanceof Array) { //数组, 递归替换
    20                         let subNode = node.querySelector('.'+j);
    21                         let subHtml = repeatNode(subNode, map[j]); //递归
    22                         let subTpl = subNode.outerHTML.replace(/s/g, ' ');
    23                         tmp = tmp.replace(subTpl, subHtml);
    24 
    25                     }
    26                 }
    27 
    28                 //再渲染内层的对象
    29                 for (let j in map) {
    30 
    31                     if (map[j] instanceof Object && !(map[j] instanceof Array)) { //对象, 递归替换
    32                         
    33                         let subNode = node.querySelector('.'+j);
    34                         let subHtml = repeatNode(subNode, [map[j]]); //递归
    35                         let subTpl = subNode.outerHTML.replace(/s/g, ' ')
    36                         tmp = tmp.replace(subTpl, subHtml);
    37 
    38                     }
    39                 }
    40 
    41                 //最后渲染外层的键值对/字符串
    42                 for (let j in map) {
    43                     if (typeof map[j] === 'string') { //字符串, 直接替换
    44                         let re = new RegExp('{' + j + '}', 'g');
    45                         tmp = tmp.replace(re, map[j]);
    46 
    47                     }
    48                 }
    49 
    50                 out.push(tmp);
    51             }
    52 
    53             return out.join('');
    54         }

    4. 全部代码

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=yes">
      6     <title>Title</title>
      7     <script src="/static/jquery.min.js"></script>
      8     <style type="text/css">
      9         div {margin:8px; margin-left: 10px; padding: 3px; border-radius: 5px;  80%;}
     10         #test {background-color: #eee;}
     11         .cc {background-color: #ccc;}
     12         .dd {background-color: #aaa;}
     13         .d3 {background-color: #888;}
     14     </style>
     15 </head>
     16 <body>
     17     <div id="target"></div>
     18 
     19 <!-- 注意{mm}是内外层都有 -->
     20 <template id="tpl">
     21     <div id="test">
     22         <div>{aa}</div>
     23         <div>{bb}</div>
     24         <div>{mm}</div>
     25         <div>
     26             <div class="cc">{n} : {v} : {mm}</div>
     27         </div>
     28         <div class="dd">
     29             <div>{d1}</div>
     30             <div>{d2}</div>
     31             <div>{mm}</div>
     32             <div class="d3">{x} : {y} : {mm}</div>
     33         </div>
     34     </div>
     35 </template>
     36    
     37     <script type="text/javascript">
     38         let arr = [{"aa":"aa","bb":"bb","mm":"1","cc":[{"n":"n1","v":"v1","mm":"2"},{"n":"n2","v":"v2","mm":"2"},{"n":"n3","v":"v3","mm":"2"}],"dd":{"d1":"d1","d2":"d2","d3":[{"x":"x1","y":"y1","mm":"4"},{"x":"x2","y":"y2","mm":"4"},{"x":"x3","y":"y3","mm":"4"}],"mm":"3"}}];
     39 
     40         let tpl = document.getElementById('tpl').innerHTML;
     41         let node = htmlToNode(tpl);
     42         //console.log(node);
     43 
     44         document.getElementById('target').innerHTML = repeatNode(node, arr);
     45 
     46         /**
     47         * @param node HTML DOM节点, 注意不是string
     48         * @param arr json数组 注意是数组类型
     49         * @return string 返回HTML字符串, 注意不是DOM节点
     50         */
     51         function repeatNode(node, arr) {
     52 
     53             let out = [];
     54             for (let i=0; i<arr.length; i++) {
     55                 let tmp = node.outerHTML;
     56                 console.log(tmp);
     57                 tmp = tmp.replace(/s/g, ' '); //去掉回车换行, 减少空白符
     58 
     59                 let map = arr[i];
     60                 console.log(map);
     61 
     62                 //先渲染内层的数组
     63                 for (let j in map) {
     64                     if (map[j] instanceof Array) { //数组, 递归替换
     65                         let subNode = node.querySelector('.'+j);
     66                         let subHtml = repeatNode(subNode, map[j]); //递归
     67                         let subTpl = subNode.outerHTML.replace(/s/g, ' ');
     68                         tmp = tmp.replace(subTpl, subHtml);
     69 
     70                     }
     71                 }
     72 
     73                 //再渲染内层的对象
     74                 for (let j in map) {
     75 
     76                     if (map[j] instanceof Object && !(map[j] instanceof Array)) { //对象, 递归替换
     77                         
     78                         let subNode = node.querySelector('.'+j);
     79                         let subHtml = repeatNode(subNode, [map[j]]); //递归
     80                         let subTpl = subNode.outerHTML.replace(/s/g, ' ')
     81                         tmp = tmp.replace(subTpl, subHtml);
     82 
     83                     }
     84                 }
     85 
     86                 //最后渲染外层的键值对/字符串
     87                 for (let j in map) {
     88                     if (typeof map[j] === 'string') { //字符串, 直接替换
     89                         let re = new RegExp('{' + j + '}', 'g');
     90                         tmp = tmp.replace(re, map[j]);
     91 
     92                     }
     93                 }
     94 
     95                 out.push(tmp);
     96             }
     97 
     98             return out.join('');
     99         }
    100 
    101         function htmlToNode(html) {
    102             let div = document.createElement('div');
    103             let pos = html.indexOf('<'); //避免开头有空白
    104             div.innerHTML = html.substring(pos);
    105             return div.firstChild;
    106         }
    107 
    108                
    109     </script>
    110 
    111 </body>
    112 </html>
    View Code

    推荐几个自己开发的小工具:

    SummerPHP 一款简洁的PHP框架, 支持多种方式渲染HTML, 支持接口化

    zbJSTool 好用的js库集合, 单页面路由框架, 前端生成分享图等等

    microStore 单页面, 小巧, 适用移动端的个人商店系统

  • 相关阅读:
    C# 将Excel中的数据到DataSet中
    Struts select标签在 FreeMarker 中的使用。
    .Net 中显式实现接口
    C#抽象类和抽象方法的应用
    iframe 自动控制高
    兔子问题总结(总结)
    MySQL group_concat 方法的使用
    服务发现与负载均衡机制的实现
    ChannelFuture
    服务发布、订阅及远程通信
  • 原文地址:https://www.cnblogs.com/iLoveMyD/p/14172238.html
Copyright © 2011-2022 走看看