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>
  
  export default {
    props: {
    //element就是下面element数据结构data里面对象
      element: {
        type: Object,
      },
      //id来自低代码平台,每个组件都有各自唯一的id
      id: {
        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 元素动态生成唯一的 id
          const 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"
        }
    }
]


export default 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”实现动画效果
在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部