vue3怎么封装一个复选框,单选框,封装单选框组件。造轮子。

1、第一种方案  创建一个组件 checkbox.vue

<template>
  <div class="checkbox" @click="changeChecked()">
    <i v-if="checked" class="iconfont icon-checked"></i>
    <i v-else class="iconfont icon-unchecked"></i>
    <span v-if="$slots.default"><slot /></span>
  </div>
</template>
<script>
import { ref, watch } from "vue";
// v-model  ====>  :modelValue  +   @update:modelValue
export default {
  name: "checkbox",
  props: {
    modelValue: {
      type: Boolean,
      default: false,
    },
  },
  setup(props, { emit }) {
    const checked = ref(false)  //   第一种实现双向数据绑定
    const changeChecked = () => {
    checked.value = !checked.value
      // 使用emit通知父组件数据的改变
      emit('update:modelValue', checked.value)
     }
    // 使用侦听器,得到父组件传递数据,给checked数据
     watch(() => props.modelValue, () => {
     checked.value = props.modelValue
    }, { immediate: true })
    return { checked, changeChecked }
  },
};
</script>

<style scoped lang="scss">
.checkbox {
  display: inline-block;
  margin-right: 2px;
  .icon-checked {
    color: red;
    ~ span {
      color: red;
    }
  }
  i {
    position: relative;
    top: 1px;
  }
  span {
    margin-left: 2px;
  }
}
</style>

我们就可以使用组件了

<template>
  <div class="sub-category">
      <checkbox v-model="checkd"></checkbox>
  </div>
</template>

 2、种方案

<template>
  <div class="checkbox" @click="changeChecked()">
    <i v-if="checked" class="iconfont icon-checked"></i>
    <i v-else class="iconfont icon-unchecked"></i>
    <span v-if="$slots.default"><slot /></span>
  </div>
</template>
<script>
import { ref, watch } from "vue";
// v-model  ====>  :modelValue  +   @update:modelValue
import { useVModel } from "@vueuse/core"; // 一定要引入
export default {
  name: "checkbox",
  props: {
    a: {
      type: Boolean,
      default: false,
    },
  },
  setup(props, { emit }) {

    // 使用useVModel实现双向数据绑定v-model指令   第二种
    // 1. 使用props接收modelValue
    // 2. 使用useVModel来包装props中的modelValue属性数据
    // 3. 在使用checked.value就是使用父组件数据
    // 4. 在使用checked.value = '数据' 赋值,触发emit('update:modelvalue', '数据')

    // const checked = useVModel(props, "modelValue", emit);
    // 如果这边使用是 modelValue 给组件 v-model 默认就是 v-model  但是若果是个 a 

    const checked = useVModel(props, "a", emit);
    // 但是若果是个 a 给组件 v-model 就是 v-model:a="flag" 
    const changeChecked = () => {
      const newVal = !checked.value;
      // 通知父组件
      checked.value = newVal;
      // 让组件支持change事件
      emit("change", newVal);
    };
    return { checked, changeChecked };
  },
};
</script>
<style scoped lang="scss">
.checkbox {
  display: inline-block;
  margin-right: 2px;
  .icon-checked {
    color: red;
    ~ span {
      color: red;
    }
  }
  i {
    position: relative;
    top: 1px;
  }
  span {
    margin-left: 2px;
  }
}
</style>

就可以使用了

<template>
   <xtx-checkbox v-model:a="checkd"></xtx-checkbox>
    // const checked = useVModel(props, "a", emit);
    // 但是若果是给组件 使用v-model    写法就是就是 v-model:a="flag" 
</template>

如果不想使用  v-model:a="checkd"

<template>
   <xtx-checkbox v-model="checkd"></xtx-checkbox>

    
// 改一下组件代码
// const checked = useVModel(props, "modelValue", emit); 

//   props: {
//    modelValue: {
//      type: Boolean,
//      default: false,
//    },
//  },
</template>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有两把刷子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值