日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue纯手写思维导图,拒绝插件(cv即用)

發(fā)布時間:2024/1/18 vue 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue纯手写思维导图,拒绝插件(cv即用) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

vue純手寫思維導圖,拒絕插件(cv即用)

已完成功能點:折疊、放大、縮小、移動
后續(xù)增加功能點:添加、刪除

先看結果:

有這么個需求,按照層級關系,把表格放在思維導圖上,我第一時間想到用插件,但是找了好久都沒有找到比較合適的插件,決定自己手寫一個

第一步:

理論猜想

模擬一個帶有層級關系的數(shù)據(jù)格式,并且可以在vue組件中需要做成組件遞歸形式,左側父級永遠包含右側子集。左側A盒子,右側F盒子用flex布局B/C/D豎著排列,右側3個div分別用偽元素分別做3根橫線,F盒子設置border-left 豎線,這樣一拼接就感覺像是一個思維導圖了,理論先這樣,但是還沒有想到B盒子的左側橫線和F盒子豎線交叉之后,上面圓圈多余的部分怎么去除。先動手再說,碰到問題再想著怎么處理問題。

第二步:

動手實踐

模擬數(shù)據(jù): 設置listCache 模擬數(shù)據(jù) 帶有層級關系的格式,id是唯一的,這樣做為了后期可能操作表格的時候方便找到唯一的表格。
遞歸組件: mindItem.vue里面的name屬性名稱設置 mindItem,然后再mindItem.vue組件里面再次引入<mindItem :list="item.children"></mindItem>即可遞歸
多余線段去除: 剛開始的做法是直接設置子集的border-left,這樣的問題會造成有線段空出來,顯得很多余,轉換一個思路。

  • 設置B和A的連接:請看圖2 把第一個div的偽元素::after設置border-left: solid 2px blue;height: 50%;bottom: 0; 這樣做是讓線段1向下展示,高度只有B盒子的一半,這樣就感覺像線段拐彎了,從A連接到B的樣式,其實是多個線段拼接起來而已。
  • 設置D和A的連接:請看圖2 把第最后一個div的偽元素::after設置border-left: solid 2px #000; height: 50%; top: 0; 這樣做是讓線段3向上展示,高度只有C盒子的一半,這樣就感覺像線段拐彎了,從A連接到C的樣式,其實是多個線段拼接起來而已。
  • 設置C和A的連接:請看圖2 把中間div的偽元素::after設置border-left: solid 2px yellowgreen; height: 100%; 處在中間地段的div盒子不必考慮線段拐彎問題,高度100%就行了和上下的盒子的線段連接起來就好了

圖2:


src/views/mind/components/mindItem.vue

