欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于vue實現多功能樹形結構組件的示例代碼

 更新時間:2024年02月02日 09:09:55   作者:一點一木  
一個優(yōu)雅展示樹形結構數據的 Vue 組件,遞歸渲染每個節(jié)點及其子節(jié)點,支持自定義顏色、文本和布局,通過獨特的樣式巧妙處理不同層級,為用戶打造豐富的視覺盛宴,文中通過代碼給大家介紹的非常詳細,感興趣的同學可以自己動手嘗試一下

核心功能

  • 遞歸渲染:組件可以遞歸地渲染每個節(jié)點及其子節(jié)點,形成樹形結構;
  • 自定義樣式:支持通過傳入的節(jié)點數據自定義節(jié)點顏色和文本;
  • 動態(tài)布局:可以根據傳入的屬性決定節(jié)點是左布局、右布局還是左右布局;
  • 層級顏色:根據節(jié)點的層級顯示不同的顏色。

廢話不多說,我們直接開始!

效果圖:

首先,我們在components文件夾下新建一個組件PathoNode.vue,該組件將負責渲染每個節(jié)點及其子節(jié)點。

其中,LEVEL_COLORS 為不同層級節(jié)點定義了顏色,isLeaf 計算屬性用于判斷當前節(jié)點是否為葉子節(jié)點。

代碼如下:

<template>
  <div class="node-item" :class="{left: isLeft}">
    <div class="node-item_not-leaf" v-if="!isLeaf">
      <div class="node-name" :style="{background: node.color || LEVEL_COLORS[node.level] || LEVEL_COLORS[3]}" :class="{'round': node.level === 2}">{{node.text}}</div>
      <div class="node-children">
        <patho-node v-for="(childNode, i) in node.children" :key="'childNode' + i" :node="childNode" :isLeft="isLeft"/>
      </div>
    </div>
    <div class="node-item_leaf" v-else>
      <div class="node-name">{{node.text}}</div>
    </div>
  </div>
</template>
?
<script>
const LEVEL_COLORS = {
  1: '#1A4843',
  2: '#464885',
  3: '#46857E',
  4: '#857146',
  5: '#6A8546',
  6: '#854646',
  7: '#818076',
  8: '#979B33',
  9: '#336E9B',
  10: '#854683'
}
export default {
  name: 'PathoNode',
  props: {
    node: {
      type: Object,
      default () {
        return {}
      }
    },
    isLeft: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      LEVEL_COLORS
    }
  },
  computed: {
    isLeaf () {
      return !(this.node.children && this.node.children.length > 0)
    }
  },
  methods: {
?
  }
}
</script>
?
<style lang="scss" scoped>
$border-color-primary: #B5BDC4;
$text-color-primary: #b4babf;
$color-black: #000000;
@mixin firstNode {
  position: relative;
  border: none;
}
@mixin rightNode {
  position: relative;
  padding-left: 10px;
  border-left: 1px solid $border-color-primary;
}
@mixin leftNode {
  position: relative;
  padding: 0;
  padding-right: 10px;
  border: none;
  border-right: 1px solid $border-color-primary;
}
@mixin rightHorizonLine {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 10px;
  border-top: 1px solid $border-color-primary;
}
@mixin leftHorizonLine {
  @include rightHorizonLine;
  left: auto;
  right: 0;
}
@mixin beforeRightFirstChild {
  bottom: 0;
  border-radius: 4px 0 0 0;
  border-left: 1px solid $border-color-primary;
}
@mixin beforeRightLastChild {
  left: 0;
  top: 0;
  bottom: 50%;
  border-radius: 0 0 0 4px;
  border: none;
  border-left: 1px solid $border-color-primary;
  border-bottom: 1px solid $border-color-primary;
}
// 左邊第一個child
@mixin beforeLeftFirstChild {
  @include beforeRightFirstChild;
  border: none;
  border-radius: 0 4px 0 0;
  border-top: 1px solid $border-color-primary;
  border-right: 1px solid $border-color-primary;
}
// 左邊最后一個child
@mixin beforeLeftLastChild {
  @include beforeRightLastChild;
  border-radius: 0 0 4px 0;
  border: none;
  border-right: 1px solid $border-color-primary;
  border-bottom: 1px solid $border-color-primary;
}
@mixin beforeRightOnlyOneChild {
  left: 0;
  top: 50%;
  bottom: auto;
  border: 0;
  border-radius: 0;
  border-top: 1px solid $border-color-primary;
}
@mixin beforeLeftOnlyOneChild {
  @include beforeRightOnlyOneChild;
  left: auto;
  right: 0;
}
.node-item {
  display: flex;
  position: relative;
  flex-direction: row;
  justify-content: flex-start;
  @include rightNode;
  &::before{
    @include rightHorizonLine;
  }
  &:first-child{
   @include firstNode;
    &::before{
      @include beforeRightFirstChild;
    }
  }
  &:last-child{
    border-left: none;
    &::before{
      @include beforeRightLastChild;
    }
  }
  &:first-child:last-child{
    border-left: none;
  }
  &:first-child:last-child::before{
    @include beforeRightOnlyOneChild;
  }
  .node-name{
    flex-shrink: 0;
    display: inline-block;
    font-size: 14px;
    border-radius: 1px;
    margin: 10px 0;
    padding: 5px 20px;
    width: auto;
    line-height: 20px;
    font-weight: 600;
    height: auto;
    border-radius: 3px;
    color: $color-black;
    &.round{
      width: 64px;
      height: 64px;
      padding: 0;
      border-radius: 50%;
      line-height: 64px;
      text-align: center;
    }
  }
  .node-children{
    @include rightNode;
    border-left: none;
    &::before{
      @include rightHorizonLine;
    }
  }
  .node-item_not-leaf{
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    &::before{
      border-left: 1px solid $border-color-primary;
    }
  }
  .node-item_leaf{
    .node-name{
      background: $color-black;
      color: $text-color-primary;
      border: 1px solid $text-color-primary;
      margin-right: 20px;
    }
  }
  &.left{
    @include leftNode;
    &::before{
      @include leftHorizonLine;
    }
    &:first-child{
      @include firstNode;
    }
    &:first-child::before{
      @include beforeLeftFirstChild;
    }
    &:last-child{
      border: none;
      &::before{
        @include beforeLeftLastChild;
      }
    }
    &:first-child:last-child{
      border-right: none;
    }
    &:first-child:last-child::before{
      @include beforeLeftOnlyOneChild;
    }
    .node-item_not-leaf{
      &::before{
        border: none;
        border-right: 1px solid $border-color-primary;
      }
    }
    .node-name{
      &::after{
        content: '\200E';
      }
    }
    .node-children{
      @include leftNode;
      border-right: none;
      &::before{
        @include leftHorizonLine;
      }
    }
    .node-item_leaf{
      .node-name{
        margin-right: 0;
        margin-left: 20px;
      }
    }
  }
  // transition
  .node-fade-enter-acitve, .node-fade-leave-active {
    transition: all .5s;
  }
  .node-fade-enter, .node-fade-leave-to{
    opacity: 0;
  }
  .node-fade-enter-to, .node-fade-leave {
    opacity: 1;
  }
}
</style>

