1. Premise basis

  • Master vue, element-UI related front-end knowledge, if you have not mastered the children’s shoes can first go to see my Vue family barrel: juejin.cn/post/684490… .

2. Service scenario description

  1. Suppose we now have a list of people who need to be assigned specific permissions to restrict who can do what:

3, code,

  1. Create authTree. vue page:
<template>
  <div class="auth_tree">
    <el-table
      :data="listData"
      border
      style="width: 100%;">
      <el-table-column label="ID" prop="id">  
      </el-table-column>
      <el-table-column label="Name" prop="name">  
      </el-table-column>
      <el-table-column label="Gender" prop="sex">  
      </el-table-column>
      <el-table-column label="Permission Configuration">
        <template slot-scope="scope">
          <el-button type="primary" size="mini" @click="opetation(scope.row.auth)"> Configure </el-button> </template> </el-table-column> </el-table> <el-dialog :visible. Sync ="dialogVisible"
      title="Configure Permissions"
      center
      width="600px"
      @close="closeDialog">
      <div class="dialog_main_content">
        <el-tree
          ref="tree"
          :data="treeData"
          :expand-on-click-node="false"
          :show-checkbox="true"
          node-key="id"
          default-expand-all
          @check="currentChecked"/>
      </div>
      <div class="dialog_footer">
        <el-button @click="cancel"</el-button> <el-buttontype="primary" @click="confirm"> determine < / el - button > < / div > < / el - dialog > < / div > < / template >Copy the code
  1. Simulation data data part:
 data() {
    return {
      listData: [
        {
          id: 1,
          name: 'syz',
          sex: 'male',
          auth: [1, 2]
        },
        {
          id: 2,
          name: 'lyy',
          sex: 'woman',
          auth: [11, 21]
        },
        {
          id: 3,
          name: 'yf',
          sex: 'male',
          auth: [211, 212]
        },
        {
          id: 4,
          name: 'xkl',
          sex: 'woman',
          auth: [211]
        },
        {
          id: 5,
          name: 'txl',
          sex: 'woman',
          auth: [221]
        }
      ],
      dialogVisible: false,
      treeData: [
        {
          id: 1,
          label: 'level 1',
          children: [
            {
              id: 11,
              label: 'secondary 1-1'
            },
            {
              id: 12,
              label: 'secondary 1-2'
            }
          ]
        }, 
        {
          id: 2,
          label: 'level 2',
          children: [
            {
              id: 21,
              label: 'secondary 2-1',
              children: [
                {
                  id: 211,
                  label: 'triple the 2-1-1'
                },
                {
                  id: 212,
                  label: 'triple the 2-1-2'
                }
              ]
            },
            {
              id: 22,
              label: 'secondary 2-2',
              children: [
                {
                  id: 221,
                  label: 'triple the 2-2-1'}]}]}}Copy the code

4. Problem description

Problem a:

  • Click Configure Opetation (scope.row.auth), the popup box needs to pop up and set the default permission. Here we check it by id, which needs to be set according to Node-key =”id”.
    opetation (auth) {
      this.dialogVisible = true
      this.$refs.tree.setCheckedKeys(auth)
    }
Copy the code

The following error is reported:

vue.esm.js?efeb:591 [Vue warn]: Error in event handler for "click": "TypeError: Cannot read property 'setCheckedKeys' of undefined"I believe many people have encountered this problem because this.dialogVisible =true", the dom is not updated immediately, but is rendered again after the whole logic is executed. Therefore, the popbox is not rendered and does not exist in the DOM tree.$refs.tree is undefinedsetCheckedKeys is definitely undefined. Solution: This.$nextTickThis ().$nextTick() will execute the callback after dom update: opetation (auth) {this.dialogVisible =true
  this.$nextTick(function() {
    this.$refs.tree.setCheckedKeys(auth)
  })
}
Copy the code

Every time you open the popup box, you will get the latest role permissions and check them.

Problem two:

  • After obtaining node data, when the parent node is selected, all the child nodes are selected, but in fact, only part of the molecular nodes are selected in many cases.
  1. Obtain node information by using the check method:
      currentChecked(data, currentChecked) {
        const { checkedNodes, halfCheckedNodes } = currentChecked
        console.log(checkedNodes, halfCheckedNodes)
      }
    Copy the code
  2. The check method has two parameters: the object corresponding to this node and the current selected object of the tree (including four attributes checkedNodes, checkedKeys, halfCheckedNodes, and halfCheckedKeys). There are three states of a tree node: selected, partially selected, and unselected. CheckedNodes indicates the currently selected node, and halfCheckedNodes indicates the partially selected node (only the parent node has some selected nodes under the parent node).
  3. Note the status of the selected node:
        currentChecked(data, currentChecked) {
          let auth = []
          const { checkedNodes, halfCheckedNodes } = currentChecked
          halfCheckedNodes.length && halfCheckedNodes.forEach(({ id }) => {
            auth.push({
              id,
              type: 2
            })
          })
          checkedNodes.length && checkedNodes.forEach(({ id }) => {
            auth.push({
              id,
              type: 1})}) // API saves auth data to background}Copy the code
  4. Modify the opetation method and listData data to filter by type and set only the selected nodes (type=1). The parent node will be automatically selected according to the status of the child nodes.
    auth: [
        {
            id: 1,
            type: 1}]Copy the code
    opetation (auth) {
      this.dialogVisible = true
      const arr = []
      auth.length &&auth.map(({ id, type= > {})type === 1 && arr.push(id)
      })
      this.$nextTick(function() {
        this.$refs.tree.setCheckedKeys(arr)
      })
    }
    Copy the code

Question 3:

  • When we encapsulate the el-Tree into a common component, such as auth-tree, this refers to the encapsulated component in the page.
 <auth-tree
      ref="authTree"
      :show-checkbox="true"
      :tree-data="tableTreeData"
      @currentChecked="currentChecked"/>
Copy the code

At this time if we use this. $refs. AuthTree. SetCheckedKeys (auth) will still be an error:

vue.esm.js?efeb:591 [Vue warn]: Error in event handler for "click": "TypeError: Cannot read property 'setCheckedKeys' of undefined"
Copy the code

Solution: In the parent component:

click() {
    this.$refs.authTree.setCheckedKeys(auth) 
}
Copy the code

Add the setCheckedKeys method to the component:

setCheckedKeys(auth) {
    this.$refs.tree.setCheckedKeys(auth) 
}
Copy the code

5, summary

  • Node-key =”id”, which is used to set the node status.
  • Callback after this.$nextTick () pops open.
  • SetCheckedKeys () must be direct through the ref of the node itself.
  • CheckedNodes, halfCheckedNodes, records the different states of several points.
  • This article is only for specific scenarios. If you encounter other scenarios, please leave a comment and discuss solutions.