Vue element ui tree hides the selected data and displays it when editing

all kinds of things have been having problems for several days. Please give me a train of thought. I feel like I have a problem with the array and data operation

.

problem description

add a freight template. After the user selects a region, the region cannot be selected or deleted, and the data is echoed when the user edits

the environmental background of the problems and what methods you have tried

put the selected id into an array disabled and store it in vuex, and then delete the edited items from disabled when editing again
but the data on the left side is initialized only once. When editing again, the data will affect each other

related codes

clipboard.png

data structure

{"name":"",
"valuation_type":"1"
"valuation_rules":
     [{"regions":[
        {"id":"13","title":"","pid":"0","open":false},
        {"id":"1301","title":"","pid":"13"}],
    "first_amount":1,
    "first_fee":"0.00",
    "additional_amount":"0",
    "additional_fee":"0.00"
    }.{"regions":[
        {"id":"11","title":"","pid":"0","open":false},
        {"id":"1101","title":"","pid":"11"}
    "first_amount":1,
    "first_fee":"0.00",
    "additional_amount":"0",
    "additional_fee":"0.00"
    }]
}

invoke component


  <div class="app-container">
    <div class="content">
      <el-form :model="freForm" status-icon :rules="freRules" ref="freForm" label-width="100px" class="fre-form" size="mini">
        <el-form-item label="" prop="name">
          <el-input type="text" v-model="freForm.name" auto-complete="off"></el-input>
        </el-form-item>
        <el-form-item label="" prop="valuation_type">
          <el-radio-group v-model="freForm.valuation_type">
            <el-radio :label="2"></el-radio>
            <el-radio :label="3"></el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="" prop="checkPass">
          <table class="fre-table sui-table table-bordered " style="width:900px">
            <thead>
              <tr>
                <th class="center"></th>
                <th class="center"></th>
                <th class="center"></th>
                <th class="center"></th>
                <th class="center"></th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(item,index) in freForm.valuation_rules" :key="index">
                <td class="left-td">
                  <span v-for="area in item.regions" :key="area.id" class="area-title" :class="{"strong":area.pid==0}"> {{area.title}} </span>
                  <el-button type="text" size="small" @click="editArea(index)"></el-button>
                  <el-button type="text" size="small"></el-button>
                </td>
                <td class="center">
                  <el-input type="text" size="mini" v-model="item.first_amount" auto-complete="off"></el-input>
                </td>
                <td class="center">
                  <el-input type="text" size="mini" v-model="item.first_fee" auto-complete="off"></el-input>
                </td>
                <td class="center">
                  <el-input type="text" size="mini" v-model="item.additional_amount" auto-complete="off"></el-input>
                </td>
                <td class="center">
                  <el-input type="text" size="mini" v-model="item.additional_fee" auto-complete="off"></el-input>
                </td>
              </tr>
            </tbody>
            <tfoot>
              <tr>
                <td colspan="5">
                  <el-button type="text" size="small" @click="addArea"></el-button>
                </td>
              </tr>
            </tfoot>
          </table>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm("freForm")"></el-button>
          <el-button @click="resetForm("freForm")"></el-button>
        </el-form-item>
      </el-form>
    </div>
    <!--address dialog-->
    <el-dialog :visible.sync="dialogVisible" width="630px" center>
      <synctree ref="synctree" v-model="finalData"></synctree>
      <span slot="footer" class="dialog-footer">
         <el-button @click="dialogVisible = false"> </el-button>
         <el-button type="primary" @click="submitArea"> </el-button>
      </span>
    </el-dialog>
    <!--address dialog-->
  </div>
  <script>
  import Synctree from "@/components/Synctree"
  import originData from "@/components/Synctree/data" //
  export default {
    components: {
      Synctree
    },
    data() {
      return {
        dialogVisible: false, //
        originData: originData, //
        freForm: { // 
          valuation_rules: [], 
          name: "",
          valuation_type: 2
        },
        }
      }
    },
      methods: {
      // 
      addArea() {
        this.dialogVisible = true
      },
     // 
      submitArea() {
        // 
        if (this.editIndex !== null) {
          // 
          this.freForm.valuation_rules[this.editIndex].regions = this.finalData
          // id
          this.editIndex = null
        } else {
          const temp = {
            regions: this.finalData,
            first_amount: 1,
            first_fee: "0.00",
            additional_amount: "0",
            additional_fee: "0.00"
          }
          // 
          if (this.finalData.length > 0) {
            this.freForm.valuation_rules.push(temp)
          }
        }
        // 
        this.finalData = []
        this.dialogVisible = false
      },
      // 
      editArea(index) {
       this.editIndex = index
        // 
       this.finalData = this.freForm.valuation_rules[index].regions
        this.dialogVisible = true 
      },
      init() {
        if (this.templateId) {
          const formData = {
            templateId: this.templateId
          }
          getFreightDetail(formData).then(res => {
            this.freForm = res.data.supplierFreightDetails
            console.log(this.freForm)
          })
        }
      }
    },

subcomponents

<template>
  <div class="v-component-sync-tree">
    <div class="origin-tree tree-item">
      <div class="tree-header"></div>
      <div class="tree-body">
        <el-tree :data="originTree" show-checkbox ref="originTree" node-key="id" :props="defaultProps" @check-change="getOriginKeys"></el-tree>
      </div>
    </div>
    <div class="tree-cut">
      <i class="ivu-icon ivu-icon-ios-arrow-right"></i>
      <el-icon class="el-icon-arrow-right"></el-icon>
    </div>
    <div class="final-tree tree-item">
      <div class="tree-header"></div>
      <div class="tree-body">
        <div class="body-main">
          <ul>
            <li v-for="(item,index) of finalTree" :key="item.id">
              <span class="item-text item-expand" @click.stop="toggleOpen(item.id)"> <el-icon class="item-icon" :class="item.open ?"el-icon-caret-bottom":"el-icon-caret-right""></el-icon>{{ item.title }}</span>
              <!--<span class="item-edit" @click.stop="popEditModal(item.id, item.title)">
                                <el-icon class="el-icon-edit"></el-icon>
                            </span>-->
              <span class="item-del" @click.stop="popDelModal(item.id, item.pid)">
                                <el-icon class="el-icon-delete"></el-icon>
                            </span>
              <ul class="tree-child" style="margin-left:20px;" :class="{"tree-show": item.open}">
                <li v-for="child of item.children" :key="child.id">
                  <span class="item-text">{{ child.title }}</span>
                  <!--<span class="item-edit" @click.stop="popEditModal(child.id, child.title)">
                                        <el-icon class="el-icon-edit"></el-icon>
                                    </span>-->
                  <span class="item-del" @click.stop="popDelModal(child.id, child.pid)">
                                        <el-icon class="el-icon-delete"></el-icon>
                                    </span>

                </li>
              </ul>
            </li>
          </ul>
        </div>
        <div class="edit-mask" v-if="editShow">
          <div class="edit-wrapper">
            <el-input class="edit-input" v-model="editText"></el-input>
            <div class="edit-opra-wrapper">
              <el-button-group>
                <el-button class="edit-cancel" type="default" @click="editCancel">
                  
                </el-button>
                <el-button class="edit-ok" type="primary" @click="editOk">
                  
                </el-button>
              </el-button-group>
            </div>
          </div>
        </div>
        <div class="del-mask" v-if="delShow">
          <div class="del-wrapper">
            <div class="del-text">
              <el-icon class="el-icon-warning"></el-icon>
              
            </div>
            <div class="del-opra-wrapper">
              <el-button-group>
                <el-button class="del-cancel" @click="delCancel">
                  
                </el-button>
                <el-button class="del-ok" type="primary" @click="delOk">
                  
                </el-button>
              </el-button-group>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import Tool from "./tool"
  require("./vue-component-sync-tree.scss")
  import {
    mapGetters
  } from "vuex"
  export default {
    name: "synctree",
    model: {
      prop: "finalList",
      event: "change"
    },

    props: {
      // 
      finalList: {
        type: Array,
        default: () => []
      },
      // 
      data: {
        type: Array,
        default: () => []
      }
      
    },
    data() {
      return {
        delShow: false, // 
        delId: "", //  => id
        delPid: "", //  => pid
        editShow: false, // 
        editText: "", //  => text
        editId: "", //  => id
        originTree: [], // Tree
        originKeys: [], // keys
        defaultProps: {
          children: "children",
          label: "title"
        },
        showChild: false,
        tempList: [],
        delKeys: [],
        ableKeys: []
      }
    },
    computed: {
      // 
        originList() {
            return this.data;
        },
      // Tree
      finalTree() {
        this.finalList.forEach(item => {
          if (item.open === undefined && Number(item.pid) === 0) {
            this.$set(item, "open", false)
          }
        })
        return Tool.arrToTree(this.finalList)
      },
      // keys
      finalKeys() {
        return this.finalList.map(item => item.id)
      },
      // keyskeys
      originToFinalKeys() {
        const parentKeys = []
        this.originList.forEach(item => {
          if (this.originKeys.includes(item.id) && Number(item.pid) !== 0) {
            parentKeys.push(item.pid)
          }
        })
        return this.unique([...parentKeys, ...this.originKeys])
      }
    },
    created() {
      // Tree
      this.initOriginTree()
    },
    mounted() {
      // 
      this.initOriginChecked()
      // this.initOriginDisChecked()
    },
    methods: {
      // 
      popDelModal(id, pid) {
        this.delId = id
        this.delPid = pid
        this.delShow = true
      },
      getFinalKeys() {
        //   console.log(this.originToFinalKeys)
      },
      // 
      delOk() {
        const keys = []
        keys.push(this.delId)
        if (Number(this.delPid) === 0) {
          // key
          this.finalTree.forEach(item => {
            if (item.id === this.delId) {
              item.children.forEach(child => {
                keys.push(child.id)
              })
            }
          })
        } else {
          // key
          keys.push(this.delPid)
        }
        // 
        keys.forEach(key => {
          this.originKeys = this.removeByValue(this.originKeys, key)
        })
        // 
        this.$refs.originTree.setCheckedKeys(this.originKeys)

        this.delCancel()
      },
      // 
      delCancel() {
        this.delShow = false
        this.delId = ""
        this.delPid = ""
      },
      // Tree
      initOriginTree() {
        this.originTree = Tool.arrToTree(this.originList)
      },
      // 
      initOriginChecked() {
        const checkedKeys = []
        this.finalList.forEach(item => {
          if (Number(item.pid) !== 0) {
            checkedKeys.push(item.id)
          } else {
            // 
            if (!this.finalList.map(i => i.pid).includes(item.id)) {
              checkedKeys.push(item.id)
            }
          }
        })
        this.$refs.originTree.setCheckedKeys(checkedKeys)
      },
      // keys
      getOriginKeys(data, checked, indeterminate) {
        //  console.log(data, checked, indeterminate)
        // if (checked === true) {
        //   this.disabledKeys.push(data.id)
        // } else {
        //   this.disabledKeys.splice(this.disabledKeys.findIndex(item => item === data.id), 1)
        // }
        this.originKeys = this.$refs.originTree.getCheckedKeys()
        // 
        // this.editCancel()
        // 
        // this.delCancel()
      },
      //  target  arg 
      findOut(target, arg) {
        return target.filter(v => !arg.includes(v))
      },
      // 
      removeByValue(target, arg) {
        const index = target.indexOf(arg)
        if (index !== -1) {
          target.splice(index, 1)
        }
        return target
      },
      // 
      unique(arr) {
        const newArr = []
        arr.forEach(item => {
          if (!newArr.includes(item)) {
            newArr.push(item)
          }
        })
        return newArr
      },
      // 
      toggleOpen(id) {
        // finalList  finalTreeidindex
        this.finalList.forEach(item => {
          if (item.id === id) {
            this.$set(item, "open", !item.open)
          }
        })
      }
    },
    watch: {
     
      // 
      originToFinalKeys() {
        // 
        this.findOut(this.originToFinalKeys, this.finalKeys).forEach(key => {
          this.originList.forEach(item => {
            if (item.id === key) {
              this.finalList.push(Tool.deepClone(item))
            }
          })
        })

        // item
        this.findOut(this.finalKeys, this.originToFinalKeys).forEach(key => {
          this.finalList.forEach(item => {
            if (item.id === key) {
              this.finalList = this.removeByValue(this.finalList, item)
            }
          })
        })
      },
      finalList() {
        // 
        this.initOriginChecked()
     
      }
    }
  }

</script>

<style rel="stylesheet/scss" lang="scss">
  .item-icon {
    font-size: 16px;
    vertical-align: middle;
    color: -sharpc0c4cc;
  }


  .tree-child {
    display: none;
  }

  .tree-show {
    display: block!important;
  }

</style>

what result do you expect? What is the error message actually seen?

selected data is not selectable, selected data can not be selected for time, but there is a problem with echo when editing

Mar.25,2021

solved it by yourself. The key is to reinitialize the data. Every time the box pops up, a copy of the data is copied and passed into the component.
every time you re-render the component, you can use v-if
< synctree VMI if = "reloadTree": data.sync= "tempList" VFI model = "finalData" > < / synctree >
. However, there is a drawback. If there is too much data, the performance is poor. I hope you can find another solution

.
     handleAdd() {
        this.reloadTree = true
        // 
        this.tempList = deepClone(this.originData)
        // disabled
        this.disabledKeys.forEach(key => {
          this.tempList.forEach(item => {
            if (key === item.id) {
              this.$set(item, 'disabled', true)
            }
          })
        })
        // 
        this.dialogVisible = true
      },

I will sort out a small demo in my spare time. Welcome to my github to watch
clipboard.png

.
Menu