JavaScript面向对象技术实现树形控件(转贴)

js实现树形结构化 我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注小歌谣 日常分享前后端知识 前言 今天来讲一下平常我们做权限系统中的树形结构知识 就是如何把对应关系的结构数据转换为可以一个树形结构 const data = [ { id: 2, pid: 0, path: '/course', name: 'Course', title: '课程管理' }, { id: 3, name: 'CourseOperate', path: 'o. 阅读详情

树形控件具有独特的扩展和折叠分支的能力,能够以较小的空间显示出大量的信息,一目了然地传达出数据之间的层次关系。凡是熟悉图形用户界面的用户,都能够自如地运用树形控件。


图一:用JavaScript实现的树形控件

HTML本身不支持树形控件,但我们可以通过一些JavaScript脚本代码实现。为了提高控件的可重用性,我们要充分运用JavaScript对面向对象编程技术的支持。本文的树形控件适用于IE 4+和Netscape 6.x,应当说这已经涵盖了当前的主流浏览器。

一、JavaScript与面向对象

面向对象的编程有三个最基本的概念:继承,封装,多态性。继承和封装这两个概念比较好理解,相对而言,多态性这个概念就比较难于掌握和运用。一般而言,多态性是指以多种形式表现的能力。在面向对象编程技术中,多态性表示编程语言拥有的一种根据对象的数据类型或类的不同而采取不同处理方式的能力。

在“纯”面向对象的语言中,例如Java,多态性一般与类的继承密不可分。也就是说,必须定义一种类的层次关系,处于顶端的是抽象类,处于下层的是各种具体的实现。抽象类定义了子类必须实现或覆盖的方法,不同的子类根据自己的需要以不同的方式覆盖抽象类的方法。

例如,计算圆面积和矩形面积的公式完全不同,按照面向对象的设计思路,我们要先定义一个抽象类Shape,Sharp类有一个findArea()方法,所有从Shape类派生的子类都必须实现findArea()方法。然后,我们定义一个代表矩形的Rectangle类,一个代表圆的Circle类,这两个类都从Shape类继承。Rectangle类和Circle类分别实现findArea()方法,两者用不同的计算公式计算面积。最终达到这样一个目标:不论对象属于Shape的哪一种子类(Rectangle或Circle),都可以用相同的方式调用findArea()方法,不用去管被调用的findArea()采用什么公式计算面积,从而有效地隐藏实现细节。

JavaScript语言不支持以类为基础的继承,但仍具有支持多态性的能力。JavaScript的继承是一种基于原型(Prototype)的继承。实际上,正如本文例子所显示的,这种继承方式简化了多态性方法的编写,而且从结构上来看,最终得到的程序也与纯面向对象语言很接近。

二、准备工作

整个树形控件由四部分构成:图形,CSS样式定义,HTML框架代码,JavaScript代码。从图一可以看出,树形控件需要三个图形,分别表示折叠的分支(closed.gif)、展开的分支(open.gif)和叶节点(doc.gif)。

下面是树形控件要用到的CSS样式定义:

< style>
body{
font: 10pt 宋体,sans-serif; color: navy; }
.branch{
cursor: pointer;
cursor: hand;
display: block; }
.leaf{
display: none;
margin-left: 16px; }
a{ text-decoration: none; }
a:hover{ text-decoration: underline; }
< /style>

CSS规则很简单:body规则设置了文档的字体和前景(文字)颜色。branch规则的用途是:当鼠标经过拥有子节点的节点时,指针会变成手的形状。之所以要定义两个cursor属性,是因为IE和Netscape使用不同的属性名称。在leaf规则中设置display属性为none,这是为了实现叶节点(不含子节点的最终节点)的折叠效果。在脚本代码中,我们通过把display属性设置成block显示出节点,设置成none隐藏节点。

三、脚本设计

本文实现的树形控件包含一个tree对象,tree对象拥有一个branches子对象集合;每一个branch(分支)对象又拥有一个子对象的集合。子对象可以是branch对象,也可以是leaf(树叶)对象。所有这三种对象分别实现一个多态性的write()方法,不同对象的write()方法根据所属对象的不同而执行不同的操作,也就是说:tree对象的write()方法与branch对象的write()方法不同,branch对象的write()方法又与leaf对象的write()方法不同。另外,tree和branch对象各有一个add()方法,分别用来向各自所属的对象添加子对象。

在HTML文档的部分加入下面这段代码。这段代码的作用是创建两个Image对象,分别对应分支打开、折叠状态的文件夹图形。另外还有几个工具函数,用于打开或折叠任意分支的子元素,同时根据分支的打开或折叠状态相应地变换文件夹图形。

< script language="JavaScript">
var openImg = new ..Asset not found..;
openImg.src = "open.gif";
var closedImg = new ..Asset not found..;
closedImg.src = "closed.gif";

function showBranch(branch){
var objBranch = document.getElementById(branch).style;
if (objBranch.display=="block")
objBranch.display="none";
else
objBranch.display="block";
swapFolder('I' + branch);
}

function swapFolder(img){
objImg = document.getElementById(img);
if (objImg.src.indexOf('closed.gif')>-1)
objImg.src = openImg.src;
else
objImg.src = closedImg.src;
}
< /script>

代码预先装入图形对象,这有利于提高以后的显示速度。showBranch()函数首先获得参数提供的分支的样式,判断并切换当前样式的显示属性(在block和none之间来回切换),从而形成分支的扩展和折叠效果。swapImage()函数的原理和showBranch()函数基本相同,它首先判断当前分支的图形(打开的文件夹还是折叠的文件夹),然后切换图形。

四、tree对象

下面是tree对象的构造函数:

function tree(){
this.branches = new Array();
this.add = addBranch;
this.write = writeTree;
}

tree对象代表着整个树形结构的根。tree()构造函数创建了branches数组,这个数组用来保存所有的子元素。add和write属性是指向两个多态性方法的指针,两个多态性方法的实现如下:

function addBranch(branch){
this.branches[this.branches.length] = branch;
}

function writeTree(){
var treeString = '';
var numBranches = this.branches.length;
for (var i=0;i treeString += this.branches[i].write();
document.write(treeString);
}

addBranch()方法把参数传入的对象加入到branches数组的末尾。writeTree()方法遍历保存在branches数组中的每一个对象,调用每一个对象的write()方法。注意这里利用了多态性的优点:不管branches数组的当前元素是什么类型的对象,我们只需按照统一的方式调用write()方法,实际执行的write()方法由branches数组当前元素的类型决定——可能是branch对象的write()方法,也可能是leaf对象的write()方法。

必须说明的是,虽然JavaScript的Array对象允许保存任何类型的数据,但这里我们只能保存实现了write()方法的对象。象Java这样的纯面向对象语言拥有强健的类型检查机制,能够自动报告类型错误;但JavaScript这方面的限制比较宽松,我们必须手工保证保存到branches数组的对象具有正确的类型。

五、branch对象

branch对象与tree对象相似:

function branch(id, text){
this.id = id;
this.text = text;
this.write = writeBranch;
this.add = addLeaf;
this.leaves = new Array();
}

branch对象的构造函数有id和text两个参数。id是一个唯一性的标识符,text是显示在该分支的文件夹之后的文字。leaves数组是该分支对象的子元素的集合。注意branch对象定义了必不可少的write()方法,因此可以保存到tree对象的branches数组。tree对象和branch对象都定义了write()和add()方法,所以这两个方法都是多态性的。下面是branch对象的add()和write()方法的具体实现:

function addLeaf(leaf){
this.leaves[this.leaves.length] = leaf;
}

function writeBranch(){
var branchString =
'< span class="branch" ' + onClick="showBranch(/'' + this.id + '/')"';
branchString += '>< img src="closed.gif" id="I' + this.id + '">' + this.text;
branchString += '< /span>';
branchString += '< span class="leaf" id="';
branchString += this.id + '">';
var numLeaves = this.leaves.length;
for (var j=0;j< numLeaves;j++) branchString += this.leaves[j].write();
branchString += '< /span>';
return branchString;
}

addLeaf()函数和tree对象的addBranch()函数相似,它把通过参数传入的对象加入到leaves数组的末尾。

writeBranch()方法首先构造出显示分支所需的HTML字符串,然后通过循环遍历leaves数组中的每一个对象,调用数组中每一个对象的write()方法。和branches数组一样,leaves数组也只能保存带有write()方法的对象。

六、leaf对象

leaf对象是三个对象之中最简单的一个:

function leaf(text, link){
this.text = text;
this.link = link;
this.write = writeLeaf;
}

leaf对象的text属性表示要显示的文字,link属性表示链接。如前所述,leaf对象也要定义write()方法,它的实现如下:

function writeLeaf(){
var leafString = '< a href="' + this.link + '">';
leafString += '< img src="doc.gif" border="0">';
leafString += this.text;
leafString += '< /a>< br>';
return leafString;
}

writeLeaf()函数的作用就是构造出显示当前节点的HTML字符串。leaf对象不需要实现add()方法,因为它是分支的终结点,不包含子元素。

七、装配树形控件

最后要做的就是在HTML页面中装配树形控件了。构造过程很简单:创建一个tree对象,然后向tree对象添加分支节点和叶节点。构造好整个树形结构之后,调用tree对象的write()方法把树形控件显示出来。下面是一个多层的树形结构,只要把它加入标记内需要显示树形控件的位置即可。注意下面例子中凡是应该加入链接的地方都以“#”替代:

< script language="JavaScript">
var myTree = new tree();
var branch1 = new branch('branch1','JavaScript参考书');
var leaf1 = new leaf('前言','#');
var leaf2 = new leaf('绪论','#');
branch1.add(leaf1);
branch1.add(leaf2);
myTree.add(branch1);

var branch2 = new branch('branch2','第一章');
branch2.add(new leaf('第一节','#'));
branch2.add(new leaf('第二节','#'));
branch2.add(new leaf('第三节','#'));
branch1.add(branch2);

var branch3 = new branch('branch2','第二章');
branch3.add(new leaf('第一节','#'));
branch3.add(new leaf('第二节','#'));
branch3.add(new leaf('第三节','#'));
branch1.add(branch3);

myTree.add(new leaf('联系我们','#'));
myTree.write();
< /script>

上述代码的运行效果如图一所示。可以看到,装配树形控件的代码完全符合面向对象的风格,简洁高效。

从本质上看,用面向对象技术构造的树形控件包含一组对象,而且这组对象实现了纯面向对象的语言中称为接口的东西,只不过由于JavaScript语言本身的限制,接口没有明确定义而已。例如,本文的树形控件由tree、branch、leaf三个对象构成,而且这三个对象都实现了write接口,也就是说,这三个对象都有一个write()方法,不同对象的write()方法根据对象类型的不同提供不同的功能。又如,tree、branch对象实现了add接口,两个对象分别根据自身的需要定义了add()方法的不同行为。可见,多态性是面向对象技术中一个重要的概念,它为构造健壮的、可伸缩的、可重用的代码带来了方便。

【正点原子I.MX6U-MINI移植篇】Ubuntu-base根文件系统移植构建过程详解(四) 能不能在ARM板上运行Ubuntu呢?答案肯定是可以的,Ubuntu是Linux系统的一种,可以简单的将Ubuntu理解为一个根文件系统,和我们用busybox、buildroot制作的根文件系统一样。因此移植Ubuntu也就是将Ubuntu根文件系统移植到我们的开发板上。 阅读详情

相关推荐

手把手教学:利用AutoDL与vLLM快速部署DeepSeek-R1大模型实战指南

本文详细介绍了如何利用AutoDL平台和vLLM框架快速部署DeepSeek-R1大模型的实战指南。从服务器配置、vLLM安装优化到模型部署的两种方案,再到性能调优和生产环境建议,手把手教你高效完成大模型部署。特别针对国内开发者遇到的网络问题提供了稳定解决方案,并分享了显存优化、磁盘清理等实用技巧。

weixin_42531779的博客 296

JavaScript树形控件大集合

转载自 anylzer 最终编辑 anylzer zTree  利用Jquery的核心代码,实现一套能完成大部分常用工作的Tree功能 兼容 IE、FireFox、Chrome 等浏览器(对于IE 6.0的兼容问题将不做特殊维护)在一个页面内可同时生成多个 Tree 实例支持 JSON 数据支持一次性静态生成 和 Ajax异步加载 两种方式支持多种事件响应及反馈支持 Tree

Dreamer Thinker Doer 8710

yolov5+非机动车违规停放+已标注数据集+机器视觉识别+三轮车tricycle8_images_xmls

文件内包含的是已标注的非机动车数据集中的三轮车tricycle8的图片部分加标注数据部分限于上传文件大小,此资源内只包含三轮车数据的tricycle8的图片部分加标注数据部分,有784张,三轮车数据总共有八个分类,此为第八类。所有的资源总共包括自行车图片8000张极其标注数据,已分类,分类包含了山地自行车,公路自行车,越野自行车,通勤自行车,共享单车等。每种自行车的张数大概在800-1000张之间,极个别重复。电动车图片8000张极其标注数据,已分类,分类包含了绿源电动车,台铃电动车,小刀电动车,雅迪电动车,共享电动车等。每种电动车的张数大概在800-1000张之间,极个别重复。三轮车图片6000张极其标注数据,已分类,分类包含了淮海三轮车,闪电客三轮车,金彭三轮车,宗申三轮车,五星三轮车等。每种三轮车的张数大概在500-600张之间,极个别重复。以上资源均为已标注,用于yolov5+已标注非机动车数据集+非机动车违规停放+机器视觉识别

详解js树形控件—zTree使用总结

【代码】详解js树形控件—zTree使用总结。

for__future_的博客 4670

Javascript】【UI】纯原生代码实现树状控件:TreeView

此控件参考aimaraJS优化而来,由原生js实现,注释详细,代码最大幅度简化 不依赖任何库,只有一个js文件和一个css文件 效果展示 html代码 <html> <head> <title>TreeView</title> <link rel="icon" href="./image/tree.p...

天天向上 Up Up Up (*^▽^*) 5452

使用JSP面向对象web编程技术实现树形控件

使用JSP面向对象web编程技术实现树形控件 2003-06-02 09:07:29 来源: 树形控件是一种人们熟悉的用户界面控件,广泛地用来显示层次型数据。 树形控件具有独特的扩展和折叠分支的能力,能够以较小的空间显示出大量的信息,一目了然地传达出数据之间的层次关系。凡是熟悉图形用户界面的用户,都能够自如地运用树形控件。     图一:用JavaScript实现的树形

feng_sundy 的专栏 2901

Jquery dtree的使用

 Dtree目录树的总结                   一:函数                            1:页面中                              tree.add(id,pid,name,url,title,target,icon,iconOpen,open);                                  参数说明:  ...

silence_cheng的专栏 167

JSON Tree 开源项目安装与使用指南

JSON Tree 开源项目安装与使用指南 一、项目目录结构及介绍 该项目位于 GitHub 上,其目录结构简洁明了,便于开发者快速上手。以下是主要的目录和文件说明: json-tree/ ├── index.html # 主入口文件,用于浏览器直接打开查看示例 ├── src/ │ ├── jsonTree.js # 核心JavaScrip...

gitblog_01179的博客 464

(LXTML笔记)Decision Tree

决策树也是有集成模型的形式,如图所示 如果以每一条路径为条件qtqtq_t,叶子为最后的分类函数gtgtg_t(有时候是常数)的话,那么整棵树可以表示为G(x)=∑Tt=1qt⋅gtG(x)=∑t=1Tqt⋅gtG(x)=\sum_{t=1}^T q_t \cdot g_t,这是条件型集成模型的形式。更一般地,我们常常写成递归的形式,即 G(x)=∑c=1C[b(x)=c]Gc(x),G(...

dede酱の日常思考 294

二叉树基础(三)树状数组(Fenwick Tree

二叉树基础(三)树状数组(Fenwick tree)概念lowbitlowbitlowbit运算结构代码基本操作update()update()update()sum()sum()sum()整体代码 概念 树状数组(Binary Indexed Tree, Fenwick Tree)是一种用于高效处理对一个存储数字的列表进行更新及求前缀和的数据结构。 lowbitlowbitlowbit运算 lowbit(x)lowbit(x)lowbit(x)是x的二进制表达式中最低位的1所对应的值,比如: (6)10=

z2656453168的博客 671

浅谈SQL Server数据内部表现形式

浅谈SQL Server数据内部表现形式 原文:浅谈SQL Server数据内部表现形式 在上篇文章浅谈SQL Server内部运行机制中,与大家分享了SQL Server内部运行机制,通过上次的分享,相信大家已经能解决如下几个问题: 1.SQL Server 体系结构由哪几部分组成? 2.SQL...

weixin_30633405的博客 89

dwz tree组件 取得所选择的值

DWZ的树结构是按,的嵌套格式构成,最顶级的以class=”tree”标识。treeFolder, treeCheck, expand|collapse则为可选的。 treeFolder:在所有树节点前加上Icon图标。 treeCheck:在所有树节点前加上checkbox,此时需要在 加上三个扩展属性tname="", tvalue="", checked="",其中tname与tva

shanzhizi的专栏 9131

Decision Tree

# -*- coding: UTF-8 -*- ''' Created on Oct 12, 2010 Decision Tree Source Code for Machine Learning in Action Ch. 3 @author: Peter Harrington ''' from math import log import operator def createDataS

风口的猪2016 331

dwz中的(tree)树形菜单的默认收缩

做网站后台时,为了方便管理,可能会用到dwz中的树形菜单,如下: 树形菜单的收缩有默认属性值,可以对其进行一定的初始设定: DWZ的树结构是按<ul>,<li>的嵌套格式构成,最顶级的<ul>以class=”tree”标识。treeFolder, treeCheck, expand|collapse则为可选的。treeFolder:在所有树节点前加上Ico...

suhanyujie的专栏 137

FLEX 构建完美的带有CheckBox三状态的Tree控件(checkTree)[附测试下载]

不用说什么了,需要两个文件:  CheckTree.as package ht { import mx.controls.Tree; import mx.core.ClassFactory; import mx.events.ListEvent; /** * 三状态复选框树控件 * */ public class CheckTree extends Tree {

火舞天涯 1万+

Java 【数据结构】 二叉树(Binary_Tree)【神装】

首先,我意识到了数据结构在编程中的关键性,二叉树作为其中的重要一环,对算法设计和问题解决都有着深远的影响。深入理解二叉树的基本概念,如节点、根节点、子节点等,为我理解二叉树结构和算法打下了坚实的基础。掌握了常见的操作和遍历算法,如插入节点、删除节点以及深度优先遍历和广度优先遍历,这些都是对树形结构理解和应用至关重要的。

2302_79806056的博客 2323

少年, Abstract Syntax Tree 了解下!

简单任务pshu 前段时间有一个简单任务。很简单,升级了Cocos Creator游戏框架,有两组JavaScript的API彻底废弃了,如果调用老的 API 直接 Exeception...

pshu0_0的博客 199

抽象语法树 Abstract syntax tree

什么是抽象语法树? 在计算机科学中,抽象语法和抽象语法树其实是源代码的抽象语法结构的树状表现形式 在线编辑器 我们常用的浏览器就是通过将js代码转化为抽象语法树来进行下一步的分析等其他操作。所以将js转化为抽象语法树更利于程序的分析。 如图: 如上图中的变量声明语句,转化为AST之后就是右图的样子。 先来分析一下左图: var 是一个关键字 AST是一个定义者 = 是Equal 等号的叫法有...

weixin_30301449的博客 507

场景图生成论文阅读笔记 之 CogTree: Cognition Tree Loss for Unbiased Scene Graph Generation

2020 arXiv 《CogTree: Cognition Tree Loss for Unbiased Scene Graph Generation》 无偏场景图生成的认知树损失 文章目录《CogTree: Cognition Tree Loss for Unbiased Scene Graph Generation》针对问题/基本思想算法步骤① Bias-based ‘Concept’② 构建Concept-centered子树③ 组合子树Cognition Tree Loss实验结果 针对问题/基

流觞时光 1208
上一篇: 用!important解决IE和Mozilla的布局差别(转贴)
下一篇: 自适应图片大小的弹出窗口
RAINMAN_NET
博客等级 码龄22年 2粉丝 37原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值