高级前端进阶(一)
希望疫情早日结束!!!
一、首先来一道开胃菜,css方面问题
在前端方面,渲染列表数据的时候,可能会更改第一个或者最后一个的样式,又或者其中第几个的样式,怎么做呢?
其实很简单,便是使用last-child选择器相关知识。
问题是,有时候,我们使用last-child会出现失效的问题。
先来个实际场景:
目的:给最后一个class="invalid"的元素添加背景色。
<h1>这样是无效的,也就是last-child失效了</h1>
<div class="question">
<div class="invalid">111111</div>
<div class="invalid">222222</div>
<div class="invalid">333333</div>
<div class="invalid">444444</div>
<div class="invalid">555555</div>
<div class="invalid">666666</div>
<div class="disturb">777777</div>
</div>
<style lang="scss" scoped>
.question {
.invalid:last-child {
background-color: cornflowerblue;
}
}
</style>
为啥会失效?主要问题就是最后有个class="disturb"的元素。
使用last-child选择器必须要有个容器包裹,否则就会失效,把上面class="invalid"元素再用一个div包裹起来便可以了。
改成以下便可以了
<div class="question">
<div>
<div class="invalid">111111</div>
<div class="invalid">222222</div>
<div class="invalid">333333</div>
<div class="invalid">444444</div>
<div class="invalid">555555</div>
<div class="invalid">666666</div>
</div>
<div>
<div class="invalid">111111</div>
<div class="invalid">222222</div>
<div class="invalid">333333</div>
<div class="invalid">444444</div>
<div class="invalid">555555</div>
<div class="invalid test">666666</div> <!-- 这样也是可以的 -->
</div>
<div class="disturb">777777</div>
</div>
二、重点来了
list转树型数据
关于这一点,个人觉得前端一般不需要这么做,毕竟前端主要负责进行数据渲染,以及用户交互。
但将list转为树型数据,里面涉及到的算法,我们还是要了解一下的。
将list转为树型数据,一般用到的是递归跟多次遍历方法。
其他的方法便不多做介绍了。在此介绍掌握最高效的方法,一次遍历即可。
list数据
[
{
id: 1, pid: 0, name: "一级数据1"
},
{
id: 2, pid: 0, name: "一级数据2"
},
{
id: 3, pid: 0, name: "一级数据3"
},
{
id: 4, pid: 1, name: "二级数据2-1"
},
{
id: 5, pid: 1, name: "二级数据2-2"
},
{
id: 6, pid: 1, name: "二级数据2-3"
},
{
id: 7, pid: 3, name: "三级数据3-1"
},
{
id: 8, pid: 3, name: "二级数据3-2"
},
{
id: 9, pid: 8, name: "三级数据3-1"
}
]
树型数据
[{
id: 1,
pid: 0,
name: "一级数据1",
children: [{
id: 4,
pid: 1,
name: "二级数据2-1"
},
{
id: 5,
pid: 1,
name: "二级数据2-2"
},
{
id: 6,
pid: 1,
name: "二级数据2-3"
}
]
},
{
id: 2,
pid: 0,
name: "一级数据2"
},
{
id: 3,
pid: 0,
name: "一级数据3",
children: [{
id: 7,
pid: 3,
name: "三级数据3-1"
},
{
id: 8,
pid: 3,
name: "二级数据3-2",
children: [{
id: 9,
pid: 8,
name: "三级数据3-1"
}]
},
]
}
]
为了实现这个目的,我们需要了解很多的知识点。
1、基本的原理
每条数据都要有相应的id跟pid
id指的是这条数据的主键(就这么理解吧),一定要是唯一的。
pid指的是这条数据的上级数据的主键id,(相当于组织机构中,上级组织机构的主键id)。
当每条数据满足具有id跟pid的时候,那便可以将数据转为树型结构。
2、JavaScript是弱类型语言。举个例子:
var o={};// 申明一个o空对象变量(里面没有任何的属性,不是null)
o.children=[];// 给o变量添加一个数组类型的变量children。这便是与强类型的区别。强类型语言必须要在一个class里面将变量都定义好。
3、引用类型(这个便是重中之重了,也是为啥一次遍历便能够实现想要的结果的原因)
引用类型,变量存储的是地址,而地址对应的是值,我们需要做的是改变值,但这个变量名称是不变的,也就是地址是不变的,值是改变的。
通过定义一个变量itemMap,动态地给itemMap添加id属性值,而itemMap属性的值为list中的一个数组对象,并且循环遍历的时候,不断给itemMap属性值添加相应的children。
详细代码如下:
// list转树型数据
function listToTree(data, mapping) {
let idMap = 'id';
let pidMap = 'pid';
if (mapping) {
idMap = mapping.id;
pidMap = mapping.pid;
}
// 以上部分主要是针对list的id跟parentid字段,万一不是id跟pid的。
let result = [];// 存储最终的结果
let itemMap = {};// 这个对象变量便是最核心的地方
for (let item of data) { // for-of遍历
let id = item[idMap]; // 获取id
let pid = item[pidMap]; // 获取pid
itemMap[id] = item;// 开始给itemMap变量赋值
let parentData = itemMap[pid];// 浅拷贝 父亲节点
if (!parentData) {
result.push(itemMap[id]);
continue; // 结束当前循环,继续下一个循环
}
parentData.children = []; //这样做的话,给有子集的项添加children属性,没子集的话,便没有children属性
parentData.children.push(item);
}
return result;
}
树型数据转list(倒过来)
这个,暂时没想到什么更好的方法,便用递归实现了。
递归,有个很形象的说法,一层一层地拨开你的心!!!
嘻嘻
// 树型数据转list
function treeToList(tree, mapping) {
var list = [];
let childrenName = 'children';
if (mapping) {
childrenName = mapping.children;
}
handleTreeToList(tree, list, childrenName);
return list;
}
// 递归方法
function handleTreeToList(tree, list, childrenName) {
if (!tree || !tree.length) {
return;
}
for (let item of tree) {// 遍历
let temp = JSON.parse(JSON.stringify(item));// 深拷贝
if (item[childrenName]) {
delete temp[childrenName];// 删除子项
}
list.push(temp);
if (item[childrenName]) {
handleTreeToList(item[childrenName], list, childrenName);// 递归调用
}
}
}
三、扩展(递归的使用,巩固递归算法)
给树型数据每项添加额外的数据
// 给树型数据每项添加flag属性
function addDataTree(tree, childrenName) {
if (childrenName == undefined)
childrenName = 'children';
for (let item of tree) {
item.flag = false;// 添加flag属性
if (item[childrenName])
addDataTree(item[childrenName], childrenName);// 递归调用
}
}
四、总结
递归算法,还是很有必要掌握的,在树型结构方面经常会用到。
希望疫情早点结束!!!
原文地址:https://www.cnblogs.com/ywjbokeyuan/p/15025776.html
- javascript 红皮高程(16)
- javascript 红皮高程(15)
- javascript 红皮高程(21)-- 乘性操作符
- javascript 红皮高程(20)-- 逻辑或
- javascript 红皮高程(19)-- 逻辑与
- 技术分享 | 浅谈 RAS
- Sniper-OJ 练习平台多题WriteUp
- 怎么能学透一个知识点
- Jarvis-OJ平台多题WriteUp分享
- 会员提问 之 JS中的私有方法有什么意义?
- 本周末的QQ群视频--还是电商网站的事
- 【译】使用Apache的mod重写来保护你的C2 Empire
- 大白话,设计一个购物车对象
- 【译】Cromos – 下载并注入代码到谷歌 Chrome 浏览器扩展中
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 宜信OCR技术探索之版面分析业务实践|技术沙龙直播速记
- Nginx的rewrite(地址重定向)剖析
- Prometheus监控神器-Kubernetes篇(二)
- C/C++实现你的浪漫表白:浪漫流星雨表白程序
- 烂了大街的 Spring 循环依赖问题,你觉得自己会了吗
- 软件测试丨自动化测试之读取配置文件
- 一文搞懂高频面试题之限流算法,从算法原理到实现,再到对比分析
- TRTC Android端开发接入学习之实现语音通话(六)
- Shell脚本加密经验分享
- python提示每天债券打新
- Python3下基于Scapy库完成网卡抓包解析
- pandas:解决groupby().apply()方法打印两次
- pandas:字段值插入数据表第一行的解决办法
- Recommending items to more than a billion people(面向十亿级用户的推荐系统)
- pandas:对字符串类型做差分比较