一、背景

最近在做个开源webapp项目,在使用ElementUINavMenu侧边导航栏过程中,由于title过长,会产生文字溢出的bug:
文字溢出
对于这样情况题主所思考的解决方法就是采用文字溢出省略的方式解决,需要注意的点是ElementUI的侧边导航栏使用的是span标签,它是内联元素,需要使用display: inline-block;将其改为内联块元素,并设置width宽度,css样式才能生效:

.text-overflow-hidden {
	text-overflow: ellipsis; 
	white-space: nowrap; 
	overflow: hidden; 
	display: inline-block;
}

但是这样就产生了一个问题:用户如何查看侧边栏中的完整内容。对于这样的问题,有两种解决方式,一是鼠标悬停显示完整内容,二是实现对侧边栏宽度的手动缩放功能(类似表格操作)。

二、解决方式

1、鼠标悬停显示完整内容

鼠标悬停显示完整内容有两种方式:一是使用ElementUIToolTip文字提示,这个查看ElementUI文档就知道怎么使用,这里就不讲了。二是利用span标签的title属性,题主采用的是这种方式,原因是ToolTip文字提示的使用整体效果不如span标签的title属性。效果如下:
文字省略
代码如下:

<span 
slot="title" 
:title="item.metadata.name" 
style="width: 70%" 
class="text-overflow-hidden">
{{item.metadata.name}}
</span>

2、实现对侧边栏宽度的手动缩放功能

A.效果展示

侧边栏缩放效果

B.侧边栏的手动缩放

实现对侧边栏宽度的手动缩放功能本质上就是对侧边栏宽度的修改,利用鼠标的按下、抬起和移动事件,监听用户的操作并获取鼠标位置。因此可以在侧边栏右边添加一个空白标签div用作事件监听。需要注意的是,由于mousemovemouseup事件会被限制在该空白标签内,且该标签较小,容易造成监听失效问题,因此需要将两个事件冒泡绑定到父级标签内,题主是将其绑定到组件的根div上。
代码如下:

html代码:

<div @mousemove="shrinkMove" @mouseup="shrinkUp" style="width:100%; height:100%">
    <el-container>
        <el-aside :width="fatherWidth" class="bd-top flex" style="position:relative;">
            <aside-component></aside-component>
            <div class="resize" @mousedown="shrinkDown" title="Shrink sidebar"></div>
        </el-aside>
        <el-main style="background-color: var(--color-background)">
            <component :is="mainComponent"></component>
        </el-main>
    </el-container>
</div>

js代码

data() {
    return {
        mainComponent: "mainStartCom",
        isShrink: false,//控制是否改变宽度
    }
},
methods: {
    shrinkMove(e) {
        if (this.isShrink) {
            let wid = e.screenX + 5//误差值
            if (wid <= 65) {// 设定65为最短宽度
                this.$store.commit('changeCollapse', true)
                this.$store.commit('changeFatherWidth', '65px')
            }else {
                this.$store.commit('changeCollapse', false)
                this.$store.commit('changeFatherWidth', wid + 'px')
            }
        }
    },
    shrinkDown(e) {
        this.isShrink = true
    },
    shrinkUp(e) {
        this.isShrink = false
    }
}

css代码

.resize {
    cursor: col-resize;
    position: absolute;
    right: 0;
    height: 100%;
    width: 5px;
}

C.折叠功能的实现

js代码中需要注意shrinkMove方法,由于题主之前实现了通过按钮控制NavMenu导航菜单的折叠功能,其原理是通过NavMenu的属性collapse进行控制,并使用vuex进行组件通信,读者也可以不使用该功能,直接通过shrinkMove方法修改侧边栏的宽度即可。整体效果如下:

菜单折叠效果图
在这里插入图片描述

菜单释放效果图
在这里插入图片描述
实现代码如下:

<!-- 顶部导航栏组件 -->
<template>
	<div class="flex center pointer icon-size" @click="changeAsideWidth">
	    <el-tooltip class="item" effect="dark" :content="!isCollapse ? 'Collapse menu' : 'Expand menu'" placement="bottom">
	        <i class="el-icon-s-fold icon" v-if="!isCollapse"></i>
	        <i class="el-icon-s-unfold icon" v-else></i>
	    </el-tooltip>
	</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
	name: 'HeaderComponent',
	data() {
        return {}
    },
	computed: {
	    ...mapState({
	        showButton: (state) => state.header.showButton,
	        isCollapse: (state) => state.aside.isCollapse,
	    })
	},
	methods: {
        changeAsideWidth() {
            if (this.isCollapse) {
                this.$store.commit('changeCollapse', false)
                this.$store.commit('changeFatherWidth', '200px')
            } else {
                this.$store.commit('changeCollapse', true)
                this.$store.commit('changeFatherWidth', '65px')
            }
        }
    },
}
</script>

<!-- 侧边导航栏组件 -->
<template>
    <el-menu 
    default-active="2" 
    active-text-color="#6E38F7" 
    style="height: 100%;" 
    :collapse="isCollapse"
    :collapse-transition="false">
    </el-menu>
</template>
 
<script>
import { mapState } from 'vuex'
export default {
    name: 'AsideComponent',
    data() {
        return {}
    },
    computed: {
        ...mapState({
            isCollapse: (state) => state.aside.isCollapse
        })
    },
}
</script>

<!-- 主页面 -->
<el-container>
    <el-aside :width="fatherWidth" class="bd-top flex" style="position:relative;">
        <aside-component></aside-component>
        <div class="resize" @mousedown="shrinkDown" title="Shrink sidebar"></div>
    </el-aside>
    <el-main></el-main>
</el-container>

<script>
export default {
	data() {
	    return {}
	},
	computed: {
	    ...mapState({
	        fatherWidth: (state) => state.aside.fatherWidth
	    })
	},
}
</script>

vuex代码如下:

// index.js
import Vue from 'vue'
import Vuex from 'vuex'
import aside from './aside'
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    aside
  }
})

// aside.js

export default {
  state: {
    fatherWidth: '200px',
    isCollapse: false
  },
  mutations: {
    changeFatherWidth(state, val) {
      state.fatherWidth = val
    },
    changeCollapse(state, val) {
      state.isCollapse = val
    }
  }
}

3.注意事项

  • 题主的代码中,标签属性class里的内容是题主自定义的CSS样式,若有需要可在题主的git仓库直接获取文件使用:

https://github.com/WuChuSheng1/skywalking-banyandb/tree/main/ui/src/assets

  • 目前在效果上仍然有个小bug,就是折叠后的效果仍然有文字存在,正常情况下是只有icon图标的,这个情况之前没有,今天突然产生的(又要疯狂查代码emmm)。

三、总结

本题客主要是实现ElementUI的侧边导航栏缩放功能,建立在实现菜单折叠功能的基础之上,读者也可不实现折叠功能,可参考题主代码进行修改即可。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