vue3 可拖动的左右面板分割组件实现

 更新时间:2021年06月02日 09:43:25   作者:我不爱吃鱼啦  
最近在使用vue的时候,遇到一个需求,实现左右div可通过中间部分拖拽调整宽度,本文就整理一下,分享给大家,有兴趣的可以学习

最近在使用vue的时候,遇到一个需求,实现左右div可通过中间部分拖拽调整宽度,本文就整理一下,分享给大家,具体如下:

效果图

分解组件

整体使用flex布局

左侧面板

  • 面板的具体内容通过slot具名插槽传入。
  • title通过prop传入
  • 可拖动,为了保证内容样式不会被拖动所破坏,对面板的宽度设定最大值/最小值

右侧面板

  • 右侧面板宽度随着左侧面板的宽度变化而变化,此处需注意,内容的宽度使用flex-auto自动适应。
  • 需要做移动端的自适应。
  • 自适应使用tailwind的媒体查询

入参分解

props

  • @param {Number} maxWidth 最大宽度
  • @param {Number} minWidth 最小宽度
  • @param {String} leftTitle 左标题
  • @param {String} rightTitle 右标题?
  • @param {Boolean} sotoreage 是否存储与localstorege

slots

  • left-content {Element}  左侧内容
  • right-content {Element} 右侧内容

具体实现

如何拖动呢?

在左侧面板与右侧面板之间添加一个隐藏的盒子,我将这个盒子隐藏在box-shadow之中。具体事件放在这个div中实现

<div id="line" class="w-2 cursor-move hidden md4:block"onMousedown={hnadleMouseDown}>
</div>

事件监听

    const hnadleMouseDown = (evt: MouseEvent) => {
      /* 获取起始点位,并存储 */
      let { pageX, pageY } = evt;
      basePosition.pageX = pageX;
      basePosition.pageY = pageY;
      /* 监听鼠标的移动事件 */
      document.addEventListener("mousemove", handleMouseMove);
      document.addEventListener("mouseup", handleMouseUp);
    };
    const handleMouseMove = evt => {
      /* 阻止浏览器默认事件,防止触发浏览器的手势功能 */
      evt.preventDefault();
      /* 设置定时器,防止dom多次回流 */
      clearTimeout(timer.value);
      timer.value = setTimeout(() => {
        let { pageX } = evt;
        const baseDiv = document.querySelector(".right-border-shadow");
        /* 处理宽度,是否处于最大值/最小值之间 */
        let baseWidth: Number | undefined =
          Number(baseDiv?.clientWidth) + (pageX - basePosition.pageX);
        baseWidth =
          baseWidth > Number(props?.maxWidth) ? props.maxWidth : baseWidth;
        baseWidth =
          Number(baseWidth) < Number(props?.minWidth)
            ? props.minWidth
            : baseWidth;
        baseDiv?.setAttribute("style", `width:${baseWidth}px`);
        /* emit宽度改变的事件 */
        ctx.emit("drugend");
        /* 存储到store */
        setStore(baseWidth);
      }, 50);
    };
    const handleMouseUp = evt => {
      /* 结束拖动之后,取消事件监听,并emit出最终宽度 */
      const width = document.querySelector(".right-border-shadow")?.clientWidth;
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
      ctx.emit("drugend", width);
    };

宽度处理

style={`width:${
            store.get("split-width")
              ? store.get("split-width")
              : props.minWidth
              ? props.minWidth
              : 384
          }px`}

优化

手动改变浏览器视窗宽度

nextTick(() => {
        ctx.emit("load", ctx);
        MutationObserver = window.MutationObserver;
        if (MutationObserver) {
          /* 监听浏览器的窗口变化,在部分情况下需要这个api */
          mo = new MutationObserver(function() {
            const __wm = document.querySelector("#rezie-id");
            // 只在__wm元素变动才重新调用 __canvasWM
            if (!__wm) {
              // 避免一直触发
              mo.disconnect();
              mo = null;
              ctx.emit("resize");
            }
          });
          mo.observe(document.querySelector("#rezie-id"), {
            attributes: true,
            subtree: true,
            childList: true,
          });
        }
      });

未生效,求指点

bug

父组件的onMounted钩子中获取子元素的slot元素节点报错,为null。目前的解决办法是在子组件的onMounted钩子中抛出一个load事件,父组件使用onLoad去处理接下来的逻辑。

git地址

仓库地址
预览地址

到此这篇关于vue3 可拖动的左右面板分割组件实现的文章就介绍到这了,更多相关vue3 可拖动左右分割面板内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • 如何通过shell脚本自动生成vue文件详解

    如何通过shell脚本自动生成vue文件详解

    这篇文章主要给大家介绍了关于如何通过shell脚本自动生成vue文件的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • Vue 使用中的小技巧

    Vue 使用中的小技巧

    这篇文章主要介绍了Vue 使用中的小技巧,是小编日常开发的时候用到的小技巧,需要的朋友可以参考下
    2018-04-04
  • 使用vue.js在页面内组件监听scroll事件的方法

    使用vue.js在页面内组件监听scroll事件的方法

    今天小编就为大家分享一篇使用vue.js在页面内组件监听scroll事件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • vue项目实现图片懒加载的简单步骤

    vue项目实现图片懒加载的简单步骤

    懒加载的好处在于减少服务器的压力,在网络比较慢的情况下,可以提前给这张图片添加一个占位图片,提高用户的体验,这篇文章主要给大家介绍了关于vue项目实现图片懒加载的相关资料,需要的朋友可以参考下
    2022-09-09
  • 深入理解Vue transition源码分析

    深入理解Vue transition源码分析

    本篇文章主要介绍了深入理解Vue transition源码分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Vue中sync修饰符分析原理及用法示例

    Vue中sync修饰符分析原理及用法示例

    在vue中,子组件如果想修改父组件的变量,一般做法是通过绑定事件的方法,父组件向子组件传递修改变量的方法,子组件触发修改变量的方法执行,这种方式中规中矩;另一种方法是使用sync修饰符,此方法可以减少很多代码量
    2022-08-08
  • Vuex 模块化使用详解

    Vuex 模块化使用详解

    这篇文章主要介绍了Vuex 模块化使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • vue实现全选功能

    vue实现全选功能

    这篇文章主要为大家详细介绍了vue实现全选功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 详解vue.js下引入百度地图jsApi的两种方法

    详解vue.js下引入百度地图jsApi的两种方法

    这篇文章主要介绍了详解vue.js下引入百度地图jsApi的两种方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • Vue动态获取数据后控件不可编辑问题

    Vue动态获取数据后控件不可编辑问题

    这篇文章主要介绍了Vue动态获取数据后控件不可编辑问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论