赞
踩
<template> <div :style="{ cursor, userSelect }" class="vue-splitter-container clearfix" @mouseup="onMouseUp" @mousemove="onMouseMove" > <pane class="splitter-pane splitter-paneL" :split="split" :style="{ [type]: percent + '%' }" > <slot name="paneL"></slot> </pane> <resizer :className="className" :style="{ [resizeType]: percent + '%' }" :split="split" @mousedown.native="onMouseDown" @click.native="onClick" ></resizer> <pane class="splitter-pane splitter-paneR" :split="split" :style="{ [type]: 100 - percent + '%' }" > <slot name="paneR"></slot> </pane> <div class="vue-splitter-container-mask" v-if="active"></div> </div> </template> <script> import Resizer from "./resizer.vue"; import Pane from "./pane.vue"; export default { name: "splitPane", components: { Resizer, Pane }, props: { minPercent: { type: Number, default: 10, }, defaultPercent: { type: Number, default: 50, }, split: { validator(value) { return ["vertical", "horizontal"].indexOf(value) >= 0; }, required: true, }, className: String, }, computed: { userSelect() { return this.active ? "none" : ""; }, cursor() { return this.active ? "col-resize" : ""; }, }, watch: { defaultPercent(newValue, oldValue) { this.percent = newValue; }, }, data() { return { active: false, hasMoved: false, height: null, percent: this.defaultPercent, type: this.split === "vertical" ? "width" : "height", resizeType: this.split === "vertical" ? "left" : "top", }; }, methods: { onClick() { if (!this.hasMoved) { this.percent = 50; this.$emit("resize"); } }, onMouseDown() { this.active = true; this.hasMoved = false; }, onMouseUp() { this.active = false; }, onMouseMove(e) { if (e.buttons === 0 || e.which === 0) { this.active = false; } if (this.active) { let offset = 0; let target = e.currentTarget; if (this.split === "vertical") { while (target) { offset += target.offsetLeft; target = target.offsetParent; } } else { while (target) { offset += target.offsetTop; target = target.offsetParent; } } const currentPage = this.split === "vertical" ? e.pageX : e.pageY; const targetOffset = this.split === "vertical" ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight; const percent = Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100; if (percent > this.minPercent && percent < 100 - this.minPercent) { this.percent = percent; } this.$emit("resize"); this.hasMoved = true; } }, }, }; </script> <style scoped> .clearfix:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; } .vue-splitter-container { height: 100%; position: relative; } .vue-splitter-container-mask { z-index: 9999; width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style>
<template> <div :class="classes"> <slot></slot> </div> </template> <script> export default { name: "Pane", props: { className: String, }, data() { const classes = [this.$parent.split, this.className]; return { classes: classes.join(" "), percent: 50, }; }, }; </script> <style lang="scss" scoped> .splitter-pane.vertical.splitter-paneL { position: absolute; left: 0px; height: 100%; padding-right: 3px; } .splitter-pane.vertical.splitter-paneR { position: absolute; right: 0px; height: 100%; padding-left: 3px; } .splitter-pane.horizontal.splitter-paneL { position: absolute; top: 0px; width: 100%; } .splitter-pane.horizontal.splitter-paneR { position: absolute; bottom: 0px; width: 100%; padding-top: 3px; } </style>
<template> <div :class="classes"></div> </template> <script> export default { props: { split: { validator(value) { return ["vertical", "horizontal"].indexOf(value) >= 0; }, required: true, }, className: String, }, computed: { classes() { const classes = ["splitter-pane-resizer", this.split, this.className]; return classes.join(" "); }, }, }; </script> <style lang="scss" scoped> .splitter-pane-resizer { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background: #000; position: absolute; opacity: 0.2; z-index: 1; -moz-background-clip: padding; -webkit-background-clip: padding; background-clip: padding-box; } .splitter-pane-resizer.horizontal { height: 12px; margin: -5px 0; border-top: 5px solid rgba(255, 255, 255, 0); border-bottom: 5px solid rgba(255, 255, 255, 0); cursor: row-resize; width: 100%; } .splitter-pane-resizer.vertical { width: 12px; height: 100%; margin-left: -5px; border-left: 5px solid rgba(255, 255, 255, 0); border-right: 5px solid rgba(255, 255, 255, 0); cursor: col-resize; } </style>
<template> <div class="components-container"> <split-pane split="vertical" @resize="resize"> <template slot="paneL"> <div class="left-container" /> </template> <template slot="paneR"> <split-pane split="horizontal"> <template slot="paneL"> <split-pane split="vertical"> <template slot="paneL"> <div class="top-left-container" /> </template> <template slot="paneR"> <div class="top-right-container" /> </template> </split-pane> </template> <template slot="paneR"> <div class="bottom-container" /> </template> </split-pane> </template> </split-pane> </div> </template> <script> import splitPane from "@/components/ui-split-pane"; export default { name: "Workbench_SplitPane", components: { splitPane, }, methods: { resize() { console.log("resize"); }, }, mounted() { console.log("split pane"); }, }; </script> <style lang="scss" scoped> .components-container { position: relative; height: 100vh; } .left-container { background-color: #d5ebe1; height: 100%; } .right-container { background-color: #b1d5c8; height: 200px; } .top-left-container { background-color: #99bcac; width: 100%; height: 100%; } .top-right-container { background-color: #80a492; width: 100%; height: 100%; } .bottom-container { width: 100%; background-color: #95e1d3; height: 100%; } </style>
https://github.com/PanJiaChen/vue-split-pane
npm install vue-splitpane
#import
import splitPane from 'vue-splitpane'
# use as global component
Vue.component('split-pane', splitPane);
<split-pane v-on:resize="resize" :min-percent='20' :default-percent='30' split="vertical">
<template slot="paneL">
A
</template>
<template slot="paneR">
B
</template>
</split-pane>
//nested <split-pane v-on:resize="resize" :min-percent='20' :default-percent='30' split="vertical"> <template slot="paneL"> A </template> <template slot="paneR"> <split-pane split="horizontal"> <template slot="paneL"> B </template> <template slot="paneR"> C </template> </split-pane> </template> </split-pane>
Property | Description | type | default |
---|---|---|---|
split | the split type | String [horizontal,vertical] | must choose one type |
min-percent | paneL max-min-percent | Number | 10 |
max-percent | paneL max-percent | Number | 10 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。