Arco Design Layout 中使用 ResizeBox 实现可拖拽侧边栏

Arco Design Layout 中使用 ResizeBox 实现可拖拽侧边栏

问题

a-layout-sider 虽然有 width 属性可以设置宽度,但没有拖拽事件 来动态调整宽度。直接使用 a-resize-box 替换会导致布局混乱。

解决方案

核心要点 :必须使用 <a-layout :has-sider="true"> 包裹 a-resize-box

vue 复制代码
<a-layout :has-sider="true">
  <a-resize-box
    :directions="['right']"
    :width="sidebarWidthImmediate"
    @moving="handleSidebarResize"
    @moving-end="handleSidebarResizeEnd"
  >
    <div>侧边栏内容</div>
  </a-resize-box>
  <a-layout-content>
    主内容区
  </a-layout-content>
</a-layout>

性能优化:双变量设计

问题

如果只用一个变量,拖拽过程中会频繁触发子组件更新和计算属性重新计算,导致卡顿。

方案

使用两个变量分离视觉反馈和数据传递:

typescript 复制代码
// 视觉反馈变量:高频更新,只影响 ResizeBox
const sidebarWidthImmediate = ref(200)

// 数据传递变量:低频更新,用于子组件和计算属性
const sidebarWidth = ref(200)

function handleSidebarResize(size: { width: number; height: number }) {
  // 拖拽过程中:只更新视觉反馈变量
  sidebarWidthImmediate.value = Math.max(minSidebarWidth, size.width)
}

function handleSidebarResizeEnd() {
  // 拖拽结束时:同步数据传递变量,触发一次子组件更新
  sidebarWidth.value = sidebarWidthImmediate.value
}

性能对比

方案 拖拽时子组件渲染 性能表现
单变量 高频(每秒数十次) ❌ 卡顿
双变量 低频(结束时1次) ✅ 流畅

完整示例

vue 复制代码
<template>
  <a-layout>
    <a-layout-header>Header</a-layout-header>
    
    <a-layout :has-sider="true">
      <a-resize-box
        :directions="['right']"
        :width="sidebarWidthImmediate"
        @moving="handleSidebarResize"
        @moving-end="handleSidebarResizeEnd"
      >
        <div class="sidebar">侧边栏内容</div>
      </a-resize-box>
      
      <a-layout-content>
        <MainContent
          :sidebar-width="sidebarWidth"
          :width="contentWidth"
        />
      </a-layout-content>
    </a-layout>
  </a-layout>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'

const minSidebarWidth = 200
const sidebarWidthImmediate = ref(minSidebarWidth) // 视觉反馈变量
const sidebarWidth = ref(minSidebarWidth) // 数据传递变量
const resizerWidth = 6
const containerWidth = ref(1200)

const contentWidth = computed(() => {
  return containerWidth.value - sidebarWidth.value - resizerWidth
})

function handleSidebarResize(size: { width: number; height: number }) {
  sidebarWidthImmediate.value = Math.max(minSidebarWidth, size.width)
}

function handleSidebarResizeEnd() {
  sidebarWidth.value = sidebarWidthImmediate.value
}
</script>

注意事项

  1. 必须设置 has-sider="true":否则布局会混乱
  2. 宽度计算需减去拖拽条宽度:通常为 6px
  3. 设置最小宽度限制:防止侧边栏过小
  4. 使用双变量模式:避免拖拽时频繁触发子组件更新
相关推荐
周某人姓周4 分钟前
DOM型XSS案例
前端·安全·web安全·网络安全·xss
程序员鱼皮15 分钟前
前特斯拉 AI 总监:AI 编程最大的谎言,是 “提效”
前端·后端·ai·程序员·开发
Irene199123 分钟前
Vue3 规范推荐的 <script setup> 中书写顺序(附:如何响应路由参数变化)
vue.js·路由
pusheng202527 分钟前
普晟传感2026年新春年会总结与分析
前端·javascript·html
谢尔登28 分钟前
React19事件调度的设计思路
前端·javascript·react.js
Emma_Maria38 分钟前
本地项目html和jquery,访问地址报跨域解决
前端·html·jquery
奋斗吧程序媛43 分钟前
常用且好用的命令
前端·编辑器
2301_796512521 小时前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:Lazyload 懒加载(懒加载的图片)
前端·javascript·react native·react.js·ecmascript·harmonyos
敲敲了个代码1 小时前
从N倍人力到1次修改:Vite Plugin Modular 如何拯救多产品前端维护困境
前端·javascript·面试·职场和发展·typescript·vite
Yff_world1 小时前
网络安全与 Web 基础笔记
前端·笔记·web安全