vue3新拟态组件库开发流程——radio组件源码

基础radio和禁用
亮点1:利用computed写一个get和set对象,根据这个对象来确定点击的是什么
亮点2:display:none掉选择框,用一个div造一个新的dom放上去样式

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useProp, useNeumorphism } from '../mixin/neumorphism'
const radio = ref() // 与html中ref=""对应,定位dom元素
const emit = defineEmits(['change','update:modelValue'])
const handleChange = (evt) => { nextTick(() => { if(props.disabled) return; model.value = props.label; emit('change', model.value) }) }
const props = defineProps({
    ...useProp,
    ...{
      modelValue: {
        type: [String, Number],
        default: ''
      },
      label: {
        type: [String, Number],
        default: ''
      },
      disabled: {
        type: Boolean,
        default: false
      },
    }
})
let model =  computed({
  get() {
      return props.modelValue
  },
  set(val) {
    
      emit('update:modelValue', val)
      radio.value && (radio.value.checked = model.value === props.label)
  }
})

const { baseStyleObject } = useNeumorphism(props)
let styleObject =  computed(() => ({ 
}))
</script>

<template>
  <div class="san-radio neumorphism" :class="[{'neumorphism-checked': model === label},{'is-disabled': disabled}]" @click="handleChange">
    <input ref="radio" :value="label" type="radio" v-model="model"/>
    <slot></slot>
    <template v-if="!$slots.default">{{label}}</template>
  </div>
</template>

<script>
export default {
  name: 'sanorin-radio',
}
</script>

<style scoped>
@import "../../style/index.css";
@import "../../style/neumorphism.css";
input{
  display: none;
}
.san-radio {
  display: inline-block;
  margin: 15px 0;
  padding: 8px;
  border-radius: 5px;
  cursor: pointer;
  user-select:none;
}
.san-radio + .san-radio{
    margin-left: 10px;
}
</style>

接下来写el-radio-group,用provide、inject接收group里的值,带响应式状态

// radio-group
<script setup>
import { computed, provide } from 'vue'
const emit = defineEmits(['update:modelValue'])

const props = defineProps({
  modelValue: {
    type: [String, Number],
    default: ''
  }
})
let radioGroupModelValue = computed(() => props.modelValue)
let updateRadioGroupModelValue = (e) => emit('update:modelValue', e)
provide('radioGroupModelValue',{ radioGroupModelValue, updateRadioGroupModelValue })
</script>

<template>
  <div class="san-radio-group" role="radiogroup">
      <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'sanorin-radio-group',
}
</script>

<style scoped>

</style>
<script setup>
import { ref, inject, computed, nextTick } from 'vue'
import { useProp, useNeumorphism } from '../mixin/neumorphism'
const radio = ref() // 与html中ref=""对应,定位dom元素
const emit = defineEmits(['change','update:modelValue'])
const handleChange = (evt) => { nextTick(() => { if(props.disabled) return; model.value = props.label; emit('change', model.value) }) }
const props = defineProps({
    ...useProp,
    ...{
      modelValue: {
        type: [String, Number],
        default: ''
      },
      label: {
        type: [String, Number],
        default: ''
      },
      disabled: {
        type: Boolean,
        default: false
      },
    }
})
const { radioGroupModelValue, updateRadioGroupModelValue } = inject('radioGroupModelValue') || {}
let model =  computed({
  get() {
      return radioGroupModelValue ? radioGroupModelValue.value : props.modelValue
  },
  set(val) {
    if (radioGroupModelValue) return updateRadioGroupModelValue(val)
    emit('update:modelValue', val)
  }
})
const { baseStyleObject } = useNeumorphism(props)
let styleObject =  computed(() => ({ 
}))
</script>

<template>
  <div class="san-radio neumorphism" :class="[{'neumorphism-checked': model == label},{'is-disabled': disabled}]" @click="handleChange">
    <input ref="radio" :value="label" type="radio" v-model="model"/>
    <slot></slot>
    <template v-if="!$slots.default">{{label}}</template>
    {{model == label}}
  </div>
</template>

<script>
export default {
  name: 'sanorin-radio',
}
</script>

<style scoped>
@import "../../style/index.css";
@import "../../style/neumorphism.css";
input{
  display: none;
}
.san-radio {
  display: inline-block;
  margin: 15px 0;
  padding: 8px;
  border-radius: 5px;
  cursor: pointer;
  user-select:none;
}
.san-radio + .san-radio{
    margin-left: 10px;
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值