節(jié)點組件部分負責定義單個節(jié)點的渲染結構,并通過遞歸調用<patho-node>組件處理子節(jié)點。當然,根據具體業(yè)務需求,你也可以進一步封裝此文件成為專用的業(yè)務組件。

<template>
  <div class="patho-tab" ref="pathoChartContainer">
    <div class="patho-tab__zoom" @click="clickHandler">
      <el-scrollbar style="height:100%; width:100%;">
        <transition name="patho-chart">
          <div class="patho-chart" :style="{ transform: `scale(${scaleRatio}) translate(${translateX}px, ${translateY}px)` }">
            <div class="patho-chart__section patho-chart__section_left" v-if="leftDatas.length > 0">
              <patho-node v-for="(node, i) in leftDatas" :key="'node' + i" :node="node" :isLeft="true" />
            </div>
            <div class="patho-chart__section patho-chart__section_center root-node" v-if="nodeData">{{ nodeData.text }}
            </div>
            <div class="patho-chart__section patho-chart__section_right " v-if="rightDatas.length > 0">
              <patho-node v-for="(node, i) in rightDatas" :key="'node' + i" :node="node" :isLeft="false" />
            </div>
          </div>
        </transition>
      </el-scrollbar>
    </div>
  </div>
</template>
<script>
import pathoNode from '@/components/PathoNode.vue'
export default {
  components: {
    pathoNode
  },
  data() {
    return {
      scaleRatio: 1,
      translateX: 0,
      translateY: 0,
      // 組織結構圖數據
      nodeData: {
        "text": "綜合分析",
        "color": null,
        "level": 1,
        "children": [
          {
            "text": "血",
            "color": "#9BBA5B",
            "level": 2,
            "children": [
              {
                "text": "活血化瘀",
                "color": null,
                "level": 3,
                "children": [
                  {
                    "text": "岷歸",
                    "color": null,
                    "level": 4,
                    "children": null
                  }
                ]
              }
            ]
          },
          {
            "text": "汗",
            "color": "#C58080",
            "level": 2,
            "children": [
              {
                "text": "固澀_止汗",
                "color": null,
                "level": 3,
                "children": [
                  {
                    "text": "白芍",
                    "color": null,
                    "level": 4,
                    "children": null
                  },
                  {
                    "text": "于朮",
                    "color": null,
                    "level": 4,
                    "children": null
                  }
                ]
              }
            ]
          }
          // ...
        ]
      }
    }
  },
  computed: {
    leftDatas() {
      const children = this.nodeData.children || []
      const len = children.length
      return children.slice(0, Math.floor(len / 2))
    },
    rightDatas() {
      const children = this.nodeData.children || []
      const len = children.length
      return children.slice(len / 2)
    }
  },
  methods: {
    clickHandler() {
      if (this.scaleRatio === 1) {
        this.scaleRatio = 1.2;
      } else {
        this.scaleRatio = 1;
      }
    }
  }
}
</script>
<style lang="scss" scoped>
$border-color-primary: #B5BDC4;
$color-primary: #49B8A3;
$color-black: #000000;
?
@mixin rightHorizonLine {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 10px;
  border-top: 1px solid $border-color-primary;
}
?
@mixin leftHorizonLine {
  @include rightHorizonLine;
  left: auto;
  right: 0;
}
?
.patho-tab {
  display: flex;
  flex-direction: column;
  height: 100%;
  position: relative;
?
  &__body {
    user-select: none;
    overflow: hidden;
    flex-grow: 1;
  }
?
  .patho-chart {
    position: relative;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin: 0 auto;
    padding: 2em 0;
    width: max-content;
    cursor: pointer;
?
    .patho-chart__section {
      display: flex;
      flex-direction: column;
      flex-shrink: 0;
      flex-basis: auto;
?
      &.patho-chart__section_right {
        position: relative;
        padding: 0 0 0 10px;
?
        &::before {
          @include rightHorizonLine
        }
      }
?
      &.patho-chart__section_left {
        position: relative;
        direction: rtl;
        text-align: left;
        justify-content: flex-end;
        padding: 0 10px 0 0;
?
        &::before {
          @include leftHorizonLine;
        }
      }
    }
?
    .root-node {
      width: 90px;
      height: 90px;
      border-radius: 50%;
      background: #1A4843;
      color: $color-black;
      font-size: 16px;
      font-weight: 600;
      color: $color-primary;
      text-align: center;
      line-height: 90px;
    }
  }
}
?
/deep/ .el-scrollbar__view {
  min-height: 100%;
}
?
.patho-tab__zoom {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.8);
  user-select: none;
  z-index: 100;
