[vue ]滚动视图解决ElementUI NavMenu 导航菜单过长显示的问题
记录一下工作
需求
导航菜单过长的时候会溢出,需要一个像 Tabs 标签页一样的滚动视图容器,可以左右滚动内部视图。
解决方法
由于时间问题,所以直接将 Tabs 源码抽取出来使用。
这里要做一些特殊处理,不允许 NavMenu 导航菜单滚动视图容器内的元素换行。
如:
使用方法如下:
<scrollView>
<div>
// 一些不换行内容
</div>
</scrollView>
最后效果
下面是抽出来的源码,稍稍改造了下,左右箭头做了自适应垂直居中,把 elementui的样式抽取出来以及修改了类名,减少依赖。
scrollView.vue
<script>
import {
addResizeListener,
removeResizeListener
} from 'element-ui/src/utils/resize-event' export default {
props: {
width: {
type: String,
default: '100%'
}
}, data () {
return {
scrollable: false,
navOffset: 0
}
}, computed: {
navStyle () {
return {
transform: `translateX(-${this.navOffset}px)`
}
}
}, methods: {
scrollPrev () {
const containerSize = this.$refs.navScroll.offsetWidth
const currentOffset = this.navOffset if (!currentOffset) return const newOffset =
currentOffset > containerSize ? currentOffset - containerSize : 0 this.navOffset = newOffset
},
scrollNext () {
const navSize = this.$refs.nav.offsetWidth
const containerSize = this.$refs.navScroll.offsetWidth
const currentOffset = this.navOffset if (navSize - currentOffset <= containerSize) return const newOffset =
navSize - currentOffset > containerSize * 2
? currentOffset + containerSize
: navSize - containerSize this.navOffset = newOffset
},
scrollToActiveTab () {
if (!this.scrollable) return const nav = this.$refs.nav
const activeTab = this.$el.querySelector('.is-active')
if (!activeTab) return
const navScroll = this.$refs.navScroll
const activeTabBounding = activeTab.getBoundingClientRect()
const navScrollBounding = navScroll.getBoundingClientRect()
const maxOffset = nav.offsetWidth - navScrollBounding.width
const currentOffset = this.navOffset
let newOffset = currentOffset if (activeTabBounding.left < navScrollBounding.left) {
newOffset =
currentOffset - (navScrollBounding.left - activeTabBounding.left)
}
if (activeTabBounding.right > navScrollBounding.right) {
newOffset =
currentOffset + activeTabBounding.right - navScrollBounding.right
}
newOffset = Math.max(newOffset, 0)
this.navOffset = Math.min(newOffset, maxOffset)
},
update () {
if (!this.$refs.nav) return
const navSize = this.$refs.nav.offsetWidth
this.height = this.$refs.nav.offsetHeight
const containerSize = this.$refs.navScroll.offsetWidth
const currentOffset = this.navOffset
if (containerSize < navSize) {
const currentOffset = this.navOffset
this.scrollable = this.scrollable || {}
this.scrollable.prev = currentOffset
this.scrollable.next = currentOffset + containerSize < navSize
if (navSize - currentOffset < containerSize) {
this.navOffset = navSize - containerSize
}
} else {
this.scrollable = false
if (currentOffset > 0) {
this.navOffset = 0
}
}
}
}, updated () {
this.update()
}, render () {
const { navStyle, scrollable, scrollNext, scrollPrev, height, width } = this
const lineHeight = {
'line-height': height + 'px'
}
const scrollBtn = scrollable
? [
<span
class={['scrollView__nav-prev', scrollable.prev ? '' : 'is-disabled']}
on-click={scrollPrev}
>
<i
style={lineHeight}
class="el-icon-arrow-left"></i>
</span>,
<span
class={['scrollView__nav-next', scrollable.next ? '' : 'is-disabled']}
on-click={scrollNext}
>
<i style={lineHeight}
class="el-icon-arrow-right"></i>
</span>
]
: null return (
<div
class={[
'scrollView__nav-wrap',
scrollable ? 'is-scrollable' : ''
]}
style={{ width }}
>
{scrollBtn}
<div
class="scrollView__nav-scroll"
ref="navScroll"
>
<div
class="scrollView__nav"
ref="nav"
style={navStyle}
>
{this.$slots.default}
</div>
</div>
</div>
)
}, mounted () {
addResizeListener(this.$el, this.update)
}, beforeDestroy () {
if (this.$el && this.update) removeResizeListener(this.$el, this.update)
}
}
</script> <style lang="less">
.scrollView__nav-wrap {
display: inline-block;
overflow: hidden;
margin-bottom: -1px;
position: relative;
vertical-align: middle;
} .scrollView__nav-wrap.is-scrollable {
padding: 0 20px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
} .scrollView__nav-wrap::after {
display: none;
} .scrollView__nav-scroll {
overflow: hidden;
} .scrollView__nav {
white-space: nowrap;
position: relative;
transition: transform 0.3s, -webkit-transform 0.3s;
float: left;
z-index: 2;
} .scrollView__nav-prev {
left: 0;
}
.scrollView__nav-next {
right: 0;
}
.scrollView__nav-next,
.scrollView__nav-prev {
position: absolute;
cursor: pointer;
line-height: 44px;
font-size: 12px;
color: #909399;
}
</style>
[vue ]滚动视图解决ElementUI NavMenu 导航菜单过长显示的问题的更多相关文章
- NavMenu 导航菜单
顶栏 适用广泛的基础用法. 导航菜单默认为垂直模式,通过mode属性可以使导航菜单变更为水平模式.另外,在菜单中通过submenu组件可以生成二级菜单.Menu 还提供了background-colo ...
- AntDesign vue学习笔记(五)导航菜单动态加载
一般的后台系统都有一个树形导航菜单,具体实现如下,主要参考https://my.oschina.net/u/4131669/blog/3048416 "menuList": [ { ...
- vue-router + ElementUI实现NavMenu 导航菜单 选中状态的切换
elemen-ui官方网站:http://element.eleme.io/#/zh-CN/component/menu 新手小白利用vue+element-ui尝试搭建后台管理系统, 效果是这样的, ...
- element-ui 框架中使用 NavMenu 导航菜单组件时,点击一个子菜单会出现多个子菜单同时展开或折叠?
我在使用 elment-ui 框架的导航组件时,直接粘贴复制了官网上 (http://element-ui.cn/#/zh-CN/component/menu)的例子不会出错,但是当我将他们转化为动态 ...
- 解决element-ui表格表头内容太长时的换行问题
在用vue+element-ui做一个后台管理系统时,遇到这样的问题, 如图: 使用el-table做一个表格,当表头内容过长时会换行,在不设置的宽度的时候每一列的宽度是等比例分配的,虽然elemen ...
- vue+element UI递归方式实现多级导航菜单
介绍 这是一个是基于element-UI的导航菜单组件基础上,进行了二次封装的菜单组件,该组件以组件递归的方式,实现了可根据从后端接收到的json菜单数据,动态渲染多级菜单的功能. 使用方法 由于该组 ...
- vue+element UI以组件递归方式实现多级导航菜单
介绍 这是一个是基于element-UI的导航菜单组件基础上,进行了二次封装的菜单组件,该组件以组件递归的方式,实现了可根据从后端接收到的json菜单数据,动态渲染多级菜单的功能. 使用方法 由于该组 ...
- Xamarin iOS教程之进度条和滚动视图
Xamarin iOS教程之进度条和滚动视图 Xamarin iOS 进度条 进度条可以看到每一项任务现在的状态.例如在下载的应用程序中有进度条,用户可以很方便的看到当前程序下载了多少,还剩下多少.Q ...
- 在ASP.NET MVC下实现树形导航菜单
在需要处理很多分类以及导航的时候,树形导航菜单就比较适合.例如在汽车之家上: 页面主要分两部分,左边是导航菜单,右边显示对应的内容.现在,我们就在ASP.NET MVC 4 下临摹一个,如下: 实现的 ...
随机推荐
- vue-cli多页面应用常遇到的问题
1.TypeError: webpack.optimize.OccurenceOrderPlugin is not a constructor 此问题出现在webpack 3中,解决办法很简单,将oc ...
- java MVC 自定义类型转换器(Formatter、AnnotationFormatterFactory)
下面一个事例,是将传入的一个身份证号,转换成一个对象(提取身份证号的地址.出身日期.性别等) 实体类 Person 有三个字段如下: String province; //地址 Date birthd ...
- Apollo配置中心介绍与使用指南
转载于https://github.com/ctripcorp/apollo,by Ctrip, Inc. Apollo配置中心介绍 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中 ...
- [洛谷P4388] 付公主的矩形
18.09.09模拟赛T1. 一道数学题. 题目传送门 首先把对角线当成是某个点的移动轨迹,从左下到右上. 那么这个点每上升一个单位长度,就穿过一个格子. 每右移一个单位长度,也会穿过一个格子. 例外 ...
- vue子组件使用自定义事件向父组件传递数据
使用v-on绑定自定义事件可以让子组件向父组件传递数据,用到了this.$emit(‘自定义的事件名称’,传递给父组件的数据) <!DOCTYPE html> <html lang= ...
- iOS开发之多线程(NSThread、NSOperation、GCD)
整理一些多线程相关的知识. 并行 & 并发 1.并行:并行是相对于多核而言的,几个任务同时执行.2.并发:并发是相对于单核而言的,几个任务之间快速切换运行,看起来像是"同时" ...
- 机器学习技法笔记(2)-Linear SVM
从这一节开始学习机器学习技法课程中的SVM, 这一节主要介绍标准形式的SVM: Linear SVM 引入SVM 首先回顾Percentron Learning Algrithm(感知器算法PLA)是 ...
- redis集群配置及python操作
之前我们分析过喜马拉雅的爬取信息,使用分布式爬取,而且需要修改scrapy-redis的过滤算法为布隆过滤来减少redis内存占用,最后考虑这样还是不一定够,那么redis集群就是更好的一种选择方式了 ...
- Javascript中的局部变量、全局变量的详解与var、let的使用区别
前言 Javascript中的变量定义方式有以下三种方式:1.直接定义变量,var与let均不写: a = 10; 2.使用var关键字定义变量 var a = 10; 3.使用let关键字定义变量 ...
- USB小白学习之路(2)端点IN/OUT互换
端点2(out)和端点6(in)的out_in互换 注:这里的out和in都是以host为标准说的,out是host的out,在设备(Cy7c68013)这里其实是输入端口:in是host的in,在设 ...