【JS 设计模式 】用组合模式来实现树形导航--JS代码结构思路分析(二)

来源:互联网 发布:开启云服务器端口命令 编辑:程序博客网 时间:2024/06/06 07:12

 

【JS 设计模式 】用组合模式来实现树形导航--代码结构思路分析(一)



根据上一节中的HTML代码结构我们通过JS来渲染HTML代码,我们先提供一下JS的代码片段,这代码代码不是一个完整的代码是经过简化的。通过JS代码来分析如何组装HTML的


Composite类型的代码:

function TreeComposite(id, name, total, level, last) {  var root = document.createDocumentFragment();  var panel = document.createElement("div");  panel.setAttribute("class", (last ? "tree-folder last" : "tree-folder"));  var b = document.createElement("b");  var i = document.createElement("i");  var link = document.createElement("a");  link.setAttribute("class", "folder");  link.href = "#";  link.innerHTML = name + "[" + total + "]";  link.id = id;  var child = document.createElement("div");  child.setAttribute("class", "tree-child");  if (level) {    panel.appendChild(i);  }  panel.appendChild(b);  panel.appendChild(link);  root.appendChild(panel);  root.appendChild(child);  this.child = child;  this.element = root;}TreeComposite.prototype = {  addNode: function (treeNode) {    this.child.appendChild(treeNode.getElement());  },  getElement: function () {    return this.element;  }}

我们先来分析一下面上面的代码片段:

TreeComposite是有一个带有参数的构造函数,它需要传入四个参数:
id:当前节点的主键(交互时用到);
name:当前节点的名称;
total:当前节点下的记录条数,不是表达他的子节点哦,这里要注意一下;
level:代表树导航的深度的层次级别,越向内级别越高;
last:当前节点是否是父节点下的子节点的最后一个节点;


我们知道了构造函数中参数代表的含义,接下下我们看一下构造函数中的代码片段
首先构造函数的第一句代码是:

var root = document.createDocumentFragment();
为什么要创建一个这样的节点,而不是创建一个div元素或其它标称的元素呢?
第一点:我们希望把它下的子节点加入document文档流中,不把当前创建的节点加入进去;
第二点:在构造函数中我们是要同时添加二个子节点,不希望创建一个无用的节点,document.createDocumentFrament代表创建一个空的节点,且占用当前文档节点流,当把它给别一个节点时,它会把它下面的子节点拿出来,而不是它;

下面这二句代码表示创建一个节点DOM,
var panel = document.createElement("div");panel.setAttribute("class", (last ? "tree-folder last" : "tree-folder"));

这二句对应的是div元素:

下面二句代码:b表示Composite的图片,i表示是一个节点的关系图片;

 var b = document.createElement("b");    var i = document.createElement("i"); 

下面代码表示创建一个包含节点名称的链接DOM元素;
var link = document.createElement("a");    link.setAttribute("class", "folder");    link.href = "#";    link.innerHTML = name + "[" + total + "]";    link.id = id;  

上面有了当前节点元素了,我们还需要创建一个它的子节点的父节点元素,意思就是它的子节点都要包含在child节点中,如下代码:
 var child = document.createElement("div");    child.setAttribute("class", "tree-child");  

下面代码表示如果是第一层节点的话,我们不希望看到它前同有一个节点层次关系图片:
 if (level) {      panel.appendChild(i);    } 

上面我们创建了一个节点的最外层DOM(panel),这时我们要把这些创建的元素添加到panel中去,
  panel.appendChild(b);    panel.appendChild(link);  

下面代码是把创建的当前节点和它的子节点的父节点,包含在root中,root是一个空节点。到这里才能说明,我们为什么要用document.createDocumentFrament()它了。
  root.appendChild(panel);    root.appendChild(child);  

下面代码,第一句是把子节点的父节点给当前对象child属性,第二句是把root节点给当前对象element属性 ,它代表当前节点的DOM;
this.child = child;  this.element = root;  

在TreeComposite对象的原型中还有二个方法 :

addNode: function (treeNode) {      this.child.appendChild(treeNode.getElement());      },    getElement: function () {      return this.element;    }  
原因组合模式是有“部分-整体”的层次结构的,addNode方法是把它的子节点(Composite或 Leaf)添加到这个child中去;getElement方法是获取当前对象的节点;



Leaf类型的代码:

function TreeLeaf(id, name, total, level, last) {  var panel = document.createElement("div");  panel.setAttribute("class", (last ? "tree-only last" : "tree-only"));  var b = document.createElement("b");  var i = document.createElement("i");  var link = document.createElement("a");  link.setAttribute("class", (total ? "folder" : "folder empty"));  link.href = "#";  link.innerHTML = name + "[" + total + "]";  link.id = id;  panel.appendChild(i);  panel.appendChild(link);  this.element = panel;}TreeLeaf.prototype = {  addNode: function (treeNode) {  },  getElement: function () {    return this.element;  }}


我们先来分析一下面上面的代码片段:

TreeLeaf是有一个带有参数的构造函数,它需要传入四个参数:
id:当前节点的主键(交互时用到);
name:当前节点的名称;
total:当前节点下的记录条数,不是表达他的子节点哦,这里要注意一下;
level:代表树导航的深度的层次级别,越向内级别越高;
last:当前节点是否是父节点下的子节点的最后一个节点;

TreeLeaf构造函数中的代码是和TreeComposite构造函数中的代码是相似的,大家可以根据TreeComposite构造函数中的代码讲解来对比着理解TreeLeaf构造函数中的代码;


根据上面的二个对象,我们来回忆一下上节讲到“将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。”这句话。


前半句我们可能好理解,是一种包含关系,谁包含着谁;

我们通过后半句来对应着代码来看一下

TreeComposite(组合对象)和TreeLeaf(单个对象)构造函数中参数的个数和顺序都是一样的,它们分别原型中的方法都是addNode和getElement。他用他们相同的方法;

我们希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象(方法),这里的方法是组合对象和单个对象都有的方法;


下面我们写一段代码对上面的二个对象的使用:

// root节点var treeRoot = new TreeComposite(0, "全部", 8, 0, true);// 添加第一个节点treeRoot.addNode(new TreeLeaf(0, "未分组", 1, 0, true));// 这是第二个节点var treeRoot1 = new TreeComposite(0, "客户", 5, 0, true);// 这是第二个节点下的二个子节点 treeRoot1.addNode(new TreeLeaf(0, "西方客户", 2, 0, true));treeRoot1.addNode(new TreeLeaf(0, "东方客户", 0, 0, true));// 将第二个节点添加root节点中去treeRoot.addNode(treeRoot1);// 这是第三个节点下的二个子节点 treeRoot.addNode(new TreeLeaf(0, "修改分组名称", 2, 0, true));// 这是第四个节点下的二个子节点 var treeRoot2 = new TreeComposite(0, "计算机", 0, 0, true);treeRoot2.addNode(new TreeLeaf(0, "硬件工程师", 0, 0, true));treeRoot2.addNode(new TreeLeaf(0, "软件工程师", 0, 0, true));// 将第三个节点添加root节点中去treeRoot.addNode(treeRoot2);// 这是第五个节点下的二个子节点 treeRoot.addNode(new TreeLeaf(0, "最新添加", 0, 0, true));// 最后打印出所有节点console.log(treeRoot.getElement());

Chrome下打印的效果 :


这一节我们是通过手动地添加元素;下一节我们讲分析根据后端人员给出一个JSON格式数据,我们如何来组装起来,下一节我们可会用到递归的概念。






1 0
原创粉丝点击