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

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

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

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

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

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

<template>
  <div class="box">
    <!-- 项目 -->
      <div class="treebox">
        <el-tree
          :data="treeData"
          :props="defaultProps"
          node-key="id"
          highlight-current
          ref="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.prevent
              class="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-column
                prop="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-column
                width="340"
                :label="$t('theads.Operation')"
                align="center"
              >
                <template slot-scope="scope">
                  <el-button
                    type="primary"
                    size="mini"
                    @click="_look(scope.row.id)"
                    >{{ $t("btns.see") }}</el-button
                  >
                  <!--  v-if="action != 3 && hasPerm('system:edit')" -->
                  <el-button
                    type="warning"
                    size="mini"
                    v-if="action != 3"
                    @click="_edit(scope.row.id)"
                    >{{ $t("btns.modify") }}</el-button
                  >
                  <!--  && hasPerm('system:delete') -->
                  <el-button
                    type="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;" -->
            <div
              class="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>

    <div
      style="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, // 列表loading
      isdel: 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 接收传的id
      workTextName: "", //接收传的 文本名称
      //  this.value = this.$route.query.id
      orgName: "", //选中的组织机构名称
      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) // 参数0
    console.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) { // 参数 数组 - id
    function tree(id) { // 接收的参数  第一级节点的父id,是null或者0
        let 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方法,存入名称和 id
                    area_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));
Logo

前往低代码交流专区

更多推荐