?
  .patho-chart {
    margin: 0;
    transform-origin: 0 0;
  }
}
?
.patho-tab__no-datas {
  margin-top: 20%;
  text-align: center;
?
  &_icon {
    width: 200px;
  }
?
  &_text {
    @include noDatas;
  }
}
?
.patho-chart-enter-active,
.patho-chart-leave-active {
  transition: opacity .5s;
}
?
.patho-chart-enter,
.patho-chart-leave-to {
  opacity: 0;
}
?
.patho-chart-enter-to,
.patho-chart-leave {
  opacity: 1;
}
</style>

通過以上設計,我們成功打造了一個多功能的樹形結構組件,具備豐富的自定義選項,涵蓋節(jié)點顏色、文本和布局等方面。這樣的組件不僅能夠實現功能性的樹形結構展示,同時為用戶提供了生動多彩的視覺體驗。

以上就是基于vue實現多功能樹形結構組件的示例代碼的詳細內容,更多關于vue多功能樹形結構組件的資料請關注腳本之家其它相關文章!

相關文章

  • 淺談vue中所有的封裝方式總結

    淺談vue中所有的封裝方式總結

    因為現在vue的流行,vue的各種插件都出來了,我們公司也是使用vue做項目,那么應該如何封裝,本文就介紹一下如何封裝,感興趣的可以了解一下
    2021-07-07
  • 解決vue同一slot在組件中渲染多次的問題

    解決vue同一slot在組件中渲染多次的問題

    今天小編就為大家分享一篇解決vue同一slot在組件中渲染多次的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • 詳解Vue CLI 3.0腳手架如何mock數據

    詳解Vue CLI 3.0腳手架如何mock數據

    這篇文章主要介紹了詳解Vue CLI 3.0腳手架如何mock數據,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • vue3-print-nb實現頁面打印(含分頁打印)示例代碼

    vue3-print-nb實現頁面打印(含分頁打印)示例代碼

    大多數后臺系統(tǒng)中都存在打印的需求,在有打印需求時,對前端來說當然是直接打印頁面更容易,下面這篇文章主要給大家介紹了關于vue3-print-nb實現頁面打印(含分頁打印)的相關資料,需要的朋友可以參考下
    2024-01-01
  • Vue.js路由vue-router使用方法詳解

    Vue.js路由vue-router使用方法詳解

    這篇文章主要為大家詳細介紹了Vue.js路由vue-router使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • vue 手機物理監(jiān)聽鍵+退出提示代碼

    vue 手機物理監(jiān)聽鍵+退出提示代碼

    這篇文章主要介紹了vue 手機物理監(jiān)聽鍵+退出提示代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • vue-cli 關閉熱更新操作

    vue-cli 關閉熱更新操作

    這篇文章主要介紹了vue-cli 關閉熱更新操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • vue使用$store.commit() undefined報錯的解決

    vue使用$store.commit() undefined報錯的解決

    這篇文章主要介紹了vue使用$store.commit() undefined報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Vue中父子組件通訊之todolist組件功能開發(fā)

    Vue中父子組件通訊之todolist組件功能開發(fā)

    這篇文章主要介紹了Vue中父子組件通訊——todolist組件功能開發(fā)的相關知識,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-05-05
  • 解決vue的component標簽渲染問題

    解決vue的component標簽渲染問題

    這篇文章主要介紹了解決vue的component標簽渲染問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論