vue自定义组件——split-pane
Posted lxm-cnblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue自定义组件——split-pane相关的知识,希望对你有一定的参考价值。
github地址: https://github.com/lxmghct/my-vue-components
组件介绍
- props:
- splitCount: 分割数量, default: 2
- direction: 分割方向, \'vertical\' or \'horizontal\', default: \'horizontal\'
- defaultRatio: 默认比例, 类型为数组, default: [1/spiltCount, 1/spiltCount, ...]
- slots:
- ...
- ...
- ...
- events:
- @resize: 拖动分割条时触发, 参数为分割线两侧的div
- @resize-stop: 拖动分割条结束时触发
- methods:
- changeItemSize(index, itemSize, dire=\'next\') 改变第item个pane的大小, dire为next或prev, 表示修改当前pane时连带修改前一个pane还是后一个
效果展示
设计思路
整个组件采用flex布局,通过设置整体的flex-direction
控制分割方向,通过修改每个pane的style.flex
控制每个pane的大小。
<div class="split-main" ref="splitMain"
:class="direction === \'vertical\' ? \'split-vertical\' : \'split-horizontal\'">
<template v-if="direction === \'vertical\'">
<div v-for="i in splitCount" :key="i" ref="splitItem"
class="split-vertical-item">
<div class="split-vertical-line" v-if="i < splitCount"
@mousedown="_startDrag(i)"
@touchstart="_startDrag(i)"></div>
<div class="split-vertical-content">
<slot :name="`pane$i`"></slot>
</div>
</div>
</template>
<template v-else>
<div v-for="i in splitCount" :key="i" ref="splitItem"
class="split-horizontal-item">
<div class="split-horizontal-line" v-if="i < splitCount"
@mousedown="_startDrag(i)"
@touchstart="_startDrag(i)"></div>
<div class="split-horizontal-content">
<slot :name="`pane$i`"></slot>
</div>
</div>
</template>
</div>
通过v-for
循环生成分割数量的pane,每个pane中间插入分割线,分割线通过@mousedown
和@touchstart
事件绑定_startDrag
方法,该方法用于监听鼠标或手指的移动事件,从而实现拖动分割线改变pane大小的功能。
_startDrag (index)
this.dragIndex = index - 1
,
_onMouseMove (e)
if (this.dragIndex === -1)
return
let items = this.$refs.splitItem
let item1 = items[this.dragIndex]
let item2 = items[this.dragIndex + 1]
let rect1 = item1.getBoundingClientRect()
let rect2 = item2.getBoundingClientRect()
let ratio1, ratio2
let minLen = this.minLen
if (this.direction === \'vertical\')
let height = this.$refs.splitMain.clientHeight
let tempY = e.clientY - rect1.top > minLen ? e.clientY : rect1.top + minLen
tempY = rect2.bottom - tempY > minLen ? tempY : rect2.bottom - minLen
ratio1 = (tempY - rect1.top) / height
ratio2 = (rect2.bottom - tempY) / height
else
let width = this.$refs.splitMain.clientWidth
let tempX = e.clientX - rect1.left > minLen ? e.clientX : rect1.left + minLen
tempX = rect2.right - tempX > minLen ? tempX : rect2.right - minLen
ratio1 = (tempX - rect1.left) / width
ratio2 = (rect2.right - tempX) / width
item1.style.flex = ratio1
item2.style.flex = ratio2
e.preventDefault()
this.$emit(\'resize\', item1, item2)
,
_onMouseUp ()
if (this.dragIndex === -1)
return
this.dragIndex = -1
this.$emit(\'resize-stop\')
完整代码在github上。https://github.com/lxmghct/my-vue-components
videojs在vue中的使用(自定义组件,如清晰度)
参考技术A 该方式使用以创建好的video标签,只是简单的改变video的src。注意,此时的自定义组件(如清晰度)并没有更新,里面的数据还是上一个视频的信息,需要手动更新,可以手动移除后再添加。该方式首先会调用dispose方法销毁已经创建的video标签,并移除所有的组件和监听事件,然后需要自己创建video并设置其id(注意该id不能与之前销毁的id相同,我也不知道为啥~ :) )和class以及src,然后将创建的video添加到文档中,如上html的结构,将作为id= vWrap的子元素添加到文档中。
一开始在项目中使用dplayer做为视频的播放库,但是由于在孤儿浏览器上出现兼容问题 🙃,因此不得不放弃转为videojs,一路走来,踩了不少抗,主要是视频切换和自定义组件在切换视频时出的问题(样式的修改可以通过css覆盖生成的样式),这篇文章谨献给自己在这里所掉的头~😭
以上是关于vue自定义组件——split-pane的主要内容,如果未能解决你的问题,请参考以下文章