[技术博客]iview组件样式踩坑记录
[技术博客]iview组件样式踩坑记录
在本次项目开发中,前端项目主要使用vue框架+iview组件构建,其中iview组件在使用过程中遇到了许多官方文档中没有明确说明或是很难注意到的小坑,这里总结一下分享给大家。
一、iview组件的特殊使用
各个组件的基本用法在官方文档中已经给出,这里总结一些官方文档并没有仔细说明的组件的特殊用法。
1.部分可以动态展开的组件(如下拉菜单)在展开时,被页面中其他元素遮挡问题。
解决方法:使用transfer属性(仅对iview组件有效)
<Dropdown transfer>
</Dropdown>
我遇到这个问题时,最初的想法是在组件的样式中添加z-index:8888
来设置该组件的堆叠顺序,令其显示在最上方。但是这种方法对于某些iview组件并不起作用,具体原因可能是iview组件本身对z-index有一套动态设置的方法,而且如导航菜单栏之类的大组件中也用到了许多小组件,手动设置的z-index无法被继承。
其实,iview组件本身提供了一个名为transfer
的属性,当在组件的tag中添加该属性时,iview会改变transfer
元素的位置,将其直接放置于<body>
tag下,并且动态设置z-index
保证其处于最上层,不会被其他元素遮挡。不是很明白为什么官方文档不提示transfer
属性的使用 😦。
效果如下图所示,加入transfer
属性的下拉框从里层的<div>
被提到了<body>
层,并且z-index
的数值会随着点击不断增加,感兴趣的朋友可以自己尝试感受一下z-index
的动态变化。
2.导航菜单栏组件选中元素的动态控制。
解决方法:配合vue框架,动态改变导航菜单栏active-name属性变量为想要选中的项的name。
<Menu :active-name="mySiderActive">
<MenuItem name="1-1">
</MenuItem>
<MenuItem name="2-1">
</MenuItem>
</Menu>
在需要改变选中项的事件中添加对变量的修改,即可改变选中项
this.mySiderActive = "2-1";
3.对话框组件不显示页脚内容。
解决方法:将footer-hide
属性设置为true
<Modal
v-model="modal1"
title="hello"
:footer-hide=true
>
</Modal>
在某些场景下,我们不想让对话框的页脚显示,而iview组件官方文档中只提供了改写页脚的方法,并没有说明如何隐藏。使用该方法貌似也可以对iview其他组件的一些部分进行隐藏,未尝试。
二、iview组件的样式修改
iview组件的样式修改可谓一路踩坑,接下来总结一下可以对样式进行修改的方法。
1.直接在具体的组件对象上添加style。
以导航菜单的<MenuItem>
元素为例:
<MenuItem name="10" style="pointer-events:none;" >
</MenuItem>
直接在该对象上设置style
样式貌似是优先级最高的方式样式加载方式,使用该方法可以将某一对象原本的iview默认样式完美覆盖,如果需要改动的对象比较少,此方法简单有效。但如果要将许多iview组件对象修改为某一相同样式,特别是还需要动态变化时,该方法就显得十分笨拙冗长。
2.全局修改某一类iview组件的样式。
-
首先,我们需要知道待修改样式的类名。
打开浏览器元素审查(以chrome为例),在这里我们可以选中相应的tag,看到html代码与页面中元素的对应关系,同时右侧将显示该元素正在应用的css样式。
右侧样式框中使用我们可以看到一长串的类名,值得对前端新手(比如我)强调的是,并不只有最后一个
.xxxxx
,使用逗号分隔的这一长串带有点和空格的东西都是css样式的类名。比如在上图红框中出现的css的类是.ivu-menu-light.ivu-menu-horizontal .ivu-menu-submenu
和.ivu-menu-light.ivu-menu-horizontal .ivu-menu-item
这两个类,而不是.ivu-menu-submenu
和.ivu-menu-item
。而且类名中的空格也很有讲究,不可以随便增删。样式框中使用黑色强调的类是我们选中元素正在应用的css类,而灰色的类名则是其他使用相同样式的类,并不是该元素正在应用的类,因此我们只需要修改深黑色类名对应的样式,即可实现对选中元素样式的覆盖。
-
接着,全局样式的修改方式是直接添加style标签,更改相应的css类的样式,比如:
<style> .ivu-menu-light.ivu-menu-horizontal .ivu-menu-submenu { color: #2d8cf0; } </style>
此时,我们就会发现页面中所有应用
.ivu-menu-light.ivu-menu-horizontal .ivu-menu-submenu
的样式被修改为我们想要的效果。 -
最后,也许我们想知道该元素在某些事件(比如hover、active等)下iview的样式,chrome为我们提供了非常贴心的功能,右键点击某元素可以选择该元素所处状态,成功选择后,右侧样式框内即出现相应的样式显示,使用相同的方法覆盖即可。
3.局部修改某一类iview组件的样式。
有时候我们并不想把整个页面的某一组件都渲染成一样的样式,仅仅想针对某一部分的样式进行修改,这个时候就需要局部修改样式。在局部修改时,我们特别需要注意父层样式的优先级高于子层样式,如果我们在父层中覆盖了iview组件的样式,那么子层中就算再覆盖该类样式,也不会产生作用。
通过深度作用选择器对某一vue组件中的样式进行修改
根据我的理解,如果在当前组件component1
的中对引用的其他组件componentn
,赋予css类名,如下所示,将vue组件MenuBar
和ControlPanel
的css类名分别设置为mymenu
和ControlPanel
<template>
<Layout>
<MenuBar class="mymenu"></MenuBar>
<ControlPanel class="mycontrol"></ControlPanel>
</Layout>
</template>
接着,我们在当前组件源码的style标签中加入scoped
属性,并在其中通过深度作用选择器,实现对单独的vue组件中iview样式的修改。比如,我们想要修改ControlPanel
组件中的.ivu-menu-dark.ivu-menu
类的样式,我们可以在组件中通过以下方式修改:
<style scoped>
.mycontrol >>> .ivu-menu-dark.ivu-menu {
background: #3f3f3f;
}
</style>
三、vue实现页面的自定义样式主题切换
在vue中实现页面的主题切换,实际上就是动态改变页面中元素的样式,同样分为单独和全局两种方式。
单独动态修改某一对象的样式
在该对象的tag中将vue变量绑定至style,写法如下:
<MenuItem name="1" :style="{'height':itemHeight, 'pointer-events':'none'}"></MenuItem>
此时,在脚本中控制itemHeight
变量的值即可实现对该对象样式中height
属性的修改。
动态修改当前模块css样式
在该模块的tag标签中将vue变量绑定为class,如下所示:
<Layout :class="controlTheme">
...
...
</Layout>
然后在当前vue组件源码中提前写好多种主题的css样式:
<style scoped>
.darkcontrol >>> .ivu-btn {
border-radius: 0px;
color: #f5f7f9;
background-color: #464e57;
border-color: #464e57;
margin: 0px;
border: 0px solid transparent;
padding: 6px 16px 6px;
margin: -3px;
}
.lightcontrol >>> .ivu-btn {
border-radius: 0px;
color: #4b4b4d;
background-color: #dddddd;
border-color: #bbbbbb;
margin: 0px;
border: 0px solid transparent;
padding: 6px 16px 6px;
margin: -3px;
}
...
...
...
</style>
此时通过脚本动态控制变量controlTheme
的值为主题类名,如darkcontrol
或lightcontrol
,即可实现对该类中css样式的动态切换。
在局部组件动态修改整个页面样式
之前我们说过添加transfer属性后的iview组件,在最终渲染时会直接被放到页面的<body>
层,这样的话无法使用第二种修改当前模块的css样式的方法来动态改变其样式,我们需要使用一种在局部组件修改整个<body>
样式的方法。具体方法如下:
在vue生命周期的beforeCreate阶段,动态为页面的最上层<body>
绑定类名,如下:
beforeCreate: function() {
document.getElementsByTagName("body")[0].className = "myLightDrop";
}
并在当前vue组件源码下修改该类的全局样式:
<style>
.myLightDrop .ivu-select-dropdown {
overflow: hidden;
max-height: 1000px;
color: #66ccff;
}
.myLightDrop .ivu-select-dropdown {
overflow: hidden;
max-height: 1000px;
color: #888888;
}
...
...
...
<style>
当发生切换主题的事件时,为<body>
再绑定其他写好的样式的类名:
changeTheme(status) {
document.getElementsByTagName("body")[0].className = status;
}
最后别忘了,在生命周期 beforeDestroy阶段去掉用于主题切换的额外绑定的类名:
beforeDestroy() {
document.body.removeAttribute("class", this.myDropTheme);
}