• vue封装自己的组件库 03.封装input+switch组件




    五、封装一个element-ui风格的input组件

    参数支持:

    参数名称参数描述参数类型默认值
    placeholder占位符string
    type文本框类型(text/password)stringtext
    disabled禁用booleanfalse
    clearable是否显示清空按钮booleanfalse
    show-password是否显示密码切换按钮booleanfalse
    namename属性string

    事件支持:

    事件名称事件描述
    blur失去焦点事件
    change内容改变事件
    focus获取焦点事件

    5.1input组件的基本框架和样式以及处理placeholde、type、name、disabled

    因为这部分与前面介绍的内容相同且比较简单,所以将这部分放在一起,不多做介绍了。

    这里需要注意的是,disabled属性为true时,输入框禁用,并且需要改变样式,之前在button组件封装的时候也用到了相同的方法,获取到值后动态设置组件样式。

    input组件的框架以及样式,获取到的数据以及数据处理:

    <template>
     <div class="one-input">
       <input
       class="one-input_inner"
       :class="{'is-disabled': disabled}"
       :placeholder="placeholder"
       :type="type"
       :name="name"
       :disabled="disabled">
     div>
    template>
    <script>
    export default {
      name: 'oneInput',
      components: {
      },
      props: {
        placeholder: {
          type: String,
          default: ''
        },
        type: {
          type: String,
          default: 'text'
        },
        name: {
          type: String,
          default: ''
        },
        disabled: {
          type: Boolean,
          default: false
        }
      },
      data () {
        return {}
      },
      methods: {}
    }
    script>
    <style lang="scss" scoped>
      .one-input{
        width: 100%;
        position: relative;
        font-size: 14px;
        display: inline-block;
        .one-input_inner{
          -webkit-appearance: none;
          background-color: #fff;
          background-image: none;
          border: 1px solid #dcdfe6;
          border-radius: 4px;
          box-sizing: border-box;
          color: #606266;
          display: inline-block;
          font-size: inherit;
          height: 40px;
          line-height: 40px;
          outline: none;
          padding: 0 15px;
          transition: border-color .2s cubic-bezier(.645,045,.355,1);
          width: 100%;
     
          &:focus{
            outline: none;
            border-color: #409eff;
          }
          // input禁用样式
          &.is-disabled{
            background-color: #f5f7fa;
            border-color: #e4e7ed;
            color: #c0c4cc;
            cursor:not-allowed;
          }
        }
      }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    父组件中传值也是与之前一样的:

     <input :value="username" @input="username=$event.target.value"/>
    
    • 1

    5.2v-model语法糖——实现双向数据绑定

    当我们给一个input标签进行双向数据绑定时,我们需要使用value绑定数据,再使用input事件监听标签内数据的变动,如下:

    • :value=“username” 使得我们可以设置变量修改表单的value的值 控制值
    • @input=“username=$event.target.value”/ 使得表单的值改动后会更新我们的变量 值反馈
    <input :value="username" @input="username=$event.target.value"/>
    
    • 1

    在封装input组件时,这样显然是不合适的,所以这里我们需要使用到v-model语法糖。

    显然,我们是不能给我们封装的input组件直接使用v-model绑定数据的,但是由于v-model的特性,他将value值绑定在了组件上,所以,我们组件内部通过接收value值的方式,就可以接收到传入的数据;并且v-model也实现了input事件,在组件内部绑定的input事件作为回调,把value值返回给父组件,这样就实现了input组件的双向绑定了。

    父组件中的使用v-model绑定:

    <one-input v-model="username">one-input>
    
    • 1
    • 注意v-model=“username” 等价于 :value=“username” @input=“username=$event.target.value” 子组件会接受到父组件传的value (注意需要接受)
    • 组件内部需要修改value的值 但不能直接 this.value = e.target.value 无法直接修改父组件传过来的值 这里又用到了v-model的实质 这里通过传递事件的方式 触发@input方法 并把我们的值传过去

    组件内部绑定value值以及实现回调:

    //绑定value值和input事件  
     <input
       class="one-input_inner"
       :class="{'is-disabled': disabled}"
       :placeholder="placeholder"
       :type="type"
       :name="name"
       :value="value"
       @input="handleInput"
       :disabled=disabled>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //绑定input事件进行回调
        handleInput (e) {
          this.$emit('input', e.target.value)
        }
    
    • 1
    • 2
    • 3
    • 4

    5.3实现clearable功能和showPassword功能

    当我们在组件中键入clearable属性时,我们希望组件可以有一个一键删除数据得功能。

    当input组件的type属性是password时,我们希望在给与show-password属性时,可以有一个显示和隐藏密码的按钮。

    实现这个两个功能,除了基本的父子组件传值外,还要添加i标签的icon字体图标,以及实现功能。

     <div class="one-input" :class="{'one-input_suffix':showSuffix}">
       <input
       class="one-input_inner"
       :class="{'is-disabled': disabled}"
       :placeholder="placeholder"
       :type="type"
       :name="name"
       :value="value"
       @input="handleInput"
       :disabled=disabled>
      <span class="one-input_suffix">
       <i class="on-input_icon one-icon-cancel"v-if="clearable && value" @click="clear">i>
       <i class="on-input_icon one-icon-visible" v-if="showPassword && type=='password'" @click="handlePassword">i>
     span>
     div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    样式:

    .one-input_suffix{
        .one-input_inner{
            padding-right: 30px;
        }
        .one-input_suffix{
            position: absolute;
            right: 10px;
            height: 100%;
            top: 0;
            line-height: 40px;
            text-align: center;
            color: #c0c4cc;
            transition: all .3s;
            z-index: 900;
            i{
                color: #c0c4cc;
                font-size: 14px;
                cursor: pointer;
                transition: color .2s cubic-bezier(.645,.045,.355,1);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5.3.1实现clearable功能

    首先获取父组件传递的clearable值,然后给i标签绑定一个点击事件,这个事件触发input事件回调,当点击叉号字体图标时,将父组件的value清空:

    clear () {
        this.$emit('input', '')
    }
    
    • 1
    • 2
    • 3

    5.3.2实现showPassword功能

    实现showPassword功能的思路很简单,就是改变input的type类型即可。但是,我们不能直接改变父组件传递过来的type值,但是我们可以使用判断type值的方式,实现type的改变。

    首先设置一个布尔类型的变量,并且设置点击事件改变这个变量:

     data () {
        return {
          // 显示是否显示密码框
          passwordVisible: false
        }
      },
    methods: {
        handlePassword () {
          this.passwordVisible = !this.passwordVisible
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    然后我们需要在绑定type值时,进行两重判断。

    第一步、判断showPassword是否为真;第二步、如果为真则通过passwordVisible去判断type为text还是password,以此来控制隐藏和现实,否则type值就为传入的type值即可:

    :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
    
    • 1

    切换显示按钮点击时的颜色

    <i
       class="my-input_icon my-icon-visible"
       v-if="showPassword && type == 'password'"
       @click="handlePassword"
       :class="{'my-icon-view-active':passwordVisible}"
       >i>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    .my-input_suffix {
      .my-input_inner {
        padding-right: 30px;
      }
      .my-input_suffix {
        position: absolute;
        right: 10px;
        height: 100%;
        top: 0;
        line-height: 40px;
        text-align: center;
        color: #c0c4cc;
        transition: all 0.3s;
        z-index: 900;
        i {
          color: #c0c4cc;
          font-size: 14px;
          cursor: pointer;
          transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
        }
        .my-icon-view-active {
          color: blue;
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    --------------------------------------------------至此,input组件封装完成-------------------------------------------------

    附组件全部代码:

    <template>
      <div class="my-input" :class="{ 'my-input_suffix': showSuffix }">
        <input
          class="my-input_inner"
          :class="{ 'is-disabled': disabled }"
          :name="name"
          :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
          :placeholder="placeholder"
          :disabled="disabled"
          :value="value"
          @input="handleInput"
        />
        <span class="my-input_suffix">
          <i
            class="my-input_icon my-icon-cancel"
            v-if="clearable && value"
            @click="clear"
          >i>
          <i
            class="my-input_icon my-icon-visible"
            v-if="showPassword && type == 'password'"
            @click="handlePassword"
            :class="{'my-icon-view-active':passwordVisible}"
          >i>
        span>
      div>
    template>
    
    <script>
    export default {
      name: "my-input",
      data() {
        return {
          // 显示是否显示密码框
          passwordVisible: false
        };
      },
      props: {
        placeholder: {
          type: String,
          default: "",
        },
        type: {
          type: String,
          default: "password",
        },
        name: {
          type: String,
          default: "",
        },
        disabled: {
          type: Boolean,
          default: false,
        },
        value: {
          type: String,
          default: "",
        },
        clearable: {
          type: Boolean,
          default: false,
        },
        showPassword: {
          type: Boolean,
          default: false,
        },
      },
      computed: {
        showSuffix() {
          return this.clearable || this.showPassword
        }
      },
      methods: {
        handleInput(e) {
          this.$emit("input", e.target.value);
        },
        clear() {
          this.$emit("input", "");
        },
        handlePassword () {
          this.passwordVisible = !this.passwordVisible
        }
      },
    };
    script>
    
    <style lang="scss" scoped>
    .my-input {
      width: 100%;
      position: relative;
      font-size: 14px;
      display: inline-block;
      .my-input_inner {
        -webkit-appearance: none;
        background-color: #fff;
        background-image: none;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        box-sizing: border-box;
        color: #606266;
        display: inline-block;
        font-size: inherit;
        height: 40px;
        line-height: 40px;
        outline: none;
        padding: 0 15px;
        transition: border-color 0.2s cubic-bezier(0.645, 045, 0.355, 1);
        width: 100%;
    
        &:focus {
          outline: none;
          border-color: #409eff;
        }
        // input禁用样式
        &.is-disabled {
          background-color: #f5f7fa;
          border-color: #e4e7ed;
          color: #c0c4cc;
          cursor: not-allowed;
        }
      }
    }
    .my-input_suffix {
      .my-input_inner {
        padding-right: 30px;
      }
      .my-input_suffix {
        position: absolute;
        right: 10px;
        height: 100%;
        top: 0;
        line-height: 40px;
        text-align: center;
        color: #c0c4cc;
        transition: all 0.3s;
        z-index: 900;
        i {
          color: #c0c4cc;
          font-size: 14px;
          cursor: pointer;
          transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
        }
        .my-icon-view-active {
          color: blue;
        }
      }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148

    六、封装一个element-ui风格的switch组件

    参数支持:

    参数名参数描述参数类型默认值
    v-model双向绑定布尔类型false
    namename属性stringtext
    activeColor自定义的激活颜色string#1ec63b
    inactiveColor自定义的不激活颜色string#dd001b

    事件支持:

    事件名称事件描述
    changechange时触发的事件

    6.1switch组件的基本框架和样式

    switch组件基本框架:

    <template>
      <div class="one-switch">
        <span class="on-switch_core">
          <span class="one-switch_button">span>
        span>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    switch组件样式:

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    6.2实现switch组件的数据双向绑定

    实现switch组件数据双向绑定和input组件相同,使用v-model语法糖即可。

    在父组件种通过v-model绑定数据,在组件内部获取value属性,并且定义一个回调函数与父组件通信,改变父组件中的绑定值即可。

    父组件:

    <one-switch v-model="active" >one-switch>
    
    • 1

    子组件,点击时改变is-checked类状态,触发滑块滑动:

    <div class="one-switch" :class="{'is-checked':value}" @click="handleClick">
      <span class="one-switch_core">
        <span class="one-switch_button">span>
      span>
    div>
     
      props: {
        value: {
          type: Boolean,
          default: false,
        },
      },
      methods: {
        handleClick () {
          this.$emit('input', !this.value)
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    滑动样式:

      // 选中样式
      .is-checked {
        .one-switch_core{
          border-color: #409eff;
          background-color: #409eff;
          .one-switch_button {
            transform: translateX(20px);
          }
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6.3实现switch组件颜色自定义

    自定义switch组件的颜色,首先需要传入颜色的值,在子组件中获取后,使用ref获取节点,将背景颜色改变为对应颜色即可。

    父组件传递色彩参数:

    <one-switch
    -model="active"
    ctive-color="#13ce66"
    inactive-color="#ff4949"
    >one-switch>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    子组件中定义ref="core"以确定节点:

     <div class="one-switch" :class="{'is-checked':value}" @click="handleClick">
        <span class="one-switch_core" ref="core">
          <span class="one-switch_button">span>
        span>
      div>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方式1:通过mouted钩子和watch监听,在刚进入页面以及value改变时对颜色进行改变:

      mounted () {
        // 修改开关颜色
        if (this.activeColor || this.inactiveColor) {
          var color = !this.value ? this.activeColor : this.inactiveColor
          this.$refs.core.style.borderColor = color
          this.$refs.core.style.backgroundColor = color
        }
      },
      watch: {
        'value' (e) {
        // 修改开关颜色
          if (this.activeColor || this.inactiveColor) {
            var color = !e ? this.activeColor : this.inactiveColor
            this.$refs.core.style.borderColor = color
            this.$refs.core.style.backgroundColor = color
          }
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    方式2: nexttick 解决子组件上传给父组件 父组件反馈子组件

    • 首先在mounted加载后修改颜色值

      methods: {
          setColor() {
              console.log(123);
              console.log(this.activeColor || this.inactiveColor);
              if(this.activeColor || this.inactiveColor){
                  let color = this.value?this.activeColor:this.inactiveColor;
                  this.$refs.core.style.borderColor = color
                  this.$refs.core.style.backgroundColor = color
              }
          }
        },
        mounted() {
            this.setColor()
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      发现颜色一致[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iHEFfOvz-1658968721486)(switch.gif)]

      因为switch是切换两种颜色 mounted只触发一次

    • 绑定点击事件进行改动

      methods: {
          handleClick() {
            this.$emit("input", !this.value);
            this.setColor()
          },
          setColor() {
              if(this.activeColor || this.inactiveColor){
                  let color = this.value?this.activeColor:this.inactiveColor;
                  console.log(color);
                  this.$refs.core.style.borderColor = color
                  this.$refs.core.style.backgroundColor = color
              }
          }
        },
        mounted() {
            this.setColor()
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

      发现新的问题 初始状态switch状态时false 但是组件内查询到按钮事件点击后 switch状态依旧为false 因为状态更新后 父组件没有及时更新给子组件 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U5JYQRvY-1658968721487)(Animation.gif)]

    • 添加this.$nexttick解决问题

      //写法1
      handleClick() {
          this.$emit("input", !this.value);
          this.$nextTick(() => {
              this.setColor();
          });
      },
      //写法2
       handleClick() {
          this.$emit("input", !this.value);
          this.$nextTick().then(() => {
              this.setColor();
          });   
      },
      //写法3
      async handleClick() {
          this.$emit("input", !this.value);
          //   this.$nextTick(() => {
          //     this.setColor();
          //   });
          //   this.$nextTick().then(() => {
          //     this.setColor();
          //   });
          await this.$nextTick();
          this.setColor();
      },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

    6.4name属性支持

    用户在使用switch组件的时候,实质上是当成表单元素来使用的。因此可能会用到组件的name属性。所以需要在switch组件中添加一个checkbox,并且当值改变的时候,也需要设置checkbox的value值。

    加入input标签:

    <template>
      <div class="one-switch" :class="{'is-checked':value}" @click="handleClick">
        <span class="one-switch_core" ref="core">
          <span class="one-switch_button">span>
        span>
        <input type="checkbox" class="one-switch_input" :name="name" ref="input">
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    设置标签样式,因为input标签只作为name绑定使用,所以将其隐藏起来:

      // 隐藏input标签
      .one-switch_input{
        position:absolute;
        width: 0;
        height: 0;
        opacity: 0;
        margin: 0;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们在页面加载和点击时修改input的checked值,保证可以和value值同步:

      mounted () {
        // 修改开关颜色
        if (this.activeColor || this.inactiveColor) {
          var color = !this.value ? this.activeColor : this.inactiveColor
          this.$refs.core.style.borderColor = color
          this.$refs.core.style.backgroundColor = color
        }
        // 控制checkbox的值,input值同步value值
        this.$refs.input.checked = this.value
      },
      methods: {
        handleClick () {
          this.$emit('input', !this.value)
          // 控制checkbox的值,input值同步value值
          this.$refs.input.checked = this.value
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    --------------------------------------------------------------至此,switch组件封装完成--------------------------------------------------

    附switch组件代码:

    <template>
      <div class="one-switch" :class="{'is-checked':value}" @click="handleClick">
        <span class="one-switch_core" ref="core">
          <span class="one-switch_button">span>
        span>
        <input type="checkbox" class="one-switch_input" :name="name" ref="input">
      div>
    template>
    <script>
    export default {
      name: 'oneSwitch',
      components: {
      },
      props: {
        value: {
          type: Boolean,
          defualt: false
        },
        activeColor: {
          type: String,
          defualt: ''
        },
        inactiveColor: {
          type: String,
          defualt: ''
        },
        name: {
          type: String,
          defualt: ''
        }
      },
      mounted () {
        // 修改开关颜色
        if (this.activeColor || this.inactiveColor) {
          var color = !this.value ? this.activeColor : this.inactiveColor
          this.$refs.core.style.borderColor = color
          this.$refs.core.style.backgroundColor = color
        }
        // 控制checkbox的值,input值同步value值
        this.$refs.input.checked = this.value
      },
      watch: {
        'value' (e) {
        // 修改开关颜色
          if (this.activeColor || this.inactiveColor) {
            var color = !e ? this.activeColor : this.inactiveColor
            this.$refs.core.style.borderColor = color
            this.$refs.core.style.backgroundColor = color
          }
        }
      },
      data () {
        return {}
      },
      methods: {
        handleClick () {
          this.$emit('input', !this.value)
          // 控制checkbox的值,input值同步value值
          this.$refs.input.checked = this.value
        }
      }
    }
    script>
    <style lang="scss" scoped>
      .one-switch{
        display: inline-block;
        align-items: center;
        position: relative;
        font-size: 14px;
        line-height: 20px;
        vertical-align: middle;
        .one-switch_core{
        margin: 0;
        display: inline-block;
        position: relative;
        width: 40px;
        height: 20px;
        border: 1px solid #dcdfe6;
        outline: none;
        border-radius: 10px;
        box-sizing: border-box;
        background: #dcdfe6;
        cursor: pointer;
        transition: border-color .3s,background-color .3s;
        vertical-align: middle;
        .one-switch_button{
          position:absolute;
          top: 1px;
          left: 1px;
          border-radius: 100%;
          transition: all .3s;
          width: 16px;
          height: 16px;
          background-color: #fff;
          }
        }
      }
      // 选中样式
      .is-checked {
        .one-switch_core{
          border-color: #409eff;
          background-color: #409eff;
          .one-switch_button {
            transform: translateX(20px);
          }
        }
      }
      // 隐藏input标签
      .one-switch_input{
        position:absolute;
        width: 0;
        height: 0;
        opacity: 0;
        margin: 0;
      }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
  • 相关阅读:
    C++中栈与堆数据存取情况
    从手工测试转自动化测试前,你必须知道的9大内容
    Vant组件库 引入 阿里矢量图 添加自己喜欢的 ICON
    Java项目:婚纱影楼摄影商城系统(java+SSM+JSP+jQuery+Mysql)
    MySQL select加锁分析
    CSS总结第七天
    中考理化生实验操作考试平台
    UE5蓝图-事件、函数、事件分发器
    基于Java的插件化集成项目实践
    【UniApp】-uni-app-CompositionAPI应用生命周期和页面生命周期
  • 原文地址:https://blog.csdn.net/a2274001782/article/details/126026896