Понимать рекурсивные компоненты Vue и реализовывать экземпляры элементов управления Tree~

Vue.js

Подумав два дня, я был готов реализовать управление деревом на основе vue по образцу ant-design-vue. Он в основном использует идею рекурсивных компонентов Vue и использование полей ввода типа CheckBox.

нужно

  • Возможность генерировать каталог дерева из входящих данных Json.
  • Возможность инициализировать выбранные узлы.
  • Узлы можно выбирать вручную, и, наконец, все выбранные узлы можно распечатать.
  • Возможность отключать узлы при инициализации.
  • Возможность свернуть дерево каталогов.
  • Измените собственный стиль CheckBox.

Пример скриншота

Завершенный элемент управления деревом выглядит следующим образом: нажмите, чтобы получить выбранный ключ узла, и все выбранные узлы появятся во всплывающем окне:

在这里插入图片描述

Рука об руку

Понимание рекурсивных компонентов Vue

В документации vue (Talent.v UE JS.org/V2/expensive/co…

  • Компоненты имеют атрибут имени
  • Рекурсивные вызовы должны быть условными

Базовый элемент управления деревом tree.vue создается в соответствии с приведенными выше инструкциями:

Глобальные переменные: global.js

При написании компонента для получения содержимого узла обнаруживается, что, поскольку он является рекурсивным компонентом, нелегко выбрать узел на каждом уровне. Поэтому создайте здесь глобальную переменную global.js для записи всех выбранных узлов. Также легко удалять и присоединять узлы. По умолчанию выбраны следующие узлы:

const nodes = ['1', '1-1', '1-1-2', '1-2-2']

export default {
  nodes
}

После написания его нужно смонтировать на main.js.

import global from 'common/js/global'
Vue.prototype.$global = global

Базовый компонент (рекурсивный компонент): tree.vue

Примечание: нет необходимости использовать атрибут компонентов, чтобы объявить себя здесь.С помощью атрибута имени вы можете вызвать значение имени компонента непосредственно в шаблоне.

<template>
  <ul class="ul-wrapper">                                    <!-- 包裹层-->
    <li v-for="item in list" :key="item.key">                <!-- 遍历-->
      <div>                                                  <!-- 是否展开图标-->
          <img class="icon"
            v-show="item.children"
            @click="changeShow"
            :src="require(`../common/images/${imgUrl}`)"
          >                                                  <!-- CheckBox-->
        <input
          type="checkbox"
          :name="item.key"
          @click="clickbox"
          :checked="isChecked(item.key)"
          :disabled="item.disabled"
        >
        <div class="checkbox-title">{{item.title}}</div>      <!-- CheckBox内容-->
      </div>
      <tree v-if="showChildren" :list="item.children"></tree> <!-- 遍历children-->
    </li>
  </ul>
</template>

<script type='text/ecmascript-6'>
export default {
  name: 'tree',
  props: {
    list: { // 所有树节点
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data () {
    return {
      showChildren: true // 是否展开根目录
    }
  },
  computed: { // computed属性计算展开图标
    imgUrl () {
      return this.showChildren ? 'down.png' : 'right.png'
    }
  },
  methods: {
    clickbox (e) { // 点击CheckBox时需要加入或删除已选中this.$global.nodes的节点数组中
      const checked = e.target.checked
      const key = e.target.name
      const nodes = this.$global.nodes // this.$global.nodes是全局变量,便于递归组件记录选中节点
      if (checked) {
        if (!nodes.includes(key)) {
          this.$global.nodes.push(key)
        }
      } else {
        this.$global.nodes = nodes.filter((item) => {
          return key !== item
        })
      }
    },
    changeShow () { // 点击是否展开根目录,当前状态取反即可
      this.showChildren = !this.showChildren
    },
    isChecked (key) { // 查看是否已经存在于选中节点中
      return this.$global.nodes.includes(key)
    }
  }
}
</script>

<style lang="stylus">
.ul-wrapper                            // ul包裹层,每层需要向右偏移30px
  margin 10px 30px 0
  .checkbox-title, .icon
    display inline-block
    vertical-align middle
  .icon
    margin-left -20px
    height 18px
    width 18px

input[type="checkbox"]                  // CheckBox样式修改
  position relative
  display inline-block
  vertical-align middle
  padding 0
  margin-right 5px
  height 18px
  width 18px
  border 1px solid #ccc
  border-radius 3px
input[type="checkbox"]:checked::before // CheckBox选中状态时样式修改
  position absolute
  top 0
  left 0
  padding-left 2px
  content: "\2713";
  height 15px
  width 13px
  font-size 12px
  font-weight: bold;
  background #1296db
  color #fff
  border-radius 3px
  border 0
input[type="checkbox"]:disabled::before // CheckBox禁用状态时样式修改
  position absolute
  top 0
  left 0
  padding-left 2px
  content: "";
  height 15px
  width 13px
  font-size 12px
  font-weight: bold;
  background #ccc
  color #fff
  border-radius 3px
  border 0
</style>

Компонент приложения tree-apply.vue

<template>
  <div class="tree-wrapper">
    <div class="btn" @click="showNodes">
      点击获取选中节点key
    </div>
    <Tree :list="treeData"></Tree>
  </div>
</template>

<script type='text/ecmascript-6'>
import Tree from 'base/tree'
export default {
  data () {
    return {
      treeData: []  // 全部节点
    }
  },
  created () {
    this.getData()
  },
  methods: {
    getData () {
      this.axios.get('/tree').then((res) => { // 获取mock数据
        this.treeData = res.data
      })
    },
    showNodes () {
      alert(this.$global.nodes)
    }
  },
  components: {
    Tree
  }
}
</script>

<style lang="stylus">
.btn
  margin 20px
  text-align center
</style>

макет данных tree.json

Здесь используется метод имитации данных, конкретное использование mock упоминается в моей последней статье «better-scroll реализует компонент карусели»:blog.CSDN.net/QQ_39083496…

  • Отключение CheckBox определяется в соответствии с «отключено»: «истинно».
  • title (обязательно) — отображаемое имя ярлыка.
  • Ключ (must) — это настоящее ключевое слово, под которым понимается обязательное поле для окончательной отправки.
[{
    "title": "1",
    "key": "1",
    "children": [
        {
            "title": "1-1",
            "key": "1-1",
            "children": [
                { "title": "1-1-1", "key": "1-1-1" },
                { "title": "1-1-2", "key": "1-1-2" },
                { "title": "1-1-3", "key": "1-1-3" }
            ]
        }, 
        {
            "title": "1-2",
            "key": "1-2",
            "children": [
                { "title": "1-2-1", "key": "1-2-1" },
                { "title": "1-2-2", "key": "1-2-2" },
                { "title": "1-2-3", "key": "1-2-3" }
            ]
        }, 
        {
            "title": "1-3",
            "key": "1-3"
        }
    ]
  }, 
  {
    "title": "2",
    "key": "2",
    "disabled": "true",
    "children": [
        { "title": "2-1", "key": "2-1" },
        { "title": "2-2", "key": "2-2" },
        { "title": "2-3", "key": "2-3" }
    ]
  }, 
  {
    "title": "3",
    "key": "3"
  }]

интерфейс:

const Mock = require('mockjs')

Mock.mock('/tree', 'get', require('./json/tree.json'))

Суммировать

На этом генерация элемента управления "дерево" завершена, и требования выполнены. Если вы не можете понять приведенный выше фрагмент кода, вы можете найти исходный код на моем github. Добро пожаловать в гости, добро пожаловать в Star~
GitHub.com/GE Involvement-жидкий аммиак/V…

больше рекомендаций