1 递归函数必须接受参数。(比如我要递归谁?)

2 在递归函数的定义初始,应该有一个判断条件,当参数满足这个条件的时候,函数停止执行,并返回值。(指定退出条件,否则就会死循环)

3 每次递归函数执行自己的时候,都需要把当前参数做某种修改,然后传入下一次递归。(每次循环在调用自己一次并传参)

4当参数被累积修改到符合初始判断条件了,递归就停止了。(最后满足条件就退出)

简单的说递归函数就是在函数体内调用n次本函数。

看一下项目的要求怎么实现
项目要求
左侧树结构为“一级组织机构 到 三级设备”树,列表初始化显示选中的设备下已有的作业文本选项,
根节点不可以点击,默认选中第一个一级组织机构,第一个一级组织机构展开,其他均折叠。
列表按照文本的创建时间逆序排列。
如下图

代码

<template><div class="box"><!-- 项目 --><div class="treebox"><el-tree:data="treeData":props="defaultProps"node-key="id"highlight-currentref="trees":expand-on-click-node="false"@node-click="handleNodeClick":default-expanded-keys="expanded"@node-expand="_openNode"@node-collapse="_closeNode"><span class="custom-tree-node flex flexs" slot-scope="{ node, data }"><img :src=" !data.device && !data.channel ? imgorg  : data.device ? imgdevice :   imgchannel "  /><span>{{ node.label }}</span></span></el-tree></div><div class="tabbox"><div class="flex flexb tabhead"><div><Label :name="title" /></div><div class="searchform flex flexe"><el-form:inline="true"@submit.native.preventclass="demo-form-inline flex flexc"><el-form-item v-if="action != 3"><el-button type="primary" size="small" @click="_add">+ 新增巡视作业文本项目</el-button></el-form-item></el-form></div></div><div class="tabmain"><div class="tabs"><el-table:data="list"style="width: 100%":height="'100%'":highlight-current-row="true"ref="multipleTable"v-loading="loading"><!-- 序号 --><el-table-column:label="$t('theads.Numbers')"align="center"type="index"width="50":index="indexMethod"></el-table-column><el-table-column prop="partCode" label="部位名称" align="center"></el-table-column><el-table-columnprop="secondType"label="二级分类"align="center"></el-table-column><el-table-column prop="firstType" label="一级分类" align="center"></el-table-column><el-table-column prop="orgName" label="组织机构" align="center"></el-table-column><el-table-column prop="itemName" label="项目名称" align="center"></el-table-column><!-- 操作 --><el-table-columnwidth="340":label="$t('theads.Operation')"align="center"><template slot-scope="scope"><el-buttontype="primary"size="mini"@click="_look(scope.row.id)">{{ $t("btns.see") }}</el-button><!--  v-if="action != 3 && hasPerm('system:edit')" --><el-buttontype="warning"size="mini"v-if="action != 3"@click="_edit(scope.row.id)">{{ $t("btns.modify") }}</el-button><!--  && hasPerm('system:delete') --><el-buttontype="danger"size="mini"v-if="action != 3"@click="_del(scope.row)">{{ $t("btns.delete") }}</el-button></template></el-table-column></el-table><!--     style="position: absolute;bottom: 30px;left: 24px;" --><divclass="pagebox"><el-pagination@size-change="_changeSize"@current-change="_changePage":page-sizes="[10, 20, 30, 40]":page-size="size":current-page="page"layout="total, prev, pager, next, sizes":total="total"></el-pagination></div></div></div></div><divstyle="text-align: right;position: absolute;right: 15px;bottom: 15px;"><el-button type="primary" @click="_back">{{ $t("btns.back") }}</el-button></div><!--删除提示--><Del:isdel="isdel":content="content"@sure="_delApi"@cancle="_closeDel"/><!--新增修改--><Edit:isdialog="isEdit":title="names":id="id":action="actions"@close="_closeEdit"@submit="_submit"/><message:success="success":info="message":show="ismess"@close="_closemess"/></div>
</template><script>
import Label from "@/components/Label";
import Del from "@/components/Del";
import Edit from "../common/ProjectShow";
import {Tripletree, //三级树getDataList //新增// delEnyData,// 删除
} from "@/api/xunjian";
export default {components: {Label,Del,Edit},name: "mypage",data() {return {title: "巡视作业文本项目", //this.$t("lables.DataI"),names: "新增巡视作业文本项目", //this.$t("lables.NewDAT"),list: [],mess: null, // message 对象 重复提示 用于关于上一个loading: false, // 列表loadingisdel: false, // 删除提示框显示、隐藏content: "", // 删除提示语isEdit: false, // 新增修改弹框显示隐藏action: 0, // 新增、修改动作 1 新增 2修改actions: 0,total: 0,page: 1,size: 10,id: "",ismess: false,message: "",success: 1,treeData: [], //树结构数据expanded: [], //默认展开defaultProps: {children: "children",label: "orgName",id: "id",orgPid: "orgPid"},orgId: "", //选中的组织机构id 接收传的idworkTextName: "", //接收传的 文本名称//  this.value = this.$route.query.idorgName: "", //选中的组织机构名称treelist: [],harr: [],imgorg: require("../../../../assets/images/icon_org.png"),imgchannel: require("../../../../assets/images/icon_channel.png"),imgdevice: require("../../../../assets/images/icon_device.png"),rowObj: {}};},created() {//获取列表this.action = this.$route.query.action;this.loading = true;this._getList(); //tab表格this.getBaseOrg(); //获取树  **主要递归的逻辑在这里** },methods: {// 获取列表_getList() {this.loading = false;getDataList({current: this.page,size: this.size,workTextName: JSON.parse(sessionStorage.getItem("workTextName"))}).then(res => {console.log(res, "tab数据列表");this.loading = false;if (res.code == "SUCCESS") {this.list = res.data.records;this.total = res.data.total;}});},// 序号indexMethod(i) {return i + (this.page == 1 ? 0 : (this.page - 1) * this.size) + 1;},// 删除接口_delApi() {this.isdel = false;let params = {id: this.rowObj.id};console.log(params, "/params项目");delEnyData(params).then(res => {if (res.code == "SUCCESS") {this.ismess = true;this.success = 1;this.message = this.$t("phrase.DelSucc");this._getList();} else {this.ismess = true;this.success = 2;this.message = res.message;}}).catch(err => {this.isdel = false;this.ismess = true;this.success = 3;this.message = err.title;});},// 取消删除_closeDel() {this.$refs.multipleTable.clearSelection();this.isdel = false;},// 新增 一定判断一下有没有权限,这个权限是有没有选中三级_add() {console.log(this.orgId, this.WorkTextName, "//./././././");let isfalse = this._checkPromise(this.orgId); // filter组织机构权限if (!isfalse) {//如果没有this.ismess = true;this.success = 3;this.message = this.$t("phrase.noauthorg");this.WorkTextName = sessionStorage.getItem("workTextName");this.OrgId = sessionStorage.getItem("orgId");console.log(this.orgId, this.WorkTextName, "//./././././");return;}// 跳转编辑新增页面this.actions = 1;this.names = "新增巡视作业文本项目"; //this.$t("lables.NewDAT");this.isEdit = true;},// 关闭新增_closeEdit() {this.actions = 0;this.isEdit = false;},// 选择每页显示条数_changeSize(val) {this.size = val;this.page = 1;this.loading = true;this._getList();},// 选择页码_changePage(val) {this.page = val;// this.size = 10;this.loading = true;this._getList();},// 查看_look(id) {this.id = id;this.actions = 3;this.names = this.$t("lables.Look");this.isEdit = true;},// 编辑_edit(id) {this.id = id;this.actions = 2;this.names = this.$t("lables.Modify");this.isEdit = true;},// 提交回调_submit(msg, isfalse) {this.isEdit = isfalse;this.ismess = true;this.success =msg == this.$t("phrase.Savedsucc")? 1: msg == this.$t("phrase.Savefailed")? 2: 3;this.message = msg;if (!isfalse) {this.actions = -1;this._getList();}},// 关闭消息_closemess() {this.ismess = false;},// 删除_del(row) {this.rowObj = row;this.isdel = true;this.content = this.$t("phrase.suredelete");},// 返回_back() {this.$router.push("/Textbox");},// 拿到树结构  存默认显示的id和名字 给下一个页面 获取组织机构getBaseOrg() {//给树结构传参数 type:1 //  后端要的参数条件,这里是固定的如果有类似的可以不要参数,直接拿用Tripletree( { type: 1 } ).then(res => {console.log(res, "获取参数后的组织机构树");if (res.code == "SUCCESS") { // 请求成功后执行的条件语句this.treeData = res.data;// 默认展开项if (res.data.length) { // 返回的data有数据let treelist = sessionStorage.getItem("Treelist"); // 取出来sessionStorage里的树结构if (treelist) { // 如果有就不用执行递归条件, 在if 语句中直接去取存储的值console.log("没有执行递归条件");this.expanded = JSON.parse(treelist);let myOrgId = sessionStorage.getItem("orgId");this.orgId = myOrgId.replace(/\"/g, ""); // 把/替换成 ''。this.orgName = sessionStorage.getItem("orgname");} else { // 如果不存在 表结构 ,就进行循环递归console.log("执行递归");this._currData(this.treeData[0]); //循环递归,在递归中处理数据 part =1 后台要的this.orgId = this.expanded[0]; // 执行递归,在进行查找子集的三级设备并选中sessionStorage.setItem("orgId", this.orgId);sessionStorage.setItem("Treelist", JSON.stringify(this.expanded));}this.$nextTick(function() {this.$refs.trees.setCurrentKey(this.orgId); // 这里的 setCurrentKey是("需要被选中的节点的参数");});let harr = [];this.harr = this._formData(this.treeData[0], harr); // 合并数据 let isfalse = this._checkPromise(this.orgId); // filter 判断是否有组织机构权限console.log("执行其他");if (isfalse) {this.pages = 1;this.size = 10;this._getList();}}}});},// 树结构数据handleNodeClick(val) {if (val.id == 0 || val.part != 1 || this.expanded.length == 0) {this.$nextTick(function() {this.$refs.trees.setCurrentKey(this.orgId);});return;}// 缓存数据结构let treelist = sessionStorage.getItem("treelist");if (treelist) {// 存在缓存treelist = JSON.parse(treelist);treelist.push(val.id);let b = new Set(treelist);treelist = [...b];// sessionStorage.setItem("treelist", JSON.stringify(treelist));} else {let arr = [];arr.push(val.id);let b = new Set(arr);arr = [...b];// sessionStorage.setItem("treelist", arr);}// 选择机构this.orgId = val.id;this.orgName = val.orgName;sessionStorage.setItem("orgid", this.orgId);sessionStorage.setItem("orgname", this.orgName);if (val.flag) {console.log(111);this.loading = true;this.pages = 1;this.size = 10;this._getList();} else {console.log(222);this.ismess = true;this.isSucc = 3;this.tipmsg = this.$t("phrase.noauthorg");}},// 合并数据 也是递归存储合并_formData(data, arr) {if (data) {arr.push(data);if (data.children.length) {data.children.forEach(item => {this._formData(item, arr);});}}return arr;},// 判断是否有组织机构权限_checkPromise(id) {console.log(id, "这个id是递归得到的第一个三级id信息");let isarr = this.harr.filter(item => item.id == id);let isfalse = false;if (isarr.length) {if (isarr[0]["flag"]) {isfalse = true;} else {isfalse = false;}}return isfalse;},// 递归查询组织机构id_currData(data) { // 参数是 this.treeData[0]) 这个数组if (data) {let IDD = sessionStorage.getItem("orgid"); // 取到sessionStorage 值if (IDD == data.id) { // 如果能满足获取的id 和存储的id 一样this._DataArr(data); // 这里也是递归函数 参数是part = 1} else { /  其他条件 去找 children if (data.children.length) {data.children.forEach(item => {if (this.expanded.length == 0) {this._currData(item);}});}}}},// 再次递归_DataArr(data) {// part 为1的时候是有三级设备的if (data.part == 1) {let id = data.id;this.expanded.push(id);this.orgName = data.orgName;sessionStorage.setItem("orgname", data.orgName);}if (data.children.length) {data.children.forEach(item => {if (this.expanded.length == 0) {this._DataArr(item);}});}},// 节点被展开触发_openNode(val) {let arr = sessionStorage.getItem("treelist");if (arr) {arr = JSON.parse(arr);arr.push(val.id);let brr = new Set(arr);let crr = [...brr];sessionStorage.setItem("treelist", JSON.stringify(crr));}},// 节点关闭触发_closeNode(val) {// 清除过往选中项 判断是否被选中 如果被选中 只删除子项let arr = sessionStorage.getItem("treelist");if (arr) {arr = JSON.parse(arr);let rarr = [];let aid = this._currId(val, rarr);let b = arr.filter(item => aid.indexOf(item) == -1);let brr = new Set(b);let crr = [...brr];sessionStorage.setItem("treelist", JSON.stringify(crr));}},// 递归id_currId(data, arr) {if (data) {arr.push(data.id);if (data.children.length) {data.children.forEach(item => {this._currId(item, arr);});}}return arr;}}
};
</script><style scoped lang="scss">
@import "../index.css";.treebox {width: 200px;flex-grow: 0;flex-shrink: 0;height: 100%;overflow-y: auto;overflow-x: auto;
}
.custom-tree-node img {width: 16px;margin-right: 5px;
}
</style>

到这里就结束了。

为了更为方便的看效果
在给一个小例子1

    let num = 0;function recursion(params) {if (params > 100) {return} else { // 先会走这里知道值为100的时候num += params;return recursion(params + 1)}}recursion(0) // 参数0console.log(num);  // 5050

小例子2

// 升级版,递归树
假设一个模拟的数据const data = [{"area_id": 5,"name": "广东省","parent_id": 0,}, {"area_id": 6,"name": "广州市","parent_id": 5,}, {"area_id": 7,"name": "深圳市","parent_id": 5,}, {"area_id": 4,"name": "北京市","parent_id": 3,}, {"area_id": 3,"name": "北京","parent_id": 0,}, {"area_id": 2,"name": "测试子地区","parent_id": 1,}, {"area_id": 1,"name": "测试地区","parent_id": 0,}]function toTreeData(data, pid) { // 参数 数组 - idfunction tree(id) { // 接收的参数  第一级节点的父id,是null或者0let arDat = []data.filter(item => { // filter过滤data数组每一项return item.parent_id === id; // 返回符合条件 每一项id 和 传入的id 数据相同的数据 ,这里返回的是一个数组 ,那么直接进行forEach循环}).forEach(item => {console.log(arDat .length); // 打印一下,看看长度,有没有值if (!tree(item.area_id).length) { // 如果没有id的长度arDat .push({ // push方法,存入名称和 idarea_id: item.area_id,label: item.name,})} else { 如果有arDat .push({ // push 名称,id,和二三级子项area_id: item.area_id,label: item.name,children: tree(item.area_id)})}})return arDat // 把变量数组arDat return出去}return tree(pid) // 第一级节点的父id,是null或者0,视情况传入
}
console.log(toTreeData(data, 0));

vue 项目实战 递归相关推荐

  1. vue 动态添加class_前端开发:Vue项目实战-Music

    大家好,我来了,本期为大家带来的前端开发知识是"前端开发:Vue项目实战-Music",有兴趣做前端的朋友,和我一起来看看吧! 主要内容 项目环境搭建 路由导航实现 ListVie ...

  2. vue 将字符串最后一个字符给替换_前端开发:Vue项目实战-Music

    大家好,我来了,本期为大家带来的前端开发知识是"前端开发:Vue项目实战-Music",有兴趣做前端的朋友,和我一起来看看吧! 主要内容 项目环境搭建 路由导航实现 ListVie ...

  3. 【VUE项目实战】68、使用pm2管理项目

    接上篇<67.上线-开启gzip和配置HTTPS服务> 上一篇我们学习了如何开启gzip配置来减少文件访问体积,并配置HTTPS服务.本篇我们讲解一下如何使用pm2管理项目. 本篇是该系列 ...

  4. Vue项目实战 —— 后台管理系统( pc端 )

    前期回顾 我只写注释 -- 让Ai写代码_的博客-CSDN博客前期回顾 Vue项目实战 -- 哔哩哔哩移动端开发-- 第二篇_的博客-CSDN博客https://blog.csdn.net/m0_57 ...

  5. 【VUE项目实战】32、权限管理-实现角色列表

    接上篇<31.权限管理-实现权限列表> 上个阶段我们完成了权限管理模块,本篇我们来介绍用户.角色和权限三者的关系,并完成角色管理列表模块. 一.权限管理业务分析 通过权限管理模块,控制不同 ...

  6. 【VUE项目实战】64、CND优化ElementUI以及首页内容定制

    接上篇<63.指定打包入口及加载外部CDN资源> 上一篇我们为开发模式与发布模式制定不同的打包入口,然后为项目加载外部CDN资源.本篇我们来学习通过CND优化ElementUI的打包,以及 ...

  7. Vue项目实战 —— 哔哩哔哩移动端开发—— 第一篇

    目录 前言完 效果图 : 登录含签权 注册带正则 个人中心 下拉加载更多主页 修改个人中心 视频播放加关注+收藏 评论盖楼A回复B B回复C C回复A类似 项目开始 封装登录.注册 封装登录 从零到一 ...

  8. 【VUE项目实战】59、订单的物流信息查询功能

    接上篇<58.订单修改收货地址的功能> 上一篇我们完成了订单列表的修改收货地址功能,本篇我们来实现订单的物流信息查询功能. 一.要实现的效果 我们要实现点击操作列的"物流进度&q ...

  9. Vue项目实战 —— 哔哩哔哩移动端开发—— 第二篇

    前期回顾     30秒学会 -- <获取验证码基本操作>_0.活在风浪里的博客-CSDN博客前期回顾 懒人必备 -- 时间神器 moment_0.活在风浪里的博客-CSDN博客亲测好用, ...

最新文章

  1. windows下rpc框架thrift的环境配置
  2. python技术点总结_Python技术点总结,碰到问题再也不用慌了!
  3. JQuery学习系列(九)AJAX
  4. 如何在一小时内更新100篇文章?-Evernote Sync插件介绍
  5. http服务器异步响应,python – 具有异步响应的Twisted http服务器,其中请求必须等待数据变为可用或超时...
  6. 上下双刘海设计感受下!夏普新旗舰亮相:骁龙855加持
  7. 玩转 SpringBoot 2 之整合 WebSocket 篇
  8. 文本分类模型_【文本分类】几个可作为Baseline的模型
  9. 分布式多副本一致性协议:paxos
  10. 事件对象以及事件委托(pink老师笔记)
  11. C. Dominant Piranha
  12. 微信小程序——校园服务小程序(四)校园论坛加预约理发服务
  13. Cocos野兽派 | 如何创造真正的优秀游戏
  14. 单片机MCU学习方法总结
  15. android连接打印机
  16. 内蒙古电大计算机考试成绩查询成绩查询,2021年网络教育7月统考成绩查询时间及入口...
  17. s3cmd 快速评估RADOSGW的性能
  18. 关于计算机方面的一些数学书
  19. 物理复习2振动、波动
  20. NTLDR是做什么的,丢失了如何恢复

热门文章

  1. Keil环境添加STC系列单片机
  2. 计算机专业用什么轴的键盘,机械键盘的哪个轴适合办公室使用
  3. 武汉大学计算机学院跳楼,武汉大学一男生跳楼身亡,自杀原因反思:徒劳教育往往跟父母有关...
  4. JMeter_Ubuntu上安装jmeter
  5. xmind 使用详解
  6. 今日头条 爬虫 java_爬虫实例:今日头条爬虫
  7. scrapy shell 调试报错TypeError: module.__init__() takes at most 2 arguments (3 g iven)
  8. Appium用xpath定位掌阅APP导航页的跳过按钮(只有class和index)
  9. stm32f103c8t6调试-while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET );卡死
  10. 计算机网络面试常见题