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的主要内容,如果未能解决你的问题,请参考以下文章

vue7自定义组件,插槽

vue 自定义组件之父子组件

Vue自定义组件父与子

Cesium指南-自定义vue组件

vue中自定义组件(插件)

vue之自定义组件