前言

这是一篇个人练习 Web 前端各种常见的控件、组件的实战系列文章。本篇文章将介绍个人通过 JQuery + 无序列表 + CSS 动画完成一个简易的树形控件。

最终实现的效果是:

这样结构比较复杂的嵌套再嵌套的 HTML 结构必须先写一个静态的观察,不可能一步到位,事情是逐渐发展的。遵循自顶向下、逐步求精、模块化三个原则。

静态实现

HTML

点击查看 HTML 代码
<ul class="category">
<li class="category-item" data-displayed="false">
<div class="category-tip">分类</div>
<ul class="sub-category">
<li class="sub-category-item">item 01</li>
<li class="sub-category-item">item 02</li>
<li class="sub-category-item">item 03</li>
</ul>
</li>
<li class="category-item" data-displayed="false">
<div class="category-tip">分类</div>
<ul class="sub-category">
<li class="sub-category-item">item 01</li>
<li class="sub-category-item">item 02</li>
</ul>
</li>
<li class="category-item" data-displayed="false">
<div class="category-tip">分类</div>
<ul class="sub-category">
<li class="sub-category-item">item 01</li>
</ul>
</li>
</ul>

基本的结构设计就是,在外层是无序列表 ul,每一项内容 li 下面嵌套 div 和 ul 标签。每一层数据展示是类名为category-tip的标签,如果标签下面还有可以展开的内容就有sub-cagetory的 ul。

CSS

点击查看 CSS 代码
.category-item {
cursor: pointer;
--li-height: 0;
} .category-item-active {
animation: category-display 0.18s cubic-bezier(0.42, 0, 0.18, 0.98) 0s;
} .sub-category {
display: none;
} .sub-category-active {
display: block;
animation: category-show 0.6s ease-in-out 0s;
} @keyframes category-show {
from {
opacity: 0;
} to {
opacity: 1;
}
} @keyframes category-display {
from {
height: 0;
} to {
height: var(--li-height);
}
}

观察最开始的效果展示可知,category-item被点击时需要展开到其子节点sub-category的高度。子节点需要有一种渐变的效果,动画设置的时间要比category-item节点展开的时间长一点。

JQuery

点击查看 JQuery 代码
$(".category-item").on("click", function () {
let displayed = $(this)[0].dataset.displayed;
if ( displayed === "false" ) {
$(this).css({
"--li-height": `${ $(this).children(".sub-category").height() }px`
});
$(this).addClass("category-item-active");
$(this).children(".sub-category").addClass("sub-category-active");
$(this)[0].dataset.displayed = "true";
} else {
$(this).removeClass("category-item-active");
$(this).children(".sub-category").removeClass("sub-category-active");
$(this)[0].dataset.displayed = "false";
}
});

要实现列表展开和收缩,必须要知道当前节点是否已经展开?因此,就必须给节点标记一个布尔值以便于判断是否展开的状态,正好 HTML 标签支持data-xxx的属性,我们可以把这个布尔值直接放在每一个需要展开的标签中:

<li class="category-item" data-displayed="false">......</li>

当点击节点时,JQuery 需要判断data-displayed是否已经展开,如果展开就移除category-item-active以及sub-category-active的动画;如果没有展开就添加这两个动画,实现展开效果。

改进

category-item-active有一个重大问题,就是点击时节点有类似于重影的重合效果。经过多次调试发现,动画开始时,高度从 0px 开始,所以发生了重影效果。正确是高度从category-tip的高度开始,到category-tipsub-category结束。

$(this).css({
"--tip-height": `${ $(this).children(".category-tip").height() }px`,
"--li-height": `${ $(this).children(".sub-category").height() }px`,
});
@keyframes category-display {
from {
height: 0;
} to {
height: calc(var(--li-height) + var(--tip-height));
}
}

动态实现

上面都还是静态实现,树形控件肯定是多层的,接下来我们将写一个渲染树形控件的函数,并且用到递归函数完成 HTML 的渲染。

通过上面静态案例可知,抽离其数据为 JS 数组:

点击查看数据
let treeOcxData = [
{
tip: "分类",
child: [
{ tip: "设计作品" },
{ tip: "技巧杂烩", child: [ { tip: "Web 前端" } ] }
]
},
{
tip: "导航",
child: [ { tip: "固钉" }, { tip: "回到顶部" }, { tip: "面包屑" } ]
},
{
tip: "数据展示"
}
];

抽离出来之后数据还是挺复杂的,不要慌,万事开头难。首先写一个递归函数能不能实现遍历所有的数据。

递归遍历数据

function rendTreeOcx(data) {
for ( let i = 0; i < data.length; i++ ) {
console.log(data[i].tip);
if ( data[i].child ) {
rendTreeOcx(data[i].child);
}
}
}

每一个数据都成功的遍历出来了,接下来就是渲染 HTML。

渲染树形控件函数

前面递归数组的递归函数能够全部依次打印出数组中每一条数据。在此基础之上,我们要添加 HTML 模板进去,完成树形控件的渲染工作。

