> 文档中心 > 使用Vue封装一个switch组件

使用Vue封装一个switch组件

参数支持:
使用Vue封装一个switch组件

一、switch组件

  1. 基本框架和样式
<template>  <div>      <span class="x_switch_core">   <span class="x_switch_btn">   </span>      </span>  </div></template><script>export default {    name: 'TwoSwitch',}</script><style lang="scss" scoped>.x_switch {  display: inline-flex;  align-items: center;  position: relative;  font-style: 14px;  line-height: 20px;  height: 20px;  vertical-align: middle;  .x-switch-input {    position: absolute;    width: 0;    height: 0;    opacity: 0;    margin: 0;  }  .x_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 0.3s, background-color 0.3s;    vertical-align: middle;    .x_switch_btn {      position: absolute;      top: 1px;      left: 1px;      border-radius: 100%;      transition: all 0.3s;      width: 16px;      height: 16px;      background: #fff;    }  }}// 选中的样式.x-switch-checked {  .x_switch_core {    border-color: #409eff;    background-color: #409eff;    .x_switch_btn {      transform: translateX(20px);    }  }}</style>
  1. 双向数据绑定
    使用Vue封装一个switch组件

在父组件中使用v-model绑定数据,在子组件内获取value属性,并定义一个点击事件(绑定回调函数)与父组件通信,改变父组件中的绑定值。

  • 父组件中:
   <two-switch v-model="swFlag"></two-switch>
  • 子组件中,点击时改变is-checked类状态看,触发滑块滑动 :
<template>  <div   @click="switchClick"  class="x_switch"  :class="{'x-switch-checked':value}">      <span class="x_switch_core">   <span class="x_switch_btn">   </span>      </span>      <input type="checkbox" class="x-switch-input" :name="name" ref="input">  </div></template>

将input事件触发出去,点击取反:
此时点击页面中的switch,value值会更新。

methods:{   switchClick(){ this.$emit('input',!this.value)    }}

使用Vue封装一个switch组件
此时,页面上组件是这个效果,value值已经实现双向绑定。
但是,我们想要看到页面上组件的切换后的效果。可以给switch组件添加滑动样式。

滑动样式:

// 选中的样式.x-switch-checked {  .x_switch_core {    border-color: #409eff;    background-color: #409eff;    .x_switch_btn {      transform: translateX(20px);    }  }}

此时,点击switch时,可以改变颜色。

  1. 实现switch 颜色自定义
    首先,需要父组件传入颜色的值,在子组件中接收。
  • 父组件传递颜色参数:
 <two-switch     v-model="swFlag"    active-color="yellow"    inactive-color="red"></two-switch>
  • 子组件中定义ref="core"以确定要改变颜色的dom节点。
  <div   @click="switchClick"  class="x_switch"  :class="{'x-switch-checked':value}">      <span class="x_switch_core" ref="core">   <span class="x_switch_btn">   </span>      </span>      <input type="checkbox" class="x-switch-input" :name="name" ref="input">  </div>

通过mouted钩子,在刚进入页面以及value改变时对颜色进行改变:

props:{    value:{ type: Boolean, default: false    },    name:{ type: String, default: ''    },    activeColor: { type: String, default: ''    },    inactiveColor: { type: String, default: ''    }},mounted(){ this.setColor()    },methods:{    switchClick(){ // v-model 绑定的是 input 事件,子传父直接用input事件;如果不用input,则需要在父组件中用@事件 + v-bind绑定值  进行接收值, // 触发父组件中的事件  ,并传值 (子传父)this.$emit('input',!this.value)// 等待父组件的value值更新dom节点后 再调用this.$nextTick(()=>{    this.setColor()})    },    // 修改开关颜色    setColor(){ 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 }    }}
  1. 添加name属性
    当用户使用switch组件时,实际上是把它当成表单元素来使用。可能会用到组件的name属性,因此需要在switch组件中添加一个checkbox,并且当值改变的时候,也需要设置checkbox的value值。

switch组件中加入input标签,并接收父组件传过来的name值:

<template>  <div   @click="switchClick"  class="x_switch"  :class="{'x-switch-checked':value}">      <span class="x_switch_core" ref="core">   <span class="x_switch_btn">   </span>      </span>      <input type="checkbox" class="x-switch-input" :name="name" ref="input">  </div></template>

接收name值:

props:{ name:{     type: String,     default: '' }    },

父组件中,传递 name值:

<two-switch     v-model="swFlag"    active-color="yellow"    inactive-color="red"    name="username"></two-switch>

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

//   隐藏input标签  .x-switch-input {    position: absolute;    width: 0;    height: 0;    opacity: 0;    margin: 0;  }

在页面加载和点击时(当value的值改变时)修改input的checked值,保证和switch组件的value值同步:

mounted(){ this.setColor()      },    methods:{ switchClick(){     // v-model 绑定的是 input 事件,子传父直接用input事件;如果不用input,则需要在父组件中用@事件 + v-bind绑定值  进行接收值,     // 触发父组件中的事件  ,并传值 (子传父)    this.$emit('input',!this.value)    // 等待父组件的value值更新dom节点后 再调用    this.$nextTick(()=>{ this.setColor()    }) }, // 修改开关颜色 setColor(){     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     }     // 控制checkbox的checked(使input的值与value同步)     this.$refs.input.checked = this.value }    }

最后,附上switch组件的全部代码:

<template>  <div   @click="switchClick"  class="x_switch"  :class="{'x-switch-checked':value}">      <span class="x_switch_core" ref="core">   <span class="x_switch_btn">   </span>      </span>      <input type="checkbox" class="x-switch-input" :name="name" ref="input">  </div></template><script>export default {    name: 'TwoSwitch',    data(){ return { }    },    props:{ value:{     type: Boolean,     default: false }, name:{     type: String,     default: '' }, activeColor: {     type: String,     default: '' }, inactiveColor: {     type: String,     default: '' }    },    mounted(){ this.setColor()      },    methods:{ switchClick(){     // v-model 绑定的是 input 事件,子传父直接用input事件;如果不用input,则需要在父组件中用@事件 + v-bind绑定值  进行接收值,     // 触发父组件中的事件  ,并传值 (子传父)    this.$emit('input',!this.value)    // 等待父组件的value值更新dom节点后 再调用    this.$nextTick(()=>{ this.setColor()    }) }, // 修改开关颜色 setColor(){     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     }     // 控制checkbox的checked(使input的值与value同步)     this.$refs.input.checked = this.value }    }}</script><style lang="scss" scoped>.x_switch {  display: inline-flex;  align-items: center;  position: relative;  font-style: 14px;  line-height: 20px;  height: 20px;  vertical-align: middle;//   不让input显示出来  .x-switch-input {    position: absolute;    width: 0;    height: 0;    opacity: 0;    margin: 0;  }  .x_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 0.3s, background-color 0.3s;    vertical-align: middle;    .x_switch_btn {      position: absolute;      top: 1px;      left: 1px;      border-radius: 100%;      transition: all 0.3s;      width: 16px;      height: 16px;      background: #fff;    }  }}// 选中的样式.x-switch-checked {  .x_switch_core {    border-color: #409eff;    background-color: #409eff;    .x_switch_btn {      transform: translateX(20px);    }  }}</style>

如何在父组件中使用?
引入并注册之后,添加:

<switch     v-model="swFlag"    active-color="yellow"    inactive-color="red"    name="username"></switch>
data(){    return {      swFlag: false;    }  }