JavaScript buildLayerTreeData 函数语法详解
JavaScript buildLayerTreeData 函数语法详解
前言
在日常的Vue项目开发中,我们经常需要处理复杂的数据结构转换。本文将以一个实际的 buildLayerTreeData 函数为例,详细解析其中涉及的各种JavaScript/ES6+语法特性,帮助开发者更好地理解和应用这些概念。
完整函数代码
async function buildLayerTreeData() {
const LegendData = [];
const layerData = [];
topicLegends.value.forEach((item) => {
item.children = item.children.filter((ele) => ele.isManager && ele.layers.length);
if (item.children.length > 0) {
LegendData.push(item);
}
});
Object.values(layerMap[sceneName.value]).forEach((layer) => {
LegendData.forEach((legend) => {
if (legend.children.some((item) => item.layers.includes(layer.id))) {
layerData.push(layer);
}
});
});
const newLayerData = [];
for (const layer of layerData) {
let rawData = [];
if (layer.layerConfig.layerType === 'landmarkLayer') {
rawData = await gisDataManager.getLandmarkLayerData(layer);
if (rawData.length > 0) {
let landmarkLayerRawData = rawData.map((item) => {
return {
...item,
idLayer: layer.id,
layerType: layer.layerConfig.layerType
};
});
console.log(landmarkLayerRawData);
newLayerData.push({
layerName: layer.layerConfig.scatterType,
icon: '',
children: landmarkLayerRawData
});
}
} else if (layer.layerConfig.layerType === 'trailLayer') {
rawData = await gisDataManager.getTrailLayerData(layer);
if (rawData.length > 0) {
const trailMap = new Map();
rawData.forEach((trailDataItem) => {
const { name } = trailDataItem;
if (!trailMap.has(name)) {
trailMap.set(name, {
...trailDataItem,
idLayer: layer.id,
layerType: layer.layerConfig.layerType,
id: name
});
}
});
const trailLayerRawData = [...trailMap.values()];
newLayerData.push({
layerName: layer.layerConfig.scatterType,
icon: '',
children: trailLayerRawData
});
}
}
}
const newLayerTreeData = LegendData.map((group) => {
return {
legendGroupName: group.txt,
legendGroup: group.children.map((child) => {
const matchedLayer = newLayerData.find((layer) => layer.layerName === child.txt);
return {
layerName: child.txt,
icon: child.icon,
children: matchedLayer ? matchedLayer.children : []
};
})
};
});
layerTreeData.value = newLayerTreeData;
}
语法详解
1. Array.prototype.forEach()
topicLegends.value.forEach((item) => { ... })
作用:遍历数组中的每个元素并执行回调函数。
特点:
- 不返回新数组,仅用于执行副作用操作
- 常用于需要对每个数组元素执行相同操作的场景
- 回调函数接收三个参数:
(element, index, array)
2. Array.prototype.map()
let landmarkLayerRawData = rawData.map((item) => {
return {
...item,
idLayer: layer.id,
layerType: layer.layerConfig.layerType
};
});
作用:创建一个新数组,新数组的元素是原数组元素经过回调函数处理后的值。
特点:
- 返回与原数组长度相同的新数组
- 不会改变原数组
- 常用于数据转换和格式化
3. Array.prototype.filter()
item.children = item.children.filter((ele) => ele.isManager && ele.layers.length)
作用:创建一个新数组,包含通过回调函数测试的所有元素。
特点:
- 返回符合条件的元素组成的新数组
- 回调函数返回 truthy 值时保留该元素
- 常用于数据筛选
4. Array.prototype.push()
LegendData.push(item);
作用:向数组末尾添加一个或多个元素。
返回值:数组的新长度。
5. Array.prototype.some()
if (legend.children.some((item) => item.layers.includes(layer.id))) {
layerData.push(layer);
}
作用:测试数组中是否至少有一个元素通过回调函数的测试。
返回值:布尔值,true 表示至少有一个元素满足条件。
6. Array.prototype.find()
const matchedLayer = newLayerData.find((layer) => layer.layerName === child.txt);
作用:返回数组中满足回调函数测试的第一个元素。
返回值:找到的元素对象或 undefined。
7. Array.prototype.includes()
item.layers.includes(layer.id)
作用:判断数组是否包含指定的值。
返回值:布尔值。
8. 扩展运算符 ...(数组应用)
const trailLayerRawData = [...trailMap.values()];
作用:将可迭代对象(如 Map.values()、Set、字符串等)转换为数组。
优点:简洁明了,代码可读性强。
对象操作
9. Object.values()
Object.values(layerMap[sceneName.value])
作用:返回一个包含对象所有可枚举属性值的数组。
返回值:对象所有属性值组成的数组。
10. 对象扩展运算符 ...
return {
...item,
idLayer: layer.id,
layerType: layer.layerConfig.layerType
};
作用:将对象的所有可枚举属性复制到新对象中。
特点:
- 实现对象的浅拷贝
- 可以同时添加或覆盖属性
- 比使用
Object.assign()更简洁
11. 对象字面量属性简写
{
layerName: layer.layerConfig.scatterType,
icon: '',
children: landmarkLayerRawData
}
作用:创建对象的简洁语法。
简写规则:当属性名和变量名相同时,可以只写属性名。
Map 数据结构
12. Map 的创建和操作
const trailMap = new Map();
trailMap.set(name, { ...trailDataItem, idLayer: layer.id });
trailMap.has(name);
const trailLayerRawData = [...trailMap.values()];
Map 常用方法:
new Map():创建新的 Map 实例Map.set(key, value):设置键值对Map.get(key):获取键对应的值Map.has(key):检查是否存在指定键Map.delete(key):删除指定键Map.values():返回所有值的迭代器Map.keys():返回所有键的迭代器Map.entries():返回所有键值对的迭代器
优势:相比普通对象,Map 的键可以是任意类型,且有更好的性能表现。
异步处理
13. async/await
async function buildLayerTreeData() {
rawData = await gisDataManager.getLandmarkLayerData(layer);
}
async 函数:
- 声明异步函数,返回 Promise 对象
- 函数内部可以使用 await 关键字
await 关键字:
- 暂停函数执行,等待 Promise 解决
- 只能在 async 函数内部使用
- 简化了 Promise 的链式调用
Vue 3 响应式
14. ref() 响应式引用
const LegendData = [];
layerTreeData.value = newLayerTreeData;
特点:
- 使用
ref()创建响应式引用 - 通过
.value访问或修改值 - 在模板中使用时会自动解包
逻辑运算符
15. 短路求值
item.children.filter((ele) => ele.isManager && ele.layers.length)
&& (逻辑与):
- 两个条件都为 true 时返回 true
- 常用于组合多个判断条件
- 具有短路特性:第一个条件为 false 时不会判断第二个
解构赋值
16. 对象解构
const { name } = trailDataItem;
作用:从对象中提取属性到变量。
优点:
- 代码更简洁
- 避免重复编写对象名
- 可以同时提取多个属性
扩展解构:
const { name, age, address } = trailDataItem;
const { name: userName } = trailDataItem; // 重命名
const { name = '默认值' } = trailDataItem; // 设置默认值
总结
这个 buildLayerTreeData 函数充分展示了现代 JavaScript 的强大功能:
- 数组方法链式调用:通过
forEach、filter、map等方法实现数据转换 - ES6+ 新特性:扩展运算符、解构赋值、Map 数据结构等提升开发效率
- 异步处理:async/await 简化异步流程控制
- 响应式编程:与 Vue 3 框架完美结合
掌握这些语法特性不仅能让代码更加简洁优雅,还能提高开发效率和代码质量。在实际项目中灵活运用这些特性,是成为优秀 JavaScript 开发者的必经之路。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)