全国免费服务热线:

18982081108
✕

成都弹性云服务器,成都高防云服务器,互联网数据服务,成都祈钰瑶

我用Vue.js与ElementUI搭建了一个无限级联层级表格组件

 前言

今天,回老家了。第一件事就是回家把大屏安排上,写作的感觉太爽了,终于可以专心地写文章了。我们今天要做的项目是怎么样搭建一个无限级联层级表格组件,好了,多了不多说,赶快行动起来吧!

项目一览

到底是啥样子来?我们来看下。

正如你所看到的那样,这个组件涉及添加、删除、编辑功能,并且可以无限级嵌套。那么怎样实现的?我们来看下。

源码

直接给出源码,就是这么直接。

 
 
 
 
  1. <template>
  2.     <div class="container">
  3.         <el-button
  4.             type="primary"
  5.             size="small"
  6.             @click="handleCreate"
  7.             icon="el-icon-circle-plus-outline"
  8.             style="margin: 10px 0"
  9.             >添加</el-button
  10.         >
  11.         <el-table
  12.             :data="tableData"
  13.             style="width: 100%; margin-bottom: 20px"
  14.             border
  15.             row-key="value"
  16.             stripe
  17.             size="medium"
  18.             :tree-props="{ children: 'children' }"
  19.         >
  20.             <el-table-column prop="label" label="标签名称"> </el-table-column>
  21.             <el-table-column prop="location" label="层级"> </el-table-column>
  22.             <el-table-column label="操作" :align="alignDir" width="180">
  23.                 <template slot-scope="scope">
  24.                     <el-button
  25.                         type="text"
  26.                         size="small"
  27.                         @click="handleUpdate(scope.row)"
  28.                         >编辑</el-button
  29.                     >
  30.                     <el-button
  31.                         type="text"
  32.                         size="small"
  33.                         @click="deleteClick(scope.row)"
  34.                         >删除</el-button
  35.                     >
  36.                 </template>
  37.             </el-table-column>
  38.         </el-table>
  39.         <el-dialog
  40.             :title="textMap[dialogStatus]"
  41.             :visible.sync="dialogFormVisible"
  42.             width="30%"
  43.         >
  44.             <el-form
  45.                 ref="dataForm"
  46.                 :rules="rules"
  47.                 :model="temp"
  48.                 label-position="left"
  49.                 label-width="120px"
  50.                 style="margin-left: 50px"
  51.             >
  52.                 <el-form-item
  53.                     label="层级:"
  54.                     prop="location"
  55.                     v-if="dialogStatus !== 'update'"
  56.                 >
  57.                     <el-select
  58.                         v-model="temp.location"
  59.                         placeholder="请选择层级"
  60.                         @change="locationChange"
  61.                         size="small"
  62.                     >
  63.                         <el-option
  64.                             v-for="item in locationData"
  65.                             :key="item.id"
  66.                             :label="item.name"
  67.                             :value="item.id"
  68.                         />
  69.                     </el-select>
  70.                 </el-form-item>
  71.                 <el-form-item
  72.                     v-if="sonStatus && dialogStatus !== 'update'"
  73.                     label="子位置:"
  74.                     prop="children"
  75.                 >
  76.                     <el-cascader
  77.                         size="small"
  78.                         :key="isResouceShow"
  79.                         v-model="temp.children"
  80.                         placeholder="请选择子位置"
  81.                         :label="'label'"
  82.                         :value="'value'"
  83.                         :options="tableData"
  84.                         :props="{ checkStrictly: true }"
  85.                         clearable
  86.                         @change="getCasVal"
  87.                     ></el-cascader>
  88.                 </el-form-item>
  89.                 <el-form-item label="标签名称:" prop="label">
  90.                     <el-input
  91.                         v-model="temp.label"
  92.                         size="small"
  93.                         autocomplete="off"
  94.                         placeholder="请输入标签名称"
  95.                     ></el-input>
  96.                 </el-form-item>
  97.             </el-form>
  98.             <div slot="footer" class="dialog-footer">
  99.                 <el-button @click="dialogFormVisible = false" size="small">
  100.                     取消
  101.                 </el-button>
  102.                 <el-button
  103.                     type="primary"
  104.                     size="small"
  105.                     @click="
  106.                         dialogStatus === 'create' ? createData() : updateData()
  107.                     "
  108.                 >
  109.                     确认
  110.                 </el-button>
  111.             </div>
  112.         </el-dialog>
  113.     </div>
  114. </template>
  115. <script>
  116. export default {
  117.     name: 'Tag',
  118.     data() {
  119.         return {
  120.             alignDir: 'center',
  121.             textMap: {
  122.                 update: '编辑',
  123.                 create: '添加',
  124.             },
  125.             dialogStatus: '',
  126.             dialogFormVisible: false,
  127.             temp: {},
  128.             isResouceShow: 1,
  129.             sonStatus: false,
  130.             casArr: [],
  131.             idx: '',
  132.             childKey: [],
  133.             rules: {
  134.                 location: [
  135.                     {
  136.                         required: true,
  137.                         message: '请选择层级',
  138.                         trigger: 'blur',
  139.                     },
  140.                 ],
  141.                 label: [
  142.                     { required: true, message: '请输入名称', trigger: 'blur' },
  143.                 ],
  144.                 children: [
  145.                     {
  146.                         required: true,
  147.                         message: '请选择子位置',
  148.                         trigger: 'blur',
  149.                     },
  150.                 ],
  151.             },
  152.             locationData: [
  153.                 {
  154.                     id: '1',
  155.                     name: '顶',
  156.                 },
  157.                 {
  158.                     id: '2',
  159.                     name: '子',
  160.                 },
  161.             ],
  162.             tableData: [
  163.                 {
  164.                     tagId: '1', // 标签id
  165.                     label: '第0', // 标签名称
  166.                     parent: '', // 父级名称
  167.                     location: '1', // 层级
  168.                     value: '0', // 标识位
  169.                     children: [
  170.                         {
  171.                             tagId: '1', // 子标签id
  172.                             childKey: ['0', '0'], // 子标识位
  173.                             label: '第0-0',
  174.                             parent: '第0',
  175.                             location: '2',
  176.                             value: '0-0',
  177.                             children: [],
  178.                         },
  179.                         {
  180.                             tagId: '2', // 子标签id
  181.                             childKey: ['0', '1'],
  182.                             label: '第0-1',
  183.                             parent: '第0',
  184.                             location: '2',
  185.                             value: '0-1',
  186.                             children: [],
  187.                         },
  188.                     ],
  189.                 },
  190.             ]
  191.         };
  192.     },
  193.     methods: {
  194.         // 递归寻找同级
  195.         findSameTable(arr, i, casArr) {
  196.             if (i == casArr.length - 1) {
  197.                 return arr;
  198.             } else {
  199.                 return this.findTable(
  200.                     arr[casArr[i].substr(casArr[i].length - 1, 1)].children,
  201.                     (i += 1),
  202.                     casArr
  203.                 );
  204.             }
  205.         },
  206.         // 寻找父级
  207.         findTable(arr, i, casArr) {
  208.             if (i == casArr.length - 1) {
  209.                 let index = casArr[i].substr(casArr[i].length - 1, 1);
  210.                 return arr[index];
  211.             } else {
  212.                 return this.findTable(
  213.                     arr[casArr[i].substr(casArr[i].length - 1, 1)].children,
  214.                     (i += 1),
  215.                     casArr
  216.                 );
  217.             }
  218.         },
  219.         // 递归表格数据(添加)
  220.         find(arr, i) {
  221.             if (i == this.casArr.length - 1) {
  222.                 return arr[this.casArr[i].substr(this.casArr[i].length - 1, 1)]
  223.                     .children;
  224.             } else {
  225.                 return this.find(
  226.                     arr[this.casArr[i].substr(this.casArr[i].length - 1, 1)]
  227.                         .children,
  228.                     (i += 1)
  229.                 );
  230.             }
  231.         },
  232.         // 递归表格数据(编辑)
  233.         findSd(arr, i, casArr) {
  234.             if (i == casArr.length - 1) {
  235.                 let index = casArr[i].substr(casArr[i].length - 1, 1);
  236.                 return arr.splice(index, 1, this.temp);
  237.             } else {
  238.                 return this.findSd(
  239.                     arr[casArr[i].substr(casArr[i].length - 1, 1)].children,
  240.                     (i += 1),
  241.                     casArr
  242.                 );
  243.             }
  244.         },
  245.         // 递归寻找同步名称
  246.         findLable(arr, i, casArr) {
  247.             if (i == casArr.length - 1) {
  248.                 let index = casArr[i].substr(casArr[i].length - 1, 1);
  249.                 return arr[index];
  250.             } else {
  251.                 return this.findLable(
  252.                     arr[casArr[i].substr(casArr[i].length - 1, 1)].children,
  253.                     (i += 1),
  254.                     casArr
  255.                 );
  256.             }
  257.         },
  258.         // 同步子名称
  259.         useChildLable(arr) {
  260.             if (arr !== []) {
  261.                 arr.forEach((item) => {
  262.                     item.parent = this.temp.label;
  263.                 });
  264.             }
  265.         },
  266.         // 递归表格数据(删除)
  267.         findDel(arr, i, item) {
  268.             let casArr = item.childKey;
  269.             if (i == casArr.length - 2) {
  270.                 let index = casArr[i].substr(casArr[i].length - 1, 1);
  271.                 arr[index].children.forEach((it, ix, arrs) => {
  272.                     if (it == item) {
  273.                         return arrs.splice(ix, 1);
  274.                     }
  275.                 });
  276.             } else {
  277.                 return this.findDel(
  278.                     arr[casArr[i].substr(casArr[i].length - 1, 1)].children,
  279.                     (i += 1),
  280.                     item
  281.                 );
  282.             }
  283.         },
  284.       // 置空
  285.         resetTemp() {
  286.             this.temp = {};
  287.         },
  288.       // 打开添加
  289.         handleCreate() {
  290.             this.resetTemp();
  291.             this.dialogFormVisible = true;
  292.             this.dialogStatus = 'create';
  293.             this.$nextTick(() => {
  294.                 this.$refs['dataForm'].clearValidate();
  295.             });
  296.         },
  297.       // 添加
  298.         createData() {
  299.             this.$refs['dataForm'].validate((valid) => {
  300.                 if (valid) {
  301.                     if (this.sonStatus == false) {
  302.                         this.temp.value = String(this.tableData.length);
  303.                         const obj = Object.assign({}, this.temp);
  304.                         obj.children = [];
  305.                         obj.parent = '';
  306.                         this.tableData.push(obj);
  307.                         this.$message({
  308.                             type: 'success',
  309.                             message: '添加成功',
  310.                         });
  311.                         this.dialogFormVisible = false;
  312.                     } else {
  313.                         let arr = this.find(this.tableData, 0);
  314.                         this.temp.value =
  315.                             String(this.casArr[this.casArr.length - 1]) +
  316.                             '-' +
  317.                             String(arr.length);
  318.                         delete this.temp.children;
  319.                         const obj = Object.assign({}, this.temp);
  320.                         obj.children = [];
  321.                         obj.childKey = [...this.casArr, String(arr.length)];
  322.                         obj.parent = this.findTable(
  323.                             this.tableData,
  324.                             0,
  325.                             this.casArr
  326.                         ).label;
  327.                         if (this.temp.location === '2') {
  328.                             obj.location = String(
  329.                                 [...this.casArr, String(arr.length)].length
  330.                             );
  331.                         }
  332.                         arr.push(obj);
  333.                         this.$message({
  334.                             type: 'success',
  335.                             message: '添加成功',
  336.                         });
  337.                         this.dialogFormVisible = false;
  338.                     }
  339.                 } else {
  340.                     return false;
  341.                 }
  342.             });
  343.         },
  344.       // 打开更新
  345.         handleUpdate(row) {
  346.             console.log(row);
  347.             row.value.length != 1
  348.                 ? (this.sonStatus = true)
  349.                 : (this.sonStatus = false);
  350.             this.temp = Object.assign({}, row); // copy obj
  351.             if (row.childKey) {
  352.                 this.childKey = row.childKey;
  353.                 this.idx = row.childKey[row.childKey.length - 1];
  354.             } else {
  355.                 this.idx = row.value;
  356.             }
  357.             console.log(this.idx);
  358.             this.dialogStatus = 'upd