<template><transition name="el-zoom-in-center"><div class="warps"><template v-for="(item, i) in list"><div:key="i"class="bodyDefault":class="[item.first ? 'bodyOuter' : '',i === 0 ? 'bodyFirst' : list.length - 1 === i ? 'bodyLast' : '',]"><iv-if="!item.first"class="iconremove":class="[!item.isExpandBefore? 'el-icon-remove-outline': 'el-icon-circle-plus-outline',]"type="primary"@click="expendBefore(item)"></i><div class="listTable" v-show="!item.isExpandBefore"><el-table :data="item.tableData" style="width: 300px" border size="small"><el-table-column prop="name" label="姓名" align="center"> </el-table-column><el-table-column prop="age" label="年齡" align="center"> </el-table-column></el-table></div><iv-if="item.children && !item.isExpandBefore"class="iconremove":class="[!item.isExpandAfter? 'el-icon-remove-outline': 'el-icon-circle-plus-outline',]"@click="expendAfter(item)"></i><divv-if="item.children && !item.isExpandAfter && !item.isExpandBefore"class="box transition-box"><mindItem :list="item.children"></mindItem></div></div></template></div></transition> </template><script> import { expendfn } from "./index.js"; export default {name: "mindItem",components: {},props: {list: {type: Array,default: [],},},data() {return {};},computed: {},watch: {list: {deep: true,handler(newVal) {this.list = newVal;},},},created() {},mounted() {},methods: {expendBefore(val) {val.isExpandBefore = !val.isExpandBefore;this.$forceUpdate();console.log("后-expendBefore", val);},expendAfter(val) {val.isExpandAfter = !val.isExpandAfter;this.$forceUpdate();console.log("前-expendAfter", val);},}, }; </script><style scoped lang="less"> .warps {& > .bodyOuter,& > .bodyFirst,& > .bodyLast,& > .bodyDefault {padding: 10px 0 10px 24px;position: relative;border-left: none;.listTable {display: inline-block;display: flex;align-items: center;.expend {width: 10px;height: 100%;// border: 1px solid blue;}}display: flex;align-items: center;.box {flex: 1;margin-left: 30px;display: inline-block;position: relative;}.box::before {content: "";width: 30px;border: solid 1px skyblue;white-space: nowrap;display: inline-block;position: absolute;left: -15px;top: 50%;transform: translate(-50%, -50%);}}& > .bodyFirst::before,& > .bodyOuter::before,& > .bodyLast::before,& > .bodyDefault::before {content: "→";width: 30px;letter-spacing: 2px;white-space: nowrap;display: inline-block;position: absolute;left: 0px;}// 橫線.bodyDefault::before {}.bodyFirst::before {}.bodyLast::before {}.bodyFirst::before {}.bodyOuter::before {content: "";border: solid 1px transparent;}// 豎線& > .bodyFirst::after,& > .bodyDefault::after,& > .bodyOuter::after,& > .bodyLast::after {content: "";width: 2px;height: 50%;border-left: solid 2px transparent;white-space: nowrap;display: inline-block;position: absolute;left: 0px;}& > .bodyDefault::after {border-left: solid 2px red;height: 100%;}& > .bodyFirst::after { border-left: solid 2px yellowgreen;height: 50%;bottom: 0;}& > .bodyLast::after {border-left: solid 2px blue;height: 50%;top: 0;}// 外層.bodyOuter::after {border-left: solid 2px transparent;}// 最外層無線條.bodyOuter {background: transparent;border-left: 2px solid transparent;&.box::before {background: transparent;}}.bodyOuter::before {background: transparent;} }.iconremove {color: #409eff;width: 22px;font-size: 20px;cursor: pointer; } </style>

src/views/mind/mind.vue

<template><div class="warp"><div class="header"><div><el-button type="primary" size="small" @click="expendAll">展開所有</el-button></div><div><el-input-numberv-model="num":precision="2":step="0.1":max="2":min="0"style="width: 100px"size="mini"controls-position="right"@change="numberChange"></el-input-number></div><div><el-button:type="isRank ? 'primary' : ''"icon="el-icon-rank"circle@click="rankfn"></el-button></div></div><div class="mind" :class="{ mindRank: isRank }" v-drag ref="refresh"><mindItem :list="list" :style="'transform: scale(' + num + ')'"></mindItem></div></div> </template><script> import mindItem from "./components/mindItem.vue"; import { expendfn } from "./components/index.js"; export default {name: "",props: {},components: { mindItem },data() {return {isRank: false,list: [],num: 1,listCache: [{id: 11,first: true,tableData: [{ id: 112, name: "李四 1級-1", age: 2 },{ id: 113, name: "李四 1級-2", age: 4 },],children: [{parent: 11,id: 21,tableData: [{ id: 122, name: "李四 2級-1", age: 30 },{ id: 123, name: "李四 2級-2", age: 34 },],},{parent: 11,id: 22,tableData: [{ id: 124, name: "李四 2級-3", age: 65 },{ id: 125, name: "李四 2級-4", age: 23 },],},{parent: 11,id: 23,tableData: [{ id: 126, name: "李四 2級-5", age: 45 },{ id: 127, name: "李四 2級-6", age: 25 },],children: [{parent: 23,id: 33,tableData: [{ id: 128, name: "李四 3級-1", age: 32 },{ id: 129, name: "李四 3級-2", age: 623 },],},{parent: 23,id: 34,tableData: [{ id: 130, name: "李四 3級-3", age: 623 },{ id: 131, name: "李四 3級-4", age: 256 },],},{parent: 23,id: 35,tableData: [{ id: 132, name: "李四 3級-5", age: 352 },{ id: 133, name: "李四 3級-6", age: 2345 },],},{parent: 23,id: 36,tableData: [{ id: 134, name: "李四 3級-7", age: 35 },{ id: 135, name: "李四 3級-8", age: 4124 },],},],},],},],};},computed: {},watch: {num(newVal, oldVal) {console.log(newVal, oldVal);if (newVal < oldVal && oldVal <= 0.5) {this.num = 0.5;}},},directives: {drag: {bind: function (el) {let odiv = el;let moveing = false;let moves = false;odiv.onmousedown = (e) => {let arr = Array.from(odiv.classList);if (!arr.includes("mindRank")) return;let disX = e.clientX - odiv.offsetLeft;let disY = e.clientY - odiv.offsetTop;document.onmousemove = (e) => {let left = e.clientX - disX;let top = e.clientY - disY;if (top <= 80 && left <= 300) {// top = 80;// left = 300;}odiv.style.left = left + "px";odiv.style.top = top + "px";moveing = true;};document.onmouseup = (e) => {document.onmousemove = null;document.onmouseup = null;moveing = false;};};},},},created() {},mounted() {this.init();},methods: {rankfn() {this.isRank = !this.isRank;},numberChange() {console.log(" this.num--", this.num);},init() {let { listCache } = this;this.list = JSON.parse(JSON.stringify(listCache));},expendAll() {this.init();},}, }; </script><style scoped lang="less"> .warp {padding: 10px; } .mind {padding: 20px;// height: calc(100vh - 150px);// width: calc(100vw - 60px);position: fixed;user-select: none;overflow: auto;background-color: #fff; } .mindRank {cursor: move; } .header {display: inline-block;align-items: center;position: fixed;z-index: 2;background-color: #fff;& > div {display: inline-block;margin-right: 20px;} } </style>

src/views/mind/components/index.js

export function expendfn({list = [],id = '',isExpend = false // 默認展開/關閉 }) {if (list.length === 0) return [];let arr = JSON.parse(JSON.stringify(list));id === '' && !isExpend && defaultfn(arr, id, isExpend); // 刷新// 刷新function defaultfn(lists) {lists.forEach((x) => {x.isExpandBefore = false;x.isExpandAfter = falseif (x.children) defaultfn(x.children);});}return arr; }

src/router/index.js

import Vue from 'vue' Vue.use(VueRouter) const routes = [{path: '/mind',naem: 'mind',component: () => import('@/views/mind/mind.vue') }, ]const router = new VueRouter({routes })export default router

src/main.js

import '@/directive/index.js' import 'element-ui/lib/theme-chalk/index.css';import App from './App.vue' import ElementUI from 'element-ui'; import Vue from 'vue' import jm from 'vue-jsmind' import router from './router' import store from './store'Vue.config.productionTip = false Vue.use(ElementUI);Vue.use(jm) if (window.jsMind) {console.log('wind')Vue.prototype.jsMind = window.jsMind } new Vue({router,store,render: h => h(App) }).$mount('#app')

總結

以上是生活随笔為你收集整理的vue纯手写思维导图,拒绝插件(cv即用)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 午夜视频网址 | 色妞综合网 | 波多野结衣欲乱上班族 | 免费毛片一级 | 国产精品jizz在线观看美国 | 色99视频| 国产高清视频免费 | 韩日成人 | 四虎精品在线 | 露出调教羞耻91九色 | 亚洲字幕成人中文在线观看 | 黄色大片儿 | 亚洲色图视频网站 | 神马伦理视频 | 草草影院ccyycom | 成人三级影院 | 波多野结衣视频网站 | 在线a网 | 国产精品夜夜躁视频 | 日韩av成人在线 | 亚洲精品乱码久久久久久不卡 | 国产91精品久久久久 | 夜夜春影院 | 欧美情爱视频 | 国产第3页| 国产 日韩 欧美 综合 | 中国av一区二区 | 婷婷丁香六月 | 性xxxx狂欢老少配o | 免费一区二区在线观看 | 一区二区不卡在线观看 | 精品国产一区二区三区四区阿崩 | xvideos永久免费入口 | 成人小视频免费看 | 亚洲av永久无码国产精品久久 | 自拍三级 | 91久久久久 | 德国艳星videos极品hd | 日本不卡视频一区 | 欧美乱大交 | 亚洲欧洲精品一区 | 久久久久久成人精品 | 日韩欧美第一页 | 日韩第九页| 日本做爰高潮又黄又爽 | 日韩精品极品视频在线观看免费 | 亚洲成人福利 | 久久精品噜噜噜成人 | 自拍偷拍第3页 | 91大神精品在线 | 精品影视一区二区 | 真实乱视频国产免费观看 | 亚洲男人天堂影院 | 在线观看亚洲一区二区 | 国产又黄又猛又爽 | 日韩av在线播放不卡 | 亚洲AV无码精品一区二区三区 | 操夜夜| 久草视频手机在线观看 | 欧美视频在线免费看 | 久久久久成人片免费观看蜜芽 | 在线观看日韩av | 一个人看的www视频在线观看 | 情侣av| 国产三级三级三级 | 国产精品性 | www.99av| 成人黄色在线观看视频 | www.日本com| 另类小说婷婷 | 久久久久亚洲无码 | 免费精品视频一区二区三区 | 老司机免费在线视频 | av激情影院 | 国产又黄又爽视频 | 777精品伊人久久久久大香线蕉 | 72种无遮挡啪啪的姿势 | 日韩天堂 | 日韩大片免费观看视频播放 | 国产日韩一区二区在线 | 久艹伊人 | 亚洲国产无 | 免费看久久 | 国产免费无码XXXXX视频 | 国产精品91一区二区 | 国产又爽又黄游戏 | 毛片网站在线观看 | 中文字幕在线二区 | 蜜桃久久精品成人无码av | 韩国一区二区三区视频 | 特级西西444www大精品视频免费看 | 成人无码av片在线观看 | 一级黄色毛毛片 | 国产在线观 | 2020国产在线 | 色日韩 | 波多野结衣精品 | 又大又硬又爽免费视频 | 日韩欧美成人一区二区 |