zoukankan      html  css  js  c++  java
  • TWaver HTML5 继承结构和成员说明

    JavaScript是一门动态语言,但是面向对象的特征没有Java那么明显,导致我们开发起来非常不习惯。拿继承来说,Java中有专门的extends和implements关键字实现,但是在JavaScript却引入了一个"别扭的"prototype,而且实现方式有很多种,虽然灵活,却很容易让初学者一头雾水不知所措。TWaver HTML5的doc是一个js文件,对编辑器很友好,但是我们看起来却不是很方便,远不如JavaDoc来得一目了然,于是我们做了另一个html,算是对原js格式doc的补充。先看一下最后完成的效果:

    运行截图:


    这并不是一个静态页面,而是用JavaScript动态解析TWaver,所以即使TWaver更新也没关系,只要在这个html中引入新的twaver.js就可以了。

    界面说明:整个页面的布局借助twaver.controls.SplitPane实现,左侧是TWaver的树组件,中间是List组件,右侧是一个pre标签,借助beautify和prettify展现js代码。

    接下来介绍一下页面上三个部分的实现方式:

    • Tree的实现,下面是初始化Tree的全部代码:
    //twaver.Util.getAllClassNames()返回TWaver所有的内部类型
    var allClassNames = twaver.Util.getAllClassNames();
    //遍历类名
    allClassNames.forEach(function (data) {
         addClass(data);
    });
    var elementBox = new twaver.ElementBox();
    var map = {};
    //初始化Tree box
    function addClass(name) {
        var node = new twaver.Node(name);
        node.setName(name);
    //分割字符串,找我们需要的类或对象
        var clazzArr = name.split(".");
        var clazz = window;
        for (var i = 0; i < clazzArr.length; i++) {
              clazz = clazz[clazzArr[i]];
        } 
    //根据不同的类型设置Icon     
        if (typeof clazz === "object") {
              node.setIcon("object");     
        } else if (typeof clazz === "function") {
              node.setIcon("class");     
        }     
        //同时将node存入map,方便查询使用
        map[name] = node;
        node.clazz = clazz;
        elementBox.add(node); } 
        //... 
        var tree = new twaver.controls.Tree(elementBox); 

    getAllClassNames返回的是类或对象的名字,但是我们要获得实际的类和对象以便可以解析它们的属性和方法。思考一下:在浏览器环境下window是根对象,所有全局对象都是window对象的属性而已,TWaver也不例外,所以我们分割字符串,通过window对象一层一层找属性,最终找到我们要的类或对象。然后我们生成Node,填充box数据容器;同时做了一个< 名字---Node>的映射,后面会用到。 初始化Tree以后设置节点的父子关系:

     elementBox.toDatas().forEach(function (data) { 
    //TWaver所有内置类型都有superClass属性,指向实际的父类或父对象,通过它可以得到父类然后从map中取出树上相应的节点     
         var superClass = data.clazz.superClass;     
         if (superClass && superClass.getClassName) { 
             data.setParent(map[superClass.getClassName()]);  
         } 
    }); 

    大家注意到,Tree的上方还有一个用来过滤数据的文本框,我们看一下它的事件处理:

     
    //Tree的过滤文本框 
    var treeFilter = document.createElement("input");
    treeFilter.type = "text"; 
    treeFilter.addEventListener("input", function () {
         var value = treeFilter.value.trim().toLowerCase();     
         if (value.length > 0) {
                 tree.setVisibleFunction(function (data) {
                     if(data.getName().toLowerCase().indexOf(value)>=0){return true};
                     //如果当前节点的名字与过滤字符串不匹配,就去查询是否有子节点匹配
                     //如果子节点匹配,父节点同样可见
                     return isChildVisible(data, value);
                 });
         } else {
                tree.setVisibleFunction(null);
         }
    });
    //...
    //递归是否有子节点可见
    function isChildVisible(parent, value) {
        var children = parent.getChildren();
        for (var i = 0; i < children.size(); i++) {           
              var child = children.get(i);           
               if (child.getName().toLowerCase().indexOf(value) >= 0) {
                   return true;
              } else if (isChildVisible(child, value)) {
                    return true;
              }
         }
         return false;
    }

    对于Tree过滤器,不能简单的判断当前节点,因为可能当前节点的名字不符合过滤字符串,但是子节点符合,这种时候父节点也要显示,所以需要做递归处理:如果当前节点的子节点符合过滤字符串,当前节点同样可见。

    • List的实现

    List比Tree要简单的多,监听Tree的选中改变事件,得到选中的Node然后解析属性和方法,填充进List的数据容器

    tree.getSelectionModel().addSelectionChangeListener(function (e) {
         var selectedData = tree.getSelectionModel().getLastData();
         if (selectedData) {
               var html = '';
               list.getDataBox().clear();
               //TWaver内置的属性和方法都在prototype上,所以如果data的类型是function,我们就遍历它的prototype
               var obj = typeof selectedData.clazz === "function" ? selectedData.clazz.prototype : selectedData.clazz;
               for (var name in obj) {
                    if (obj.hasOwnProperty(name)) {
                          var listNode = new twaver.Node();
                          if (typeof obj[name] === "function") {
                                listNode.setIcon("method");
                          } else {
                                listNode.setIcon("property");
                          }
                          listNode.setName(name + " - " + typeof obj[name]);
                          //注意getContent方法,对于function直接返回,对于Object再进行一次遍历
                          listNode.content = "" + getContent(obj[name]);
                          html += name + ":" + listNode.content;
                          list.getDataBox().add(listNode);
                     }
                }
                pre.innerHTML = '';
                html = js_beautify(html);
                pre.appendChild(document.createTextNode(html));
                prettyPrint();
           }
    });

    除了填充list,我们还直接把对象属性的js代码组合起来放到右侧pre中,为了规范js代码,我们用到了js_beautify和prettify两个类库,感兴趣的同学可以谷歌一下。

    • pre的实现

    在List上点击某个属性或方法的时候,更新pre的内容为属性值或方法代码

    //list选中的节点发生变化时更新pre
    list.getSelectionModel().addSelectionChangeListener(function (e) {
         var data = list.getSelectionModel().getLastData();
         if (data) {
             pre.innerHTML = '';
             var html = js_beautify(data.content + "");
             pre.appendChild(document.createTextNode(html));
             prettyPrint();
          }
    });

    这三部分介绍完,实际上这个页面也就写完了,通过这些代码,大家应该可以感受到JavaScript的灵活之处,页面布局部分的代码就不介绍了,大家可从下载附件自行研究,最后附上附件见原文最下方

  • 相关阅读:
    使用 requests 维持会话
    使用 requests 发送 POST 请求
    使用 requests 发送 GET 请求
    requests 安装
    使用 urllib 分析 Robots 协议
    使用 urllib 解析 URL 链接
    使用 urllib 处理 HTTP 异常
    使用 urllib 处理 Cookies 信息
    使用 urllib 设置代理服务
    按单生产程序发布
  • 原文地址:https://www.cnblogs.com/twaver/p/2777019.html
Copyright © 2011-2022 走看看