2

前言

近期移动端项目中遇到个需求,数据需要树形显示。找了一些插件觉得不太适合,就看了看相关文章以及视频,想着以学习和积累的态度,就自己封装了个tree的树形展示组件。学习到了组件在它的模板内可以递归地调用自己,直接上代码吧~

子组件代码

<template>
  <div class="experTree">
    <ul v-for="item in data" :key="item.name">
      <li class="experTree_info">
        <div class="experTree_bar" @click="onOpenHandler">
          <img
            v-if="isHaschildren(item)"
            src="@/assets/images/expert-right.png"
            alt=""
            class="icon"
            :class="on_off ? 'vertical' : 'normal'"
          />
          <div v-if="!isHaschildren(item)" class="icon"></div>
          <span> {{ item[label] }} </span>
        </div>
        <div class="experTree_select" @click="onSelectHandler(item)">选择</div>
      </li>
       <exper-tree
        v-show="on_off"
        v-if="isHaschildren(item)"
        :data="item[children]"
        :defaultProps="defaultProps"
        @onSelectHandler="onSelectHandler"
      ></exper-tree>
    </ul>
  </div>
</template>

<script>
export default {
  name: "experTree",
  props: {
    data: {
      type: [Object, Array],
      required: true
    },
    defaultProps: {
      type: Object,
      default: () => {
        return {
          children: "children",
          label: "label"
        };
      }
    }
  },
  data() {
    return {
      on_off: false
    };
  },
  computed: {
    label() {
      return this.defaultProps.label;
    },
    children() {
      return this.defaultProps.children;
    },
    isHaschildren() {
      return data => {
        return data[this.children] && data[this.children].length;
      };
    }
  },
  methods: {
    onOpenHandler() {
      this.on_off = !this.on_off;
    },
    onSelectHandler(item) {
      this.$emit("onSelectHandler", item);
    }
  }
};
</script>

<style lang="scss" scoped>
.anime_time {
  transition: all 0.3s;
}
.dis_flex {
  display: flex;
  align-items: center;
}
.experTree {
  &_info {
    @extend .dis_flex;
    height: 48px;
    justify-content: space-between;
    .experTree_bar {
      @extend .dis_flex;
      height: 100%;
      flex: 1;
      .icon {
        width: 38px;
        height: 38px;
        &.vertical {
          transform: rotate(90deg);
          @extend .anime_time;
        }
        &.normal {
          @extend .anime_time;
        }
      }
    }
    .experTree_select {
      color: $mainColor;
      padding: 5px;
      box-sizing: border-box;
    }
  }
}
</style>

父组件调用

<template>
   <div class="tree-menu">
     <expert-tree
       :data="list"
       :defaultProps="defaultProps"
       @onSelectHandler="onSelectHandler"
     ></expert-tree>
   </div>
</template>

<script>
import expertTree from "./expert_tree.vue";
let list = [
  {
    name: "Web秀",
    children: [
      {
        name: "web前端",
        children: [
          {
            name: "CSS"
          },
          {
            name: "JavaScript"
          },
          {
            name: "Vue"
          },
          {
            name: "小程序"
          },
          {
            name: "Three.js"
          }
        ]
      },
      {
        name: "服务器"
      },
      {
        name: "工具类"
      }
    ]
  },
  {
    name: "今日头条",
    children: [
      {
        name: "图片"
      },
      {
        name: "新闻",
        children: []
      }
    ]
  },
  {
    name: "Angular"
  }
];
export default {
  name: "selectSector",
  components: { expertTree },
  data() {
    return {
      list: [...list],
      defaultProps: {
        children: "children",
        label: "name"
      }
    };
  },
  methods: {
    onSelectHandler(data) {
      console.log(data, "expert_tree");
    }
  }
};
</script>

<style lang="scss" scoped></style>

结尾

有写的不足的地方希望大家多提提意见,目前自己的技术确实不怎么样,希望跟各位大佬多多沟通交流,共同进步。早日跟上各位前辈的步伐~

刘某学前端
4 声望2 粉丝

与其临渊羡鱼,不如退而结网