使用element-ui的el-tree組件入坑講解之setCheckedKeys

一、前提基礎

  • 掌握vue、element-ui相關前端知識,如有還沒掌握的童鞋能夠先去看個人vue全家桶一文:juejin.im/post/5bfe4a…

二、業務場景描述

  1. 假設如今咱們有一我的員列表,須要給每一個人配置特定的權限來限制哪些人能夠幹些什麼:

三、代碼

  1. 新建AuthTree.vue頁面:
<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="姓名" prop="name">  
      </el-table-column>
      <el-table-column label="性別" prop="sex">  
      </el-table-column>
      <el-table-column label="權限配置">
        <template slot-scope="scope">
          <el-button type="primary" size="mini" @click="opetation(scope.row.auth)">配置</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-dialog
      :visible.sync="dialogVisible"
      title="配置權限"
      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-button type="primary" @click="confirm">確 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
複製代碼
  1. 模擬數據data部分:
data() {
    return {
      listData: [
        {
          id: 1,
          name: 'syz',
          sex: '男',
          auth: [1, 2]
        },
        {
          id: 2,
          name: 'lyy',
          sex: '女',
          auth: [11, 21]
        },
        {
          id: 3,
          name: 'yf',
          sex: '男',
          auth: [211, 212]
        },
        {
          id: 4,
          name: 'xkl',
          sex: '女',
          auth: [211]
        },
        {
          id: 5,
          name: 'txl',
          sex: '女',
          auth: [221]
        }
      ],
      dialogVisible: false,
      treeData: [
        {
          id: 1,
          label: '一級 1',
          children: [
            {
              id: 11,
              label: '二級 1-1'
            },
            {
              id: 12,
              label: '二級 1-2'
            }
          ]
        }, 
        {
          id: 2,
          label: '一級 2',
          children: [
            {
              id: 21,
              label: '二級 2-1',
              children: [
                {
                  id: 211,
                  label: '三級 2-1-1'
                },
                {
                  id: 212,
                  label: '三級 2-1-2'
                }
              ]
            },
            {
              id: 22,
              label: '二級 2-2',
              children: [
                {
                  id: 221,
                  label: '三級 2-2-1'
                }
              ]
            }
          ]
        }
      ]
    }
  }
複製代碼

四、 問題描述

問題一:

  • 點擊配置opetation(scope.row.auth),須要彈出彈框並設置默認權限,這裏咱們經過id爲依據來勾選,這是須要設置依據node-key="id"
opetation (auth) {
      this.dialogVisible = true
      this.$refs.tree.setCheckedKeys(auth)
    }
複製代碼

這時候將會報如下錯誤:前端

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

相信不少人遇到過這個問題,這是由於this.dialogVisible = true時並無當即更新dom,而是等整個邏輯執行完後再一次新渲染,所以此時的彈框並未渲染,在dom樹中是不存在的,
this.$refs.tree is undefined的因此setCheckedKeys確定也是undefined。

解決方法: this.$nextTick(),this.$nextTick()會在dom更新以後在執行回調:

opetation (auth) {
  this.dialogVisible = true
  this.$nextTick(function() {
    this.$refs.tree.setCheckedKeys(auth)
  })
}
複製代碼

到這裏每次打開彈框的時候都會獲取最新的角色權限並勾選。vue

問題二:

  • 獲取節點數據後,當父節點被勾選時,全部的子節點所有被勾選,而實際上不少時候只有部分子節點被勾選。
  1. 經過check的方法獲取節點的信息:
    currentChecked(data, currentChecked) {
        const { checkedNodes, halfCheckedNodes } = currentChecked
        console.log(checkedNodes, halfCheckedNodes)
      }
    複製代碼
  2. check的方法,有兩個參數,該節點所對應的對象、樹目前的選中狀態對象(含checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四個屬性)。樹節點的狀態有三種,選中,部分選中,未選中。checkedNodes表示當前選中的節點,halfCheckedNodes表示部分選中(只可能存在於父節點,父節點下有部分子節點被選中)。
  3. 這裏提供一個解決思路,記錄選中節點的狀態:
    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 將auth數據保存至後臺
        }
    複製代碼
  4. 修改opetation方法和listData數據,根據type過濾,只設置所有選中的節點(type=1),父節點會根據子節點的狀況自動勾選。
    auth: [
        {
            id: 1,
            type:1
        }
    ]
    複製代碼
    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)
      })
    }
    複製代碼

問題三:

  • 當咱們將el-tree封裝成一個公用的組件的時候,好比叫auth-tree,這是在頁面中引用封裝好的組件。
<auth-tree
      ref="authTree"
      :show-checkbox="true"
      :tree-data="tableTreeData"
      @currentChecked="currentChecked"/>
複製代碼

這時若是咱們使用this.$refs.authTree.setCheckedKeys(auth) 仍然會報錯:node

vue.esm.js?efeb:591 [Vue warn]: Error in event handler for "click": "TypeError: Cannot read property 'setCheckedKeys' of undefined"
複製代碼

解決辦法:在父組件中:element-ui

click() {
    this.$refs.authTree.setCheckedKeys(auth) 
}
複製代碼

在組件中添加setCheckedKeys方法:api

setCheckedKeys(auth) {
    this.$refs.tree.setCheckedKeys(auth) 
}
複製代碼

五、 總結

  • node-key="id", 設置節點狀態的依據。
  • this.$nextTick()彈框打開後的回調。
  • setCheckedKeys()必須是經過節點自己的ref來直接。
  • checkedNodes, halfCheckedNodes,記錄幾點的不一樣狀態。
  • 本文只是針對特定的場景的講解,如遇到其它場景問題,歡迎留言一塊兒討論解決方案。
相關文章
相關標籤/搜索