前言
这篇文章呢我打算积累一些vue使用技巧,比如,在开发过程中遇到的一些奇奇怪怪令人摸不着头脑的问题,如明明使用了mouseover和mouseout为什么就是没有效果呢,诸如此类的问题,我会总结到这里,持续更新,加油。
目录
一、鼠标事件
今天来分享一个比较有意思的东西,vue在写某些动画的时候遇到的问题,这个问题困扰了很久,现在解决了,但还是不明白到底是收到了什么影响。
如果遇到鼠标移入移出事件没有效果,但是你觉得代码正确,可就是出不来效果,你可能遇到了和我一样的问题,那就是该项目是移动项目。在手机端,并没有mouseover和mouseout事件,这里我们要把这两个事件对应的换成touchstart和touchend。现在我们来了解一下touch事件,js文档。
touchstart事件:当手纸触摸屏幕时触发,即使已经有一个手指放在屏幕上也会触发。
touchend事件:当手指从屏幕上离开的时候触发。
touchmove事件:当手指在屏幕上滑动时连续触发。这个事件发生期间,调用prevent Default()事件 可以阻止某些鼠标事件发生。
touchcancel事件:当系统停止跟踪触摸的时候触发。关于这个时间的确切触发事件,文档中并没有具体说明。
这里采用动态绑定事件来解决触摸事件的绑定,当然也可以在标签里写上@touchstart,都是可以滴~
<template>
<div>
<div ref='ban'>
{{message}}
</div>
</div>
</template>
<script>
export default{
name:'',
data(){
return{
message:'Tendency'
}
},
mounted(){
//初始化绑定触摸事件
this.touchEventAuto();
},
methods:{
touchEventAuto(){
let _this=this;
//动态绑定事件
this.$refs.ban.ontouchstart=function () {
_this.$refs.ban.style.backgroundColor='#eee'
this.message='Zero'
}
this.$refs.ban.ontouchend=function () {
_this.$refs.ban.style.backgroundColor='white'
this.message='Tendency'
}
}
}
}
</script>
网上有些说将@mouseover写成@mouseover.native,我发现在这里是不可取的,使用这个的条件是用了非原生html,即用了某些ui插件如element-ui等。同时,大前提是非移动项目。在这些前提下是可以加native的。
- 2020.6.29 Am
二、文档滑动条
这次的问题出现在给div设置滑动的时候,滑动条隐藏,换个方式显示滑动到哪里了,间接直观且美观的显示文本滑动条。如图:
主要的难点就是如何设置滑动以及美化滚动条,这里想到了如何获取滚动像素,需要用到jQuery,可参考jquery教程(scrollLeft()或scrollTop())
那么首先给div设置可滑动(overflow-x),然后隐藏滚动条。
<template>
<div class='mainPageReport'>
<div>报表1</div>
<div>报表2</div>
<div>报表3</div>
</div>
</template>
<style lang='scss'>
.mainPageReport{
width:100%;
display: flex;
/*设置div可滑动*/
overflow-x: scroll;
div{
/*让div里文本水平居中*/
text-align: center;
/*让div里面的内容垂直居中*/
align-items: center;
/*让自己垂直居中*/
align-self: flex-start;
width:50%;
height:20vw;
margin-left: 3vw;
}
}
/*隐藏滑动条*/
.mainPageReport :: -webkit-scrollbar {
display:none
}
</style>
添加三个按钮,然后给滑动框绑定事件scroll。通过滚动条的值来判断哪个小圆点变亮,优化代码:
<template>
<div class='out-mainPageReport'>
<div class='mainPageReport' res='scrolls' @scroll='changeScroll'>
<div>报表1</div>
<div>报表2</div>
<div>报表3</div>
</div>
<div class="act">
<div :class="{'blueScroll':scrollCircle[0]}"></div>
<div :class="{'blueScroll':scrollCircle[1]}"></div>
<div :class="{'blueScroll':scrollCircle[2]}"></div>
</div>
</div>
</template>
<script>
export default:{
data() {
return {
scrollCircle:[false,false,false]//控制圆点亮度
}
},
methods:{
changeScroll(){
//获取滑动文本框滚动条的滚动值
let ls=$(this.$refs.scrolls).scrollLeft();
if(ls ==0){//根据实际情况判断
this.scrollCircle[1]=this.scrollCircle[0]=true;
this.scrollCircle[2]=false;
}else if(ls >70&& ls<100){
this.scrollCircle[0]=false
this.scrollCircle[1]=true
this.scrollCircle[2]=false
}else if(ls >150){
this.scrollCircle[0]=false
this.scrollCircle[1]=this.scrollCircle[2]=true
}
//重新渲染scrollCircle元素
this.scrollCircle=JSON.parse(JSON.stringify(this.scrollCircle));
}
}
}
</script>
<style>
.out-mainPageReport{
/*给子元素添加一个定位*/
position: relative;
/*.......*/
.act{
/*根据父级决定定位*/
position: absolute;
bottom: 0vw;
left: 43vw;
display: flex;
justify-content: space-between;
div{
width: 3vw;
height: 3vw;
margin-left: 1vw;
border: 1px solid lightblue;
border-radius: 3vw 3vw;
}
}
.blueScroll{
background-color: #0dbaf3;
}
}
</style>
- 2020.9.9 Pm
三、强制刷新组件
今天遇到一个有意思的事儿,如果想要强制刷新组件,这时候该怎么办。搜到了一个帖子,上面方法讲的很详细,我挑了一个适合自己的哈,也是最简单直接了当当当当当的方法。有时间看一下这个贴子,如何强制vue组件重新渲染。
问题的答案就是,在组件上添加key标识,key的作用主要是让vue知道某个组件是由某块数据渲染的,让数据对应的组件有种惟一的对应关系,通过key,vue可以知道那些数据变了,哪些没有变。如果key不变,vue将不会重新渲染组件,如果key改变了,vue会销毁旧的组件重新创建一个。
原理有了,那我们就开始动手实践。
<template>
<acomponent :key="index"></my-component>
</template>
<script>
import acomponent from './acomponent .vue';
export default {
components: { acomponent },
data() {
return {
index: 0
};
},
methods: {
forceRerender(){
this.index++;
}
},
mounted(){
this.forceRerender();
}
};
</script>
- 2020.11.20 Pm
四、画表格的小技巧
画表格不难,但是把多个表格组合起来就不是很容易,尤其是遇到单元格宽度的border大小占width、设置单元格宽度、以及单元格内容,接下来看下面这几个设置
table{
/*一般情况下,列表宽度由单元格内容决定,默认值auto,而fixed:列宽由表格宽度和列宽度设定*/
table-layout:fixed;
/*属性规定自动换行的处理方法*/
word-break:break-all;
/*需要设置固定宽度*/
width:99vw;
/*合并表格边框*/
border-collapse: collapse;
tr{
th{
/*文本水平居中*/
text-align: center;
/*文本垂直居中*/
vertical-align: middle;
/*假如您需要并排放置两个带边框的框,可通过将 box-sizing 设置为 "border-box"。这可令浏览器呈现出带有指定宽度和高度的框,并把边框和内边距放入框中。*/
box-sizing: border-box;
}
}
}
后来再画表格的时候发现,在表格外面套个div,这个div必须有一个指定的width才有用
- 2020.12.17 Pm
五、修改滚动条样式
/*修改滚动条样式*/
.content::-webkit-scrollbar{
width:10px;
height:10px;
/**/
}
.content::-webkit-scrollbar-track{
background: rgb(239, 239, 239);
border-radius:2px;
}
.content::-webkit-scrollbar-thumb{
background: #bfbfbf;
border-radius:10px;
}
.content::-webkit-scrollbar-thumb:hover{
background: #333;
}
.content::-webkit-scrollbar-corner{
background: #179a16;
}
六、处理数据的小操作
时隔许久,记录我常用的对数组的操作。
## 数组操作
var arr1=[1,2,3,4]
一、增加,操作的是原数组
//向前插入一个元素
arr1.unshift(0)//[0,1,2,3,4]
//向后追加一个元素
arr1.push(5)//[0,1,2,3,4,5]
//在数组中间插入一个元素,如在第三个位置插入'a'
arr1.splice(2,0,'a')//[0,1,'a',2,3,4,5]
二、删除,操作的是原数组
//从数组中删除第一个元素
arr1.shift()//[1,'a',2,3,4,5]
//从数组中删除最后一个元素
arr1.pop()//[1,'a',2,3,4]
//从数组中删除中间某个元素,案例:删除元素'a'
arr1.splice(arr1.indexOf('a'),1)//[1,2,3,4]
三,修改,操作的是原数组
//修改元素数组3,改成'b'
arr1.splice(arr1.indexOf(3),0,'b')//[1,2,'b',4]
四、复制
//根据元素下标复制数组,从下标1复制到下标3
arr1.slice(1,4)
五、排序---箭头函数语法
1、普通数组排序
//function xxx()相当于()
//{return xxx}分情况,如果方法体中只有return时,可省略return如下
//如还有其他则,{ return xxx}必须写全
arr1.sort((a,b)=>a-b)//升序
arr1.sort((a,b)=>b-a)//降序
//上面例子相当于
arr1.sort((a,b)=>{return a-b}) /*等价于*/ arr1.sort(function(a,b){return a-b})
2、数组中为对象,及对象之间按照某个属性值进行排序
var arr=[
{index:3},
{index:1},
{index:2}
]
arr.sort((a,b)=>a.index-b.index)
注:a,b代表的是arr数组下的每一个元素
3、连接两个数组,不修改原数组,返回新数组
var arrays=arr.concat(arr1) --合并两个数组
4、数组数字相加,条件是该数组内元素必须是数字或者能转换成数组的字符串数组
var numArr=["1",2,3,4]
var sum=numArr.reduce((t,n)=>t+parseInt(n)) -- 输出10
5、map函数的使用方法
//据我目前了解map操作数组,如
var arr2=[
{a:1,b:2},
{a:2,b:2}
]
var arr3=arr2.map((e)=>{
return e.a
})
//那么 arr3输出结果为[1,2],由此可见e代表的是数组中每个元素,这样操作不会影响到原数组.
6、es6数组去重
var a = [1,2,3,3,3,4,4,5,6,6]
//先用set对数组进行去重,然后将set对象转换成数组对象
Array.from(new Set(a))
//输出:[1,2,3,4,5,6]
//Array.form可以将类似数组形式转换成真正的数组
//某些用法可以类比map,如在上例中,对去重的数组进行自加
Array.from(new Set(a),(v)=>v+=v)
//输出:[2,3,6,8,10,12]
## 对象操作
var obj={}
一、增加属性
obj.name="张三"
obj.age=18
-- 输出:{name:"张三",age:18}
二、删除属性
delete obj.age;
-- 输出:{name:"张三"}
三、查找属性
Object.keys(obj)//这个东西是obj对象的所有属性的数组
例:查看obj对象里是否含有name属性
console.log(Object.keys(obj).indexOf("name")!=-1?"存在name属性":"不存在name属性")
四、修改属性值
obj.name="李四"
-- 输出:{name:"李四"}
五、合并对象
//这样操作会返回一个修改后的对象,如果不用原对象承接,也是会直接影响到原对象的
Object.assign(obj,{class:"三年一班"})
-- 输出:{name:"李四",class:"三年一班"}
## 补充: 箭头函数
基础格式: ()=>{}
作用范围,目前我在用的时候,只有使用匿名函数的时候在用这个,
而且还需要注意,如果你的函数里有使用到this这个关键字,最好还是
不要用箭头函数,因为箭头函数里的this指向的是父级this,谁调用
的 this 指向的就是谁的当前所在的作用域的对象。
一个参数的格式:参数名=>{}:例:e=>{}
一个参数且方法体里只有return:例:e=>e,返回的是e
多个参数且方法体中还有其他内容:例:(a,b)=>{var x=a,y=b return x+""+y}
例如上/述map的使用中还可以这样写:arr2.map(e=>e.a);
==== 重 点 ====
1、参数区域()可以创建初始值,即若调用时不传参数,就是这个值,且 无需使用类型声明(var、const、let),如
var test=(n=1)=>++n
test() -- 输出: 2
test(5) --输出: 6
2、参数括号内定义的变量是局部变量(默认参数),函数体内{}不使用
var定义的变量是全局变量,函数体内{} 用var定义的变量是局部变量
## 规律性字符串拼接
split() 、join()
例:var array = [1,2,3,4,5]
1) 用"-"将array元素拼接
var arr3 = array.join("-"); -- 输出"1-2-3-4-5"
2) 将arr3还原成array
var arr4 = arr3.map(e=>parseInt(e)) --输出[1,2,3,4,5]
注: join函数可以不传参数,直接将数组各个元素转换成字符串进行拼接
## 补充过滤器(filter)用法,数组对象的方法
作用是返回符合条件的元素
var b = [
{
name:"A",
value:1
},
{
name:"B",
value:1
}
]
例如返回name是A的对象
console.log(b.filter(function(v,i,arr){
return v.name==='A'
}))
## 补充reduce函数,数组方法,有累计叠加的功效
作用是将数组进行整合然后重组,
将其累计或添加到新数组形成一个整体或添加到对象中
例如:
var names=["app","user","permission","errorLog"]
var modules=[{
state:{},mutations:{},actions:{}
},{
state:{},mutations:{},actions:{}
},{
state:{},mutations:{},actions:{}
},{
state:{},mutations:{},actions:{}
}]
例如我想得到一个names数组和modules数组按照下标匹配的新对象
/*
{
app:{state:{},...},
user:{state:{},...},
permission:{state:{},...},
errorLog:{state:{},...}
}
*/
/*
1、reslt:是最终要得到的内容,其类型可以是Object,Array,Number等,
并且每次循环都要返回该值,然后待下次循环时可以使用,
2、reduce的第二个值可传可不传,如果不传,
那么result的值将会取该数组下标0的值,那么value值取该数组第二个值
*/
var result=names.reduce((result,value,index)=>{
result[value]=modules[index]
return result
},{})
## 补充:some函数,数组方法
作用:方法测试数组中是不是至少有 1 个元素通过了被提供的函数测试。
它返回的是一个 Boolean 类型的值。
const array = [1, 2, 3, 4, 5];
// checks whether an element is even
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// expected output: true
callback
用来测试每个元素的函数,接受三个参数:
element
数组中正在处理的元素。
index 可选
数组中正在处理的元素的索引值。
array可选
some()被调用的数组。
thisArg可选
执行 callback 时使用的 this 值。
七、var const let区别
一、var 声明的变量会存在window对象上,而const和let则不会;实际上可以用window.a得到
二、var 声明的变量存在变量提升,即在使用var声明变量之前使用到该变量时仅会提示undefined,不会报错
三、var 声明的变量可以跨作用域访问到,而const和let不行
四、var 可以声明相同变量在同一作用域下,而const和let不行
五、在块儿级作用域下,如果外部使用var 声明了一个变量a,则在块级作用域中如果再用let或const再次声明相同变量时,则外部使用var声明的a会无法直接得到,需要用到window.a的方式去获取。
六、const声明的变量,一旦声明必须赋值,不能使用null占位。且声明后不能再修改。如果声明的是个对象,可以修改对象的属性。
2021.5.17 Am
八、汉字拼音转换(小问题)
需要用到一个js(js-pinyin),使用如下。
1、npm引入
npm管理的js引入方法应该都在上面的连接里,我就不多说了
2、html直接引入pinyin.js
<script type="text/javascript" src="js/lib/js-pinyin/pinyin.js"></script>
3、使用:
var pinyin = new Pinyin();
//checkPolyphone: 是否检查多音字
//charCase: 输出拼音的大小写模式,0-首字母大写;1-全小写;2-全大写
pinyin.setOptions({checkPolyphone: true, charCase: 0});
let name="河南加油!!!!郑州加油!!!!"
//获取全拼,首字母大写
console.log(pinyin.getFullChars(name));//HeNanJiaYou!!!!ZhengZhouJiaYou!!!!
//简拼
console.log(pinyin.getCamelChars(name));//HNJY!!!!ZZJY!!!!
4、直接用简拼(getCamelChars)汇报k未定义错误,这个工具包中简拼可能需要修改一下原先的js
在pinyin.js中找到并修改成j即可
九、vuex 将数据保存在session中
插件:vuex-along
安装:
npm install vuex-along --save
# or
yarn add vuex-along
用法
import createVuexAlong from 'vuex-along'
export default new Vuex.Store({
state:{...},
modules:{
home:home
},
plugins: [createVuexAlong({
name:"localData",
session:{
list:[home.userMessage]
}
})]
});
十、es5继承
function Persion(name,age){
this.name=name;
this.age=age
}
function Student(name,age,score){
//继承属性
Persion.call(this,name,age)
this.score=score;
}
//es5原型继承——继承方法
//子类原型指向父类实例
Student.prototype=new Persion();
//子类原型构造器指向子类
Student.prototype.constructor=Student;
十一、Base64加密
npm install crypto-js
import CryptoJS from "crypto-js"
//encrypt
var rawStr = "hello world!";
var wordArray = CryptoJS.enc.Utf8.parse(rawStr);
console.log(1,wordArray)
var base64 = CryptoJS.enc.Base64.stringify(wordArray);
console.log(2,base64)
//decrypt
var parsedWordArray = CryptoJS.enc.Base64.parse(base64);
var parsedStr = parsedWordArray.toString(CryptoJS.enc.Utf8);
console.log(3,parsedStr);
十二、根据code查找目录树全目录名称
// 通过 code 反查全路径
// 参数:list: 属性数据 targetCode: 目标code fullPathList: 记录查找路径list
getFullListByCode(list, targetCode, fullPathList = []) { // fullPathList 全路径
let fullList
for (let i = 0; i < list.length; i++) {
let item = list[i]
let { code, name, childList } = item
let newfullPathList = [...fullPathList, { code, name }] // 存储上一级路径的数据
if (item.code === targetCode) {
return newfullPathList
} if (childList && childList.length) {
fullList = this.getFullListByCode(childList, targetCode, newfullPathList)
if (fullList) return tabList
}
}
return fullList
}
十三、Vue2全局监听eventHub(Bus总线)
//main.js
import Vue from "vue"
Vue.prototype.$eventHub=new Vue();
//任意一个顶级组件用来监听
export default{
mounted(){
this.$eventHub.$on('myChangeEvent',this.onChange)
},
beforeDestroy(){
this.$eventHub.$off('myChangeEvent')
},
methods:{
onChange(data){
console.log(data)
}
}
}
//子孙组件用来广播
export default{
methods:{
changeMyEvent(){
this.$eventHub.$emit('myChangeEvent',{value:1})
}
}
}
十四、数组分组与统计(lodash)
这里用到了lodash这个工具,注意第二个参数,若是函数则可以利用返回唯一值来多条件筛选
let arr=[
{"series":"大会议室A01","type":"07"},
{"series":"大会议室A01","type":"07"},
{"series":"大会议室A01","type":"07"},
{"series":"大会议室A01","type":"02"},
{"series":"大会议室A01","type":"03"},
{"series":"大会议室A01","type":"04"},
{"series":"大会议室A02","type":"04"}]
//假设你已经引入了lodash
Object.values(_.groupBy(arr,v=>`${v.series}#${v.type}`)).map(e=>{
return _.uniqBy(e,m=>{
m.count=e.length
return `${m.series}#${m.type}`
})
}).flat(1)
//
一、.groupBy(collection,func)函数
参数:
collection:Object||Array,
func:Function,
返回值:
Object
1、例:单条件分组,根据班级分
let a=[
{classroom:'一年一班',name:'小兰'},
{classroom:'一年一班',name:'小美'},
{classroom:'一年二班',name:'小马'},
{classroom:'一年二班',name:'小华'},
{classroom:'一年三班',name:'小红'},
{classroom:'一年三班',name:'小绿'},
]
//开始分组
_.groupBy(a,'classroom')
//输出:
{
"一年一班":[{"classroom":"一年一班","name":"小兰"},{"classroom":"一年一班","name":"小美"}],
"一年二班":[{"classroom":"一年二班","name":"小马"},{"classroom":"一年二班","name":"小华"}],
"一年三班":[{"classroom":"一年三班","name":"小红"},{"classroom":"一年三班","name":"小绿"}]
}
2、例:多条件分组,根据班级和时间分组
let a=[
{classroom:'一年一班',name:'小兰',time:'2060-1-1'},
{classroom:'一年一班',name:'小王',time:'2060-1-1'},
{classroom:'一年一班',name:'小美',time:'2060-1-2'},
{classroom:'一年二班',name:'小马',time:'2060-1-2'},
{classroom:'一年二班',name:'小赵',time:'2060-1-3'},
{classroom:'一年二班',name:'小刘',time:'2060-1-3'},
{classroom:'一年三班',name:'小红',time:'2060-1-4'},
{classroom:'一年三班',name:'小绿',time:'2060-1-5'},
{classroom:'一年三班',name:'小黄',time:'2060-1-5'},
]
//开始分组:
_groupBy(a,v=>`${v.classroom}#${v.time}`)//把字段连接起来,作为生成的对象的唯一属性
//输出:
{
"一年一班#2060-1-1":[
{"classroom":"一年一班","name":"小兰","time":"2060-1-1"},
{"classroom":"一年一班","name":"小王","time":"2060-1-1"}
],
"一年一班#2060-1-2":[
{"classroom":"一年一班","name":"小美","time":"2060-1-2"}
],
"一年二班#2060-1-2":[
{"classroom":"一年二班","name":"小马","time":"2060-1-2"}
],
"一年二班#2060-1-3":[
{"classroom":"一年二班","name":"小赵","time":"2060-1-3"},
{"classroom":"一年二班","name":"小刘","time":"2060-1-3"}
],
"一年三班#2060-1-4":[
{"classroom":"一年三班","name":"小红","time":"2060-1-4"}
],
"一年三班#2060-1-5":[
{"classroom":"一年三班","name":"小绿","time":"2060-1-5"},
{"classroom":"一年三班","name":"小黄","time":"2060-1-5"}
]
}
二、uniqBy去重
let a=[
{"series":"大会议室A01","type":"07"},
{"series":"大会议室A01","type":"07"},
{"series":"大会议室A01","type":"07"},
{"series":"大会议室A01","type":"02"},
{"series":"大会议室A01","type":"03"},
{"series":"大会议室A01","type":"04"},
{"series":"大会议室A02","type":"04"}]
//开始去重
_.uniqBy(arr,v=>v.series+'-'+v.type)
//输出:
[
{series: '大会议室A01', type: '07'},
{series: '大会议室A01', type: '02'},
{series: '大会议室A01', type: '03'},
{series: '大会议室A01', type: '04'},
{series: '大会议室A02', type: '04'},
]
十五、矩阵CSS(gaps,grid,box-sizing)
1、gap:盒子里上下边距和左右边距的间隔,依托于grid布局和flex布局
2、box-sizing:
content-box:width 与 height 只包括内容的宽和高,不包括边框(border),内边距(padding),外边距(margin)。
border-box:width 和 height 属性包括内容,内边距和边框,但不包括外边距。
box-sizing对外比较友好,对内可能需要自己根据实际情况调整
<style>
:root{
--box-width:300px;
--box-height:100px;
}
.container{
margin:0 auto;
width:calc( var(--box-width) * 3 + 100px);
height: calc( var(--box-height) * 4 + 30px);
border: 1px solid black;
display: flex;
gap: 10px 50px;
padding: 10px;
flex-wrap: wrap;
align-content: space-around;
}
.box{
width: var(--box-width);
height: var(--box-height);
background-color: antiquewhite;
}
</style>
<div class="container">
<div class="box"></div>
</div>
<!--或者-->
3、grid:
grid-template-columns:纵列中每列的宽度,因为纵裂受宽度影响,有几列设置几个
grid-template-rows:横排中每排的高度,因为横排受高度影响,有几排设置几个
<style>
:root{
--box-width:300px;
--box-height:100px;
}
.container{
margin:0 auto;
width:calc( var(--box-width) * 3 + 100px);
height: calc( var(--box-height) * 4 + 30px);
border: 1px solid black;
display: grid;
grid-template-columns:var(--box-width) var(--box-width) var(--box-width);
gap: 10px 50px;
padding: 10px;
}
.box{
width: var(--box-width);
height: var(--box-height);
background-color: antiquewhite;
}
</style>
<div class="container">
<div class="box"></div>
</div>
十六、目录树,查找指定子孙目录下的所有目录树
function collectCodes(treeArray, targetCode, collectedCodes = []) {
const findNode = findNodeByCode(treeArray, targetCode);
if (findNode) {
collectChildCodes(findNode, collectedCodes);
}
return collectedCodes;
}
function findNodeByCode(treeArray, targetCode) {
for (const node of treeArray) {
if (node.code === targetCode) {
return node;
}
if (node.children && node.children.length > 0) {
const foundNode = findNodeByCode(node.children, targetCode);
if (foundNode) {
return foundNode;
}
}
}
return null;
}
function collectChildCodes(node, collectedCodes) {
collectedCodes.push(node.code);
if (node.children && node.children.length > 0) {
for (const childNode of node.children) {
collectChildCodes(childNode, collectedCodes);
}
}
}
// 使用例子
const treeArray = [
// ... (你提供的树形数组)
{
code:'1'
}
];
const targetCode = "56781"; // 你想要选择的目录树中任意子目录或子孙目录的 code
const result = collectCodes(treeArray, targetCode);
console.log("收集到的 codes:", result);
十七、下载文件
//生成文件
let blob = new Blob(['测试']);
//创建下载链接
let href = URL.createObjectURL(blob);
//创建下载标签
let link = document.createElement('a');
//设置文件名
let fileName='测试下载.txt'
//download:导致浏览器将链接的 URL 视为下载资源。
link.download=fileName;
link.href=href;
link.click();