点击查看 JS 代码
function rendTreeOcx(data, enableFold) {
let template = `<ul class="tree-ocx-ul">`;
if ( enableFold ) template = `<ul class="tree-ocx-ul tree-ocx-ul-enable-fold">`;
for ( let i = 0; i < data.length; i++ ) {
if ( data[i].child ) {
template += `
<li class="tree-ocx-li tree-ocx-li-enable-fold" data-is-folded="false">
<div class="tree-ocx-tip">
${ data[i].tip }
</div>
${ rendTreeOcx(data[i].child, true) }
`;
} else {
template += `
<li class="tree-ocx-li">
<div class="tree-ocx-tip tree-ocx-tip-normal">${ data[i].tip }</div>
`;
}
template += `</li>`;
}
template += `</ul>`;
return template;
}

如果还有子节点就在if ( data[i].child )体内执行递归函数,否则就完成这一层的 HTML。

Gitee 仓库

https://gitee.com/shiramashiro/web-learning/tree/main/src/03.案例

Web 前端实战:JQ 实现树形控件的更多相关文章

  1. Web应用程序开发,基于Ajax技术的JavaScript树形控件

    感谢http://www.cnblogs.com/dgrew/p/3181769.html#undefined 在Web应用程序开发领域,基于Ajax技术的JavaScript树形控件已经被广泛使用, ...

  2. BootstrapBlazor实战 Tree树形控件使用(2)

    继续上篇实战BootstrapBlazor树型控件Tree内容, 本篇主要讲解整合Freesql orm快速制作数据库后台维护页面 demo演示的是Sqlite驱动,FreeSql支持多种数据库,My ...

  3. BootstrapBlazor实战-Tree树形控件使用(1)

    实战BootstrapBlazor树型控件Tree的使用, 以及整合Freesql orm快速制作数据库后台维护页面 demo演示的是Sqlite驱动,FreeSql支持多种数据库,MySql/Sql ...

  4. 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>

    上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...

  5. 基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用

    在前面介绍了两篇关于我的基于MVC4+EasyUI技术的Web开发框架的随笔,本篇继续介绍其中界面部分的一些使用知识,包括控件的赋值.取值.清空,以及相关的使用. 我们知道,一般Web界面包括的界面控 ...

  6. TreeView树形控件递归绑定数据库里的数据

    TreeView树形控件递归绑定数据库里的数据. 第一种:性能不好 第一步:数据库中查出来的表,字段名分别为UNAME(显示名称),DID(关联数据),UTYPE(类型) 第二步:前台代码 <% ...

  7. 转--基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用

    原文  http://www.cnblogs.com/wuhuacong/p/3317223.html 基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用 在前面介绍了两篇关于我的基 ...

  8. SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题

    转:http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发--关于TreeView树形控 ...

  9. vue+element-ui之tree树形控件有关子节点和父节点之间的各种选中关系详解

    做后端管理系统,永远是最蛋疼.最复杂也最欠揍的事情,也永远是前端开发人员最苦逼.最无奈也最尿性的时刻.蛋疼的是需求变幻无穷,如同二师兄的三十六般变化:复杂的是开发难度寸步难行,如同蜀道难,难于上青天: ...

随机推荐

  1. Python Beautiful Soup库

    Beautiful Soup库 Beautiful Soup库:https://www.crummy.com/software/BeautifulSoup/ 安装Beautiful Soup: 使用B ...

  2. vue运行npm run dev时候,自动打开页面

    在config/index.js找到dev:{}里面的autoOpenBrowser: 设置为true,重新npm run dev一次就自动弹出浏览器页面啦!

  3. 一款开源的跨平台实时web应用框架——DotNetify

    今天给大家介绍一个开源的轻量级跨平台实时HTML+C#.NET Web应用程序开发框架--DotNetify,允许你在C#.NET后端上创建具有React.React Native.Vue或Blazo ...

  4. MyBatis - MyBatis的层次结构

    API接口层 规定了一系列接口,能够向外提供接口,对内进行操作. 数据处理层 负责SQL相关处理工作,如:SQL查找.SQL执行.SQL映射等工作. 基础支撑层 提供基础功能支撑,包括连接管理.事务管 ...

  5. Halodoc使用 Apache Hudi 构建 Lakehouse的关键经验

    Halodoc 数据工程已经从传统的数据平台 1.0 发展到使用 LakeHouse 架构的现代数据平台 2.0 的改造.在我们之前的博客中,我们提到了我们如何在 Halodoc 实施 Lakehou ...

  6. c++ 辗转相除(动图)

    #include<iostream> #include<cstdio> #include<iomanip> #include<cstring> usin ...

  7. ESP8266 系统环境搭建

    1. 前言 因为ESP8266/ESP32这个开发环境没少折腾,是真没见过这么难搞又不清晰的环境. 简单开发可以使用Arduino IDE ,这个平台还是挺好的.开发使用Arduino的函数库,很高效 ...

  8. Volcano社区v1.6.0版本正式发布

    摘要:Volcano社区v1.6.0版本正式发布.此次版本增加了弹性作业管理.基于真实负载的动态调度. 基于真实负载的重调度.Volcano Job插件--MPI等多个新特性. 本文分享自华为云社区& ...

  9. 面试突击58:truncate、delete和drop的6大区别

    在 MySQL 中,使用 truncate.delete 和 drop 都可以实现表删除,但它们 3 个的使用场景和执行效果完全不同,接下来我们来盘点一下. truncate.delete.drop区 ...

  10. SAP BDC 用户输入日期转系统日期格式: CONVERT_DATE_TO_EXTERNAL

    BDC中,日期输入格式不正确:可调用FM  CONVERT_DATE_TO_EXTERNAL DATA:l_bdcfield LIKE bdcdata-fval."BDC field val ...