Vue 遞歸組件(構建樹形菜單)

對於一些有規律的DOM結構,若是咱們再一遍遍的編寫一樣的代碼,顯然代碼是比較繁瑣和不科學的,並且本身的工做量會大大增長,git

那麼有沒有一種方法來解決這個問題呢?docker

答案是確定的,咱們能夠經過 遞歸 方式來生成這個結構,固然在 Vue 模板中也是能夠實現的,咱們能夠在 Vue 的組件中調用本身自己,這樣就能達到目的。bash

固然,在 Vue 中,組件能夠遞歸的調用自己,可是有一些條件:架構

  • 該組件必定要有 name 屬性
  • 要確保遞歸的調用有終止條件,防止內存溢出

爲了方便理解遞歸組件,我寫了一個小小的 Demo:組件化

下面有這樣一個數據,咱們但願把它作成一個文件樹同樣的結果:ui

treeData: {
        title: "Web全棧架構師",
        children: [
          {
            title: "Java架構師"
          },
          {
            title: "JS高級",
            children: [
              {
                title: "ES6"
              },
              {
                title: "動效"
              }
            ]
          },
          {
            title: "Web全棧",
            children: [
              {
                title: "Vue訓練營",
                expand: true,
                children: [
                  {
                    title: "組件化"
                  },
                  {
                    title: "源碼"
                  },
                  {
                    title: "docker部署"
                  }
                ]
              },
              {
                title: "React",
                children: [
                  {
                    title: "JSX"
                  },
                  {
                    title: "虛擬DOM"
                  }
                ]
              },
              {
                title: "Node"
              }
            ]
          }
        ]
      }
複製代碼

先寫一個樹組件(Item):this

<template>
  <li>
    <!-- 點擊摺疊展開 -->
    <div @click="toggle">
      <!-- 顯示內容 -->
      {{model.title}}
      <!-- 顯示摺疊展開的圖標,若是沒有下級目錄的話,則不顯示 -->
      <span v-if="isFolder">[{{open?'-':'+'}}]</span>
    </div>
    <!-- 控制是否顯示下級目錄 -->
    <ul v-show="open" v-if="isFolder">
      <!-- 重點代碼,調用自身,實現遞歸,綁定數據 -->
      <Item v-for="model in model.children" :model="model" :key="model.title"></Item>
    </ul>
  </li>
</template>
<script>
export default {
  name: "Item",
  // 若是想使用此組件,則須要傳遞的數據
  props: {
    model: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      // 默認不顯示下級目錄
      open: false
    };
  },
  computed: {
    // 控制是否有下級目錄和顯示下級目錄
    isFolder() {
      return this.model.children && this.model.children.length;
    }
  },
  methods: {
    // 點擊摺疊展開的方法
    toggle() {
      if (this.isFolder) {
        this.open = !this.open;
      }
    }
  }
};
</script>
複製代碼

具體代碼的功能已在上面註釋spa

再次強調,這個組件必需要含有 name 這個屬性,若是沒有 name 這個屬性會形成控件自身不能調用自身,並且調用的時候最好綁定一個 key 值,由於這個 key 值是惟一的標識code

另外須要注意,當遞歸組件的時候,須要有一個條件來終止遞歸,在這裏使用 v-for 隱形條件終止遞歸component

而後在外部組件引入這個組件,並綁定數據使用,以下:

<template>
  <div>
    <ul>
      <!-- 使用這個組件,並綁定數據 -->
      <Item :model="treeData"></Item>
    </ul>
  </div>
</template>
<script>
// 導入遞歸組件
import Item from "./views/Item";
export default {
  name: "App",
  data() {
    return {
      // 須要實現遞歸的數據,上面已經給出
      treeData: {...
      }
    };
  },
  components: {
    // 註冊組件
    Item
  }
};
</script>
複製代碼

上面的代碼已經實現了一個遞歸樹形結構了,展現效果以下:

圖片加載失敗!

後面是 + 號 的能夠點擊展開,是 - 號 的能夠點擊摺疊

雖然這篇博客看起來很簡單,只是一個小的知識點,可是Vue的遞歸組件確實是一個很是強大的功能。能夠用來實現一些相似文件樹、部門樹、級聯選擇這樣的組件,在實際業務開發中這些組件也常常用到,仍是很是重要的~


^_<

相關文章
相關標籤/搜索