首页  >  问答  >  正文

javascript - 我写的这段把对象数据变为DOM节点的代码该怎么优化?

简单介绍下思路:
ajax到对象,然后从子到父依次创建对象,设置样式,添加层级。
然后代码长这样:

function Activity(obj) {
  var activityContent = document.createElement('a');
  activityContent.innerHTML = obj.post.c;
  activityContent.className = 'activity-content';
  activityContent.style.overflow = 'hidden';
  activityContent.href = '/t/'+obj.tid+'#'+obj.pid;
  var activityTitleText = document.createElement('span');
  activityTitleText.innerHTML = obj.oc.t;
  activityTitleText.style.overflow = 'hidden';
  var activityTitle = document.createElement('p');
  activityTitle.className = 'activity-title';
  var activityTitleA = document.createElement('a');
  activityTitleA.appendChild(activityTitleText);
  activityTitleA.href = '/t/'+obj.tid;
  var activityInfo = document.createElement('span');
  activityInfo.className = 'activity-info';
  if(obj.forum) {
    var color = obj.forum.color || 'orange';
    var forum = document.createElement('a');
    forum.href= '/f/'+obj.fid;
    var forumText = document.createElement('span');
    forumText.className = 'activity-title-forum';
    forumText.style.backgroundColor = color;
    forumText.innerHTML = ' '+obj.forum.abbr+' ';
    forum.appendChild(forumText);
    activityTitle.appendChild(forum);
  }
  if(obj.toMyForum) {
    var color = obj.toMyForum.color || 'orange';
    var toMyForum = document.createElement('a');
    toMyForum.href= '/m/'+obj.toMyForum._key;
    var toMyForumText = document.createElement('span');
    toMyForumText.className = 'activity-title-forum';
    toMyForumText.style.backgroundColor = color;
    toMyForumText.innerHTML = ' '+obj.toMyForum.abbr+' ';
    toMyForum.appendChild(toMyForumText);
    activityTitle.appendChild(toMyForum);
  }
  if(obj.myForum) {
    var color = obj.myForum.color || 'orange';
    var myForum = document.createElement('a');
    myForum.href= '/m/'+obj.myForum._key;
    var myForumText = document.createElement('span');
    myForumText.className = 'activity-title-forum';
    myForumText.style.backgroundColor = color;
    myForumText.innerHTML = ' '+obj.myForum.abbr+' ';
    myForum.appendChild(myForumText);
    activityTitle.appendChild(myForum);
  }
  activityTitle.appendChild(activityTitleA);
  activityInfo.appendChild(activityTitle);
  activityInfo.appendChild(activityContent);
  var activityUser = document.createElement('p');
  activityUser.className = 'activity-user';
  activityUserA = document.createElement('a');
  activityUserA.href = '/activities/'+obj.uid;
  var activityUserAvatar = document.createElement('img');
  activityUserAvatar.className = 'activity-user-avatar';
  activityUserAvatar.src = '/avatar/'+ obj.uid;
  activityUserA.appendChild(activityUserAvatar);
  var username = document.createElement('a');
  username.href = '/activities/'+obj.uid;
  username.innerHTML = obj.user.username;
  activityUser.appendChild(activityUserA);
  activityUser.appendChild(username);
  var type;
  switch (obj.type) {
    case 1:
      type = 'Po';
      break;
    case 2:
      type = 'Re';
      break;
    case 4:
      type = 'Rc';
      break;
    default:
      type = 'X';
  }
  var activityType = document.createElement('p');
  activityType.className = 'activity-type';
  var activityTypeText = document.createElement('p');
  activityTypeText.className = 'activity-type-text';
  activityTypeText.innerHTML = type;
  var activityTypeDate = document.createElement('p');
  activityTypeDate.className = 'activity-type-date';
  activityTypeDate.innerHTML = moment(obj.time).fromNow();
  activityType.appendChild(activityTypeText);
  activityType.appendChild(activityTypeDate);
  var activity = document.createElement('p');
  activity.className = 'activity';
  activity.appendChild(activityType);
  activity.appendChild(activityUser);
  activity.appendChild(activityInfo);
  return activity;
}

就这种玩意儿。。。咋优化呢?
前端对ES6的支持不理想,所以字符串模板不能用,又不好添加框架,硬写的话,应该怎么做?
这样写对比字符串拼接然后直接innerHTML有什么劣势?

三叔三叔2705 天前898

全部回复(3)我来回复

  • 代言

    代言2017-06-12 09:30:43

    首先,JS 人肉维护 DOM 的【过程式编程】在可维护性上是劣于模板风格的【声明式编程】的。考虑一行简单的 <p>xxx</p> 和一大坨 document.createElement('p')...,它们在可维护性上有天壤之别。

    那么,怎样在没有 ES6 或各种框架语法糖的情况下,采用类似字符串模板的方式,将数据绑定到 HTML 呢?这里有一种 jQuery 作者曾经推荐的方案:

    首先可以在 HTML 里搞个猥琐的 <script> 标签装模板,注意这个模板本身对 JS 并没有任何依赖,也可以把模板放在 <body> 外面。

    <script id="my-template" type="text/x-custom-template">
        <p class="xxx">
            <p class="yyy">%name%</p>
            <p class="zzz">%value%</p>
        </p>
    </script>

    渲染数据时,直接取出模板中的 HTML 文本,用 JS 做正则替换即可:

    var template = document.getElementById("my-template").innerHTML;
    var html = template
                .replace(/%name%/, data['name'])
                .replace(/%value%/, data['value']);
    // insert HTML...

    参考我的这篇博客:
    http://ewind.us/2016/js-rende...

    当然,全量重置 innerHTML 是有性能风险的。但如果数据全量更新,那么即便是原生 JS 编写的代码,最后的 DOM 操作次数和直接重置 innerHTML 实际上是一样的。这时有几种思路:

    1. React 就是为了这类问题而生的。把 React 当做你的 innerHTML,随便全量重置,React 帮你 diff 然后按需更新 DOM,岂不美哉?

    2. Vue 通过依赖收集,直接能够找到变动的 DOM 所在位置并按需更新,连 diff 都不用,更是不知道高到哪里去了。

    3. 自己维护符合业务需求的 diff 算法(如只插入末尾)和 DOM 操作。也许是一个新轮子诞生的前奏呢(

    回复
    0
  • 滿天的星座

    滿天的星座2017-06-12 09:30:43

    结构太复杂,不优雅,纯粹是 肉抗,而且debug简直就是噩梦,以后代码维护量太大!
    建议使用 前端 JS模板引擎,eg:artTemplate,就引入一个 JS 文件而已。

    回复
    0
  • 漂亮男人

    漂亮男人2017-06-12 09:30:43

    最简单的优势:比innerHTML快。
    当你一次性添加几百个这种结构的时候,你就能体会到明显的速度差异

    回复
    0
  • 取消回复