vue实现自定义radio组件

效果展示

在这里插入图片描述

父组件中使用

<radio-group v-model="radioIschecked">
          <radio label="个人" value="1"></radio>
          <radio label="收藏" value="2"></radio>
</radio-group>

Radio.vue

<template>
  <div class="radio-wrap">
    <div class="left" :class="isChecked?'box-click':''" ref="box" @click="handleClick">
      <transition name="fade">
        <div class="circle" v-show="isChecked"></div>
      </transition>
    </div>
    <div class="right">{{label}}</div>
  </div>
</template>
<script lang='ts'>
import { Component, Vue, Watch, Prop } from "vue-property-decorator";
@Component({
  components: {}
})
export default class extends Vue {
  private isChecked: boolean = false;
  @Prop()
  private label!: string;
  @Prop()
  private value!: string;
  private handleClick() {
    this.isChecked = !this.isChecked;
    if (this.isChecked) {
      this.$parent.$emit("radioChange", this.value);
    }
  }
  private checkIsActive(value) {
    if (this.value === value) {
      this.isChecked = true;
    } else {
      this.isChecked = false;
    }
  }
}
</script>
<style scoped lang="scss">
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
.radio-wrap {
  height: 24px;
  display: inline-block;
  vertical-align: center;
  margin-bottom: 5px;
  .left {
    height: 24px;
    width: 24px;
    border-radius: 50%;
    background-color: #ffffff;
    display: inline-block;
    border: 1.2px solid #cccccc;
    box-sizing: border-box;
    .circle {
      margin-left: 9px;
      margin-top: 9px;
      border-radius: 50%;
      width: 6px;
      height: 6px;
      background-color: #ffffff;
    }
  }
  .left:hover {
    cursor: pointer;
  }
  .right {
    margin-left: 5px;
    padding-right: 10px;
    display: inline;
    vertical-align: top; // 内联元素默认的vertical-align为baseline。对象的内容与基线对齐。如果我们在right插入文字。则为出现left right不水平对齐的情况
    line-height: 24px;
    color: #66757f; // 在mounted
    font-size: 15px;
  }
  .box-click {
    background-color: #1da1f2;
    border: 0.5px solid #cccccc;
  }
}
</style>

RadioGroup.vue

<template>
  <div class="radio-group-wrap">
    <slot></slot>
  </div>
</template>
<script lang='ts'>
import { Component, Vue, Watch, Prop } from "vue-property-decorator";
@Component({
  components: {}
})
export default class extends Vue {
  @Prop()
  private value!: string;
  private dispatch(value) {
    // 调用所有子组件的checkIsActive方法
    this.$children.forEach(item => {
      const temp: any = item; // ts还是不好用。。。
      temp.checkIsActive(value);
    });
  }
  private radioChange(value) {
    this.$emit("input", value);
    this.dispatch(value);
  }
  private mounted() {
    if (this.value) {
      this.dispatch(this.value);
    }
    this.$on("radioChange", this.radioChange);
  }
}
</script>
<style scoped lang="scss">
</style>

这里script部分是用ts写的,你可以改成js的语法。template和style部分不用改。

发布了51 篇原创文章 · 获赞 18 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_42565137/article/details/99704160
今日推荐