1.技术:
“vue”: “^2.6.14”,
“element-ui”: “^2.15.6”,
2.需求:
**同一个页面存在多个switch组件时,
需要更改各自的高度、宽度、选择颜色、非选中颜色等样式
,
并且样式隔离
互不影响!**
3.效果图:
4.重要代码index.vue页面:
<template><div:id="id"><el-switch:ref="'mySwitch_' + id"v-model="element.data.value"@change="handelChange"></el-switch></div></template><script>exportdefault{props:{//element就是下面element数据结构data里面对象element:{type: Object,},//id来自低代码平台,每个组件都有各自唯一的idid:{type: String,},},data(){return{};},watch:{//使用watch,因为目前低代码平台性能问题,导致数据与视图不一致,不得已使用深度监听"element.data":{handler(val, oldVal){this.load();},deep:true,//因为低代码平台里数据结构层级深,所以加了deep深度监听},},methods:{//初始化绑定swtich组件的唯一dom元素id和新增style唯一的id,增加样式隔离load_init(){this.$nextTick(()=>{const switchComponent =this.$refs["mySwitch_"+this.id];// 为每个 .switch__core 元素动态生成唯一的 idconst switchCoreElement =
switchComponent.$el.querySelector(".el-switch__core");
switchCoreElement.id =`el-switch-core-${this.id}`;//为每个组件绑定唯一的style样式,增加样式隔离,强行覆盖原生样式const styleId =`style-el-switch-core-${this.id}`;let existingStyle = document.getElementById(styleId);if(!existingStyle){const style = document.createElement("style");
style.id = styleId;
style.innerHTML ="";
document.head.appendChild(style);}});},//根据上面新增的样式隔离,进行查询更改,以此覆盖原生的组件样式load(){this.$nextTick(()=>{const switchComponent = document.getElementById(`el-switch-core-${this.id}`);if(switchComponent){// 更新各个 switch 组件的样式
switchComponent.style.height =this.element.data.switcheight +"px";
switchComponent.style.width =this.element.data.switcWidth +"px";
switchComponent.style.borderRadius =this.element.data.switcheight /2+"px";if(this.element.data.value){
switchComponent.style.background =this.element.data.openColor;
switchComponent.style.borderColor =this.element.data.openColor;}else{
switchComponent.style.background =this.element.data.closeColor;
switchComponent.style.borderColor =this.element.data.closeColor;}const existingStyle = document.getElementById(`style-el-switch-core-${this.id}`);if(existingStyle){
existingStyle.innerHTML =`
#el-switch-core-${this.id}:after {
height: ${this.element.data.switcheight}px;
width: ${this.element.data.switcheight}px;
content: "";
position: absolute;
top: -1px;
left: 1px;
border-radius: 100%;
-webkit-transition: all .3s;
transition: all .3s;
background-color: ${this.element.data.circleColor};
}
.el-switch.is-checked #el-switch-core-${this.id}:after {
left: 100%;
margin-left: -${this.element.data.switcheight}px;
}
`;}}});},},created(){//初始化绑定swtich组件的唯一dom元素id和新增style唯一的id,增加样式隔离this.load_init();//根据上面新增的样式隔离,进行查询更改,以此覆盖原生的组件样式this.load();},};</script>
5.element数据结构:
let list =[{data:{value:false,openColor:"#409EFF",closeColor:"#DCDFE6",switcheight:22,switcWidth:40,circleColor:"#FFFFFF"}}]exportdefault list;
6.深度解析原理
6.1.
根据ref找到class为el-switch__core的dom元素,并且赋值唯一的id
6.2.
因为::after伪类不能直接修改,只能通过新增的style节点样式,来覆盖原生组件的样式;(新增的style增加唯一id进行组件样式隔离)
6.3.深入style样式,在控制台==》元素==》html节点==》head节点==>style节点
7.总结
element-ui框架的switch组件,实际就是input+span元素实现的,
其中switch的圆球是通过span的::after伪类绝对定位上去的,
通过“transition: all .3s”实现动画效果
版权归原作者 鱼干~ 所有, 如有侵权,请联系我们删除。