若依系统侧边菜单实现可拖拽宽度

项目中菜单名字过长显示不全,要求实现菜单宽度拖拽。去查了若依官网,作者团队建议直接修改固定宽度,但不符合我们要求。故此有了以下代码:

一、拖拽组件封装

//ResizeBox组件代码
<template>
      <div  ref="resize" class="resize">
        <div ref="resizeHandle" class="handle-resize"></div>
        <slot></slot>
      </div>
  </template>
  <script>
  export default {
    name: 'ResizeBox',
    props: {
      resizeConf: {
        type: Object,
        default: () => ({
          width: 200, // 初始宽度
          widthRange: [200, 500] // 宽度范围
        })
      }
    },
    mounted() {
      console.log(this.resizeConf);
      this.dragControllerDiv(this.$refs.resize, this.$refs.resizeHandle)
    },
    methods: {
      dragControllerDiv: function(resizeBox, resizeHandle) {
        resizeBox.style.width = this.resizeConf.width + 'px'
        // 鼠标按下事件
        resizeHandle.onmousedown = e => {
          const resizeWidth = resizeBox.offsetWidth
          const startX = e.clientX // 水平坐标
          // 鼠标拖动事件
          document.onmousemove = ev => {
            const moveX = ev.clientX
            const moveLen = resizeWidth + (moveX - startX)
            if (this.resizeConf.widthRange[0] <= moveLen && this.resizeConf.widthRange[1] >= moveLen) {
              resizeBox.style.width = moveLen + 'px'
            }
            if(moveLen > this.resizeConf.widthRange[1]) {
              resizeBox.style.width = this.resizeConf.widthRange[1] + 'px'
              this.$emit('changeWidth', moveLen)
            } else if(moveLen < this.resizeConf.widthRange[0]) {
              resizeBox.style.width = this.resizeConf.widthRange[0] + 'px'
              this.$emit('changeWidth', moveLen)
            } else{
              this.$emit('changeWidth', moveLen)
            }
          }
          // 鼠标松开事件
          document.onmouseup = function() {
            document.onmousemove = null
            document.onmouseup = null
          }
        }
      }
    }
  }
  </script>
  <style lang="scss" scoped>
  .resize {
    background: #FFF;
    position: relative;
    word-wrap: break-word;
    .handle-resize {
      cursor: col-resize;
      position: absolute;
      right: -4px;
      width: 6px;
      height: 50px;
      border-left: 2px solid #c5c5c5;
      border-right: 2px solid #c5c5c5;
      top: calc(50% - 25px);
    }
  }
  </style>
   

二、若依布局页应用组件

在这里插入图片描述
上面是代码页修改对比图,以下是详细代码:

<template>
  <div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
    <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
    <ResizeBox v-if="sidebar.opened && !sidebar.hide" ref="ResizeBoxRef" id="ResizeBoxId" :resize-conf="resizeConf" style="height: 100%; position: absolute; z-index: 9;" @changeWidth="changeWidth">
      <sidebarclass="sidebar-container" :style="{width: marginLeft}" />
    </ResizeBox>
    <div v-else>
      <sidebar v-if="!sidebar.hide" class="sidebar-container"/>
    </div>
    <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container" :style="{marginLeft: sidebar.opened ? marginLeft : device === 'mobile' ? '0px':'54px'}">
    <!-- <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container"> -->
      <div :class="{ 'fixed-header': fixedHeader }">
        <navbar @setLayout="setLayout" />
        <tags-view v-if="needTagsView" />
      </div>
      <app-main />
      <settings ref="settingRef" />
    </div>
  </div>
</template>

<script setup>
import ResizeBox from './components/ResizeBox.vue'
import { useWindowSize } from '@vueuse/core'
import Sidebar from './components/Sidebar/index.vue'
import { AppMain, Navbar, Settings, TagsView } from './components'
import defaultSettings from '@/settings'

import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings'

const marginLeft = ref('200px')
const resizeConf = ref({
  width: 200, // 初始宽度
  widthRange: [200, 400] // 宽度范围
})
  
function changeWidth(width) {
  resizeConf.value.width = width > resizeConf.value.widthRange[1] ? resizeConf.value.widthRange[1]: width < resizeConf.value.widthRange[0] ? resizeConf.value.widthRange[0]:width;
  marginLeft.value = width > resizeConf.value.widthRange[1] ? resizeConf.value.widthRange[1]+'px': width < resizeConf.value.widthRange[0] ? resizeConf.value.widthRange[0]+'px': width+'px'; 
}

const settingsStore = useSettingsStore()
const theme = computed(() => settingsStore.theme);
const sideTheme = computed(() => settingsStore.sideTheme);
const sidebar = computed(() => useAppStore().sidebar);
const device = computed(() => useAppStore().device);
const needTagsView = computed(() => settingsStore.tagsView);
const fixedHeader = computed(() => settingsStore.fixedHeader);

const classObj = computed(() => ({
  hideSidebar: !sidebar.value.opened,
  openSidebar: sidebar.value.opened,
  withoutAnimation: sidebar.value.withoutAnimation,
  mobile: device.value === 'mobile'
}))

const { width, height } = useWindowSize();
const WIDTH = 992; // refer to Bootstrap's responsive design

watchEffect(() => {
  if (device.value === 'mobile' && sidebar.value.opened) {
    useAppStore().closeSideBar({ withoutAnimation: false })
  }
  if (width.value - 1 < WIDTH) {
    useAppStore().toggleDevice('mobile')
    useAppStore().closeSideBar({ withoutAnimation: true })
  } else {
    useAppStore().toggleDevice('desktop')
  }
})

function handleClickOutside() {
  useAppStore().closeSideBar({ withoutAnimation: false })
}

const settingRef = ref(null);
function setLayout() {
  settingRef.value.openSetting();
}
</script>

<style lang="scss" scoped>
  @import "@/assets/styles/mixin.scss";
  @import "@/assets/styles/variables.module.scss";

.app-wrapper {
  @include clearfix;
  position: relative;
  height: 100%;
  width: 100%;

  &.mobile.openSidebar {
    position: fixed;
    top: 0;
  }
}

.drawer-bg {
  background: #000;
  opacity: 0.3;
  width: 100%;
  top: 0;
  height: 100%;
  position: absolute;
  z-index: 999;
}

.fixed-header {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 9;
  width: calc(100% - #{$base-sidebar-width});
  transition: width 0.28s;
}

.hideSidebar .fixed-header {
  width: calc(100% - 54px);
}

.sidebarHide .fixed-header {
  width: 100%;
}

.mobile .fixed-header {
  width: 100%;
}
</style>

注意此处要删除 !important,否则布局页style样式不会生效:
在这里插入图片描述

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现动态路由和动态侧边菜单栏,需要先使用Vue Router来处理路由,然后使用Vue3的组合式API来实现动态路由和动态侧边菜单栏。 首先,在Vue Router定义路由时,可以使用动态路由参数来实现动态路由。例如: ```javascript const routes = [ { path: '/user/:id', component: User } ] ``` 在这个例子,路由为/user/:id,其:id是动态的,可以根据需要传入不同的参数来生成不同的路由。 然后,在组件使用Vue3的组合式API来获取当前路由参数,例如: ```javascript import { useRoute } from 'vue-router' export default { setup() { const route = useRoute() console.log(route.params.id) // 输出当前路由参数 } } ``` 接下来,可以根据当前路由参数来生成动态的侧边菜单栏。例如: ```javascript import { useRoute, useRouter } from 'vue-router' export default { setup() { const router = useRouter() const route = useRoute() const menuItems = [ { name: '用户列表', path: '/users' }, { name: '用户详情', path: `/user/${route.params.id}` }, { name: '添加用户', path: '/add-user' }, ] return { menuItems, goToPage(path) { router.push(path) } } } } ``` 在这个例子,使用useRouter来获取路由实例,然后根据当前路由参数生成动态的侧边菜单栏。同时,定义一个goToPage方法,用来跳转到指定的页面。 最后,在侧边菜单栏组件使用v-for指令来渲染菜单项,例如: ```html <template> <div> <ul> <li v-for="item in menuItems" :key="item.path" @click="goToPage(item.path)"> {{ item.name }} </li> </ul> </div> </template> ``` 通过这样的方式,就可以实现动态路由和动态侧边菜单栏了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值