首頁 >web前端 >Vue.js >Vue 中使用 directive 實作表格樹的技巧及最佳實踐

Vue 中使用 directive 實作表格樹的技巧及最佳實踐

WBOY
WBOY原創
2023-06-25 17:48:30929瀏覽

隨著網路的日益發展,前端框架也越來越成熟和完善,Vue.js 作為其中的佼佼者,它的組件化開發模式和響應式特性,使得前端開發變得更加快捷、簡單、高效。其中,Directive(指令)是 Vue.js 中十分重要的一個概念和功能,方便使用者擴展 Vue.js 的行為和 DOM 操作,從而實現更豐富和靈活的功能。本文將介紹在 Vue.js 中使用 Directive 實作表格樹的技巧和最佳實務。

一、Directive 概述

Directive(指令)是Vue.js 中一種特殊的標籤,與傳統的HTML 標籤不同,它的作用是用於操作DOM,具有很強的功能和靈活性,可以根據自己的需求去編寫使用。

以Vue.js 自帶的v-if 指令為例,當指定表達式的結果為true 時,根據指令所在的元素標籤會在DOM 樹上建立/更新對應的節點;當指定當表達式的值為false 時,則會將對應節點從DOM 樹上移除。這便是 Directive 的基本使用方式。

二、表格樹的實作

表格樹是在表格中以樹狀結構展示的數據,它是一種常見的數據展示方式。在實作表格樹的過程中,我們可以使用 Vue.js 中的指令來實作。

在 Directive 中,有兩個比較重要的概念,一個是鉤子函數(Hook Function),另一個是 dom 元素操作(DOM Operation)。

鉤子函數以生命週期函數為代表,對於大多數 DOM 操作的實作而言,主要包括 bind、inserted、update、componentUpdated 和 unbind 這五個函數。其中,bind 函數會在指令綁定到元素上時執行,inserted 函數會在元素插入到父節點中時執行,update 函數會在元素更新時執行,componentUpdated 函數會在元件更新完畢後執行,unbind 函數會在指令被解綁時執行。

DOM 元素操作是指在指令中,我們可以直接操作 DOM 元素,以實現自己想要的功能。包括 createElement、appendChild、removeChild、classList.add 等操作。

接下來,我們將基於 Directive 的鉤子函數和 DOM 元素操作,來詳細解析在 Vue.js 中實作表格樹的具體實作步驟。

(1)數據準備

首先,我們需要準備一組數據,用於儲存表格樹的所有數據,並在後續的操作中對它進行操作和更新。

const data = [{
    id: 1,
    name: 'Parent 1',
    children: [{
      id: 2,
      name: 'Child 1 of Parent 1'
    }, {
      id: 3,
      name: 'Child 2 of Parent 1',
      children: [{
        id: 4,
        name: 'Child 1 of Child 2 of Parent 1'
      }]
    }]
  },
  {
    id: 5,
    name: 'Parent 2'
  }
]

(2)directive 的定義

接下來,我們需要定義一個名為table-tree 的Directive,並根據指令的生命週期函數,在不同的環節進行具體的DOM 操作。

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>Name</th>
        </tr>
      </thead>
      <tbody>
        <tr 
          v-for="node in treeData" 
          v-table-tree:node="{node: node, level: 0}" 
          :class="{'tree-row': node.hasChildren}" 
          :key="node.id">
          <td>{{node.id}}</td>
          <td>{{node.name}}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  directives: {
    'table-tree': {
      bind: function (el, binding) {
        const table = el.querySelector('table') // 获取 table 元素
        const {node} = binding.value
        const childNodes = node.children
        if (childNodes && childNodes.length) {
          const parentTr = el.querySelector(`[key="${node.id}"]`) // 获取当前节点对应的 tr 元素
          const trLength = parentTr.querySelectorAll('td').length // 获取 tr 中子 td 的数量
          const td = document.createElement('td')
          td.setAttribute('colspan', trLength)
          td.innerHTML = '<div class="tree-content"></div>'
          parentTr.appendChild(td) // 增加一个 td 元素,用于放置下一级节点
          const childTable = document.createElement('table') // 新增一个 table 元素,用于放置下一级节点的数据
          td.querySelector('.tree-content').appendChild(childTable)

          childNodes.forEach((child) => { // 递归处理下一级节点
            child.hasChildren = !!child.children
            const tr = document.createElement('tr')
            tr.setAttribute('key', child.id)
            tr.classList.add('tree-child-row')
            childTable.appendChild(tr)
            const td = document.createElement('td')
            td.innerHTML = child.name
            td.classList.add('tree-child-content')
            tr.appendChild(td)
            if (child.children) {
              const innerTd = document.createElement('td')
              tr.appendChild(innerTd)
              const innerTable = document.createElement('table')
              innerTable.setAttribute('class', 'tree-inner-table')
              innerTd.appendChild(innerTable)
              this.$options.directives['table-tree'].bind(innerTable, {value: {node: child, level: binding.value.level + 1}})
            }
          })
        }
      },
      unbind: function(el, binding) {
      }
    }
  },
  props: {
    treeData: {
      type: Array,
      required: true
    }
  }
}
</script>

<style>
.tree-row .tree-content:before {
  content: '';
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 5px;
  vertical-align: middle;
  background-image: url('expanding-arrow.png'); /* 展开箭头图标 */
  background-repeat: no-repeat;
  background-position: center center;
}
.tree-row:not(.expanded) .tree-content:before {
  transform: rotate(-90deg);
}
.tree-row.expanded .tree-content:before {
  transform: rotate(0);
}
.tree-child-row {
  display: none;
}
.tree-row.expanded ~ .tree-child-row {
  display: table-row;
}
</style>

(3)效果顯示

自此,我們就完成了實作表格樹的全部操作。具體的效果展示,可以參考下面的截圖。

7a0b225dd9c9df367c35091251dd1aac

#三、總結

本文主要介紹了在Vue.js 中使用directive 實作表格樹的技巧和最佳實務。透過鉤子函數和 DOM 元素操作,我們可以方便的獲取 DOM 元素以及對 DOM 元素進行操作,實現我們所期望的功能。同時,Vue.js 的 directive 功能,也為我們提供了極大的靈活性和擴展性,可以根據個人需求進行客製化開發。

以上是Vue 中使用 directive 實作表格樹的技巧及最佳實踐的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn