vue组件横向树实现代码

实现一个 vue 组件横向树需要以下步骤:

第一步:安装依赖

横向树的实现需要使用到 d3 (Data-Driven Documents) 库,而在 Vue 中使用 d3 需要先安装依赖。可以通过 npm 来安装:

npm install d3@5.15.0

对于 Vue 项目,可以在 main.js 中引入 d3 库,以便在整个项目中使用:

import * as d3 from "d3";
Vue.prototype.$d3 = d3;

第二步:实现组件

实现横向树的核心代码是在组件中编写的。下面是一个示例:

<template>
  <div class="tree-diagram">
    <svg :width="width" :height="height">
      <g :transform="'translate(' + margin.left + ',' + margin.top + ')'">
        <template v-if="data">
          <rect class="background" :width="treeWidth" :height="treeHeight" @click.stop=""></rect>
          <g :transform="'translate(' + paddingLeft + ',' + paddingTop + ')'">
            <TreeNode
              :node="data"
              :level="1"
              :height="height"
              :width="width"
              :nodeWidth="nodeWidth"
              :nodeHeight="nodeHeight"
              :linkStrokeWidth="linkStrokeWidth"
              :linkStrokeColor="linkStrokeColor"
              :nodeFillColor="nodeFillColor"
              :nodeTextColor="nodeTextColor"
              @node-clicked="onNodeClicked"
            ></TreeNode>
          </g>
        </template>
        <template v-else>
          <text>No Data</text>
        </template>
      </g>
    </svg>
  </div>
</template>
<script>
import TreeNode from "./TreeNode.vue";

export default {
  name: "TreeDiagram",
  components: {
    TreeNode,
  },
  props: {
    data: {
      type: Object,
      default: null,
    },
    width: {
      type: Number,
      default: 800,
    },
    height: {
      type: Number,
      default: 600,
    },
    nodeWidth: {
      type: Number,
      default: 200,
    },
    nodeHeight: {
      type: Number,
      default: 80,
    },
    linkStrokeWidth: {
      type: Number,
      default: 4,
    },
    linkStrokeColor: {
      type: String,
      default: "#666",
    },
    nodeFillColor: {
      type: String,
      default: "#fff",
    },
    nodeTextColor: {
      type: String,
      default: "#000",
    },
  },
  data() {
    return {
      margin: {
        top: 20,
        right: 20,
        bottom: 20,
        left: 20,
      },
    };
  },
  computed: {
    treeWidth() {
      return this.nodeWidth * 2 + this.paddingLeft * 2;
    },
    treeHeight() {
      return this.nodeHeight * 2 + this.paddingTop * 2;
    },
    paddingLeft() {
      return this.nodeWidth * 0.5;
    },
    paddingTop() {
      return this.nodeHeight * 0.5;
    },
  },
  methods: {
    onNodeClicked(node) {
      this.$emit("node-clicked", node);
    },
  },
};
</script>
<style scoped>
.background {
  fill: none;
}

.node {
  font: 10px sans-serif;
  cursor: pointer;
}

.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 1.5px;
}

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 2px;
}
</style>

上面的代码中使用到了 TreeNode 组件,可以通过下面的代码来实现:

<template>
  <g :transform="'translate(' + (node.x - nodeWidth / 2) + ',' + (node.y - nodeHeight / 2) + ')'">
    <rect :width="nodeWidth" :height="nodeHeight" :fill="nodeFillColor"></rect>
    <text :x="nodeWidth / 2" :y="nodeHeight / 2" :dy="nodeHeight * 0.35" :text-anchor="'middle'" :fill="nodeTextColor">
      {{ node.name }}
    </text>
    <template v-if="node.children">
      <g class="children">
        <template v-for="(child, index) in node.children" :key="index">
          <TreeNode
            :node="child"
            :level="(level || 0) + 1"
            :height="height"
            :width="width"
            :nodeWidth="nodeWidth"
            :nodeHeight="nodeHeight"
            :linkStrokeWidth="linkStrokeWidth"
            :linkStrokeColor="linkStrokeColor"
            :nodeFillColor="nodeFillColor"
            :nodeTextColor="nodeTextColor"
            @node-clicked="onNodeClicked"
          ></TreeNode>
        </template>
      </g>
    </template>
  </g>
</template>
<script>
export default {
  name: "TreeNode",
  props: {
    node: {
      type: Object,
      default: null,
      required: true,
    },
    level: {
      type: Number,
      default: null,
    },
    height: {
      type: Number,
      default: 600,
    },
    width: {
      type: Number,
      default: 800,
    },
    nodeWidth: {
      type: Number,
      default: 200,
    },
    nodeHeight: {
      type: Number,
      default: 80,
    },
    linkStrokeWidth: {
      type: Number,
      default: 4,
    },
    linkStrokeColor: {
      type: String,
      default: "#666",
    },
    nodeFillColor: {
      type: String,
      default: "#fff",
    },
    nodeTextColor: {
      type: String,
      default: "#000",
    },
  },
  computed: {
    isRoot() {
      return this.level === 1;
    },
  },
  methods: {
    onNodeClicked() {
      this.$emit("node-clicked", this.node);
    },
  },
};
</script>
<style scoped>
</style>

示例说明

下面是两个示例:

  1. 显示简单数据结构的横向树
<template>
  <TreeDiagram :data="treeData" @node-clicked="onNodeClicked" />
</template>
<script>
import TreeDiagram from "./TreeDiagram.vue";

export default {
  name: "App",
  components: {
    TreeDiagram,
  },
  data() {
    const treeData = {
      name: "rootNode",
      children: [
        {
          name: "childNode1",
        },
        {
          name: "childNode2",
        },
      ],
    };

    return {
      treeData,
    };
  },
  methods: {
    onNodeClicked(node) {
      console.log("Node Clicked: ", node);
    },
  },
};
</script>
  1. 显示复杂数据结构的横向树
<template>
  <TreeDiagram :data="treeData" />
</template>
<script>
import TreeDiagram from "./TreeDiagram.vue";

const data = {
  name: "flare",
  children: [
    {
      name: "data",
      children: [
        {
          name: "converters",
          children: [
            { name: "Converters", value: 721 },
            { name: "DelimitedTextConverter", value: 4294 },
          ],
        },
      ],
    },
    {
      name: "display",
      children: [
        { name: "DirtySprite", value: 8833 },
        {
          name: "LineSprite",
          children: [
            { name: "Arrows", value: 841 },
            { name: "LineSprite", value: 1769 },
          ],
        },
      ],
    },
  ],
};

export default {
  name: "App",
  components: {
    TreeDiagram,
  },
  data() {
    return {
      treeData: data,
    };
  },
};
</script>

参考文献:

  1. vue 组件横向树实现 https://www.jianshu.com/p/694a99d50de3
  2. D3.js https://d3js.org/

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue组件横向树实现代码 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • vue-cli2.9.3 详细教程

    Vue CLI2.9.3 详细教程 Vue CLI2.9.3 是一个由 Vue 官方提供的命令行工具,用于快速搭建基于 Vue.js 的项目和 SPA 应用,可根据用户的选择预设一套规范的项目目录结构、开发规范、自动化构建及相关依赖库等。本教程将详细介绍如何使用 Vue CLI2.9.3 进行项目搭建以及配置。 安装 Vue CLI 命令行工具 首先,需要使…

    Vue 2023年5月27日
    00
  • Vue实现导航栏菜单

    我会为您详细讲解如何使用Vue实现导航栏菜单。 1. 确定导航栏菜单数据格式 首先我们需要确定导航栏菜单的数据格式,一般而言可以使用以下格式: menuList: [ { name: ‘Home’, path: ‘/’, icon: ‘el-icon-menu’ }, { name: ‘Service’, path: ‘/service’, icon: ‘e…

    Vue 2023年5月27日
    00
  • Vue基础之侦听器详解

    Vue基础之侦听器详解 在Vue中,我们可以通过侦听器来监听组件内部数据的变化并做相应的处理。侦听器可以观察数据的变化并在变化时执行一些操作。在本篇文章中,我们将深入探讨Vue的侦听器,包括如何定义侦听器,侦听器的使用场景以及一些示例。 定义侦听器 我们可以在Vue组件内定义侦听器,在组件的watch选项中添加需要侦听的数据和相应的处理函数即可。定义侦听器的…

    Vue 2023年5月27日
    00
  • vue3中的watch和watchEffect实例详解

    Vue3中的watch和watchEffect实例详解 在Vue3中,watch和watchEffect可以定义响应式数据的副作用。本文会详细讲解两者的区别和使用方式,并给出几个实例示例说明。 watch watch的基本用法是:当数据发生变化时执行一个函数。可以用来监听单个数据的变化,也可以监听多个数据。 监听单个数据 监听单个数据可以通过$watch函数…

    Vue 2023年5月27日
    00
  • 浅谈webpack性能榨汁机(打包速度优化)

    我来详细讲解一下“浅谈webpack性能榨汁机(打包速度优化)”的完整攻略。 一、前言 在现在的前端开发中,使用Webpack打包已成为主流,但是Webpack打包速度的问题一直都是众多开发者关注的重点。本文将从Webpack的优化策略和实战两个方面来为大家讲解如何优化Webpack的打包速度。 二、Webpack的优化策略 尽可能少地使用loader 在W…

    Vue 2023年5月28日
    00
  • vue中 v-for循环的用法详解

    Vue中v-for循环的用法详解 在Vue中,v-for是一种指令,用于循环渲染数据列表。本篇攻略将详细讲解Vue中v-for的用法。 基本用法 v-for指令需要用在具有多个子节点的元素上,它的语法格式为: <div v-for="(item, index) in items" :key="index">…

    Vue 2023年5月27日
    00
  • Vue使用video标签实现视频播放

    下面我将详细讲解“Vue使用video标签实现视频播放”的完整攻略。 概述 想要在 Vue 中使用 video 标签实现视频播放,需要用到 Vue 的指令和事件等相关知识,以下是实现过程的具体步骤。 步骤 1. 安装和引入 video.js video.js 是一个现代化的视频播放器,它可以帮助我们轻松地实现视频播放功能。我们需要安装它并在 Vue 中引入:…

    Vue 2023年5月28日
    00
  • Vue2.0实现购物车功能

    Vue2.0实现购物车功能的攻略可以分为以下几个步骤: 第一步:创建一个Vue实例 首先,我们需要在页面上引入Vue.js的库文件,并创建一个Vue实例。 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id=…

    Vue 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部