SwitchOn.vue
<template>
<div class="switch-container">
<div id="ecllipse" :class="ecllipseInit" @click="$emit('switch')">
<div id="circle" :class="circleInit"></div>
<div id="word" :class="wordInit">{{ wordKey }}</div>
</div>
</div>
</template>
<script setup>
import { computed, toRefs } from 'vue';
defineOptions({
inheritAttrs: false // 禁止自动继承父组件中的标签属性
})
// 接收父组件传入的属性width,toggle
const props = defineProps({
'width': {
type: String,
default: '100px',
}
,
'toggle': {
type: Boolean,
default: true,
}
});
// 注册开关事件
defineEmits(['switch']);
// 本地使用与父组件绑定的属性(如:width,toggle)和通过发射事件switch绑定的方法(如:doToggleSwitch)
const { width, toggle } = toRefs(props);
// class样式属性绑定并初始化
const ecllipseInit = computed(() => {
return toggle.value ? 'ecllipse-right' : 'ecllipse-left';
});
const circleInit = computed(() => {
return toggle.value ? 'circle-right' : 'circle-left';
});
const wordInit = computed(() => {
return toggle.value ? 'word-left' : 'word-right';
});
const wordKey = computed(() => {
return toggle.value ? 'ON' : 'OFF';
});
// 其余标签属性绑定并初始化
const height = computed(() => {
return 0.4 * width.value.replace('px', '') + 'px';
})
const borderRadius = computed(() => {
return height.value.replace('px', '') / 2 + 'px';
})
const fontSize = computed(() => {
return (0.2 * width.value.replace('px', '') + 6) + 'px';
})
const lrdistance = computed(() => {
return 0.08 * width.value.replace('px', '') + 'px';
})
</script>
<style scoped>
.switch-container {
margin: auto;
width: v-bind(width);
height: v-bind(height);
position: relative;
}
#ecllipse {
width: v-bind(width);
height: v-bind(height);
border-radius: v-bind(borderRadius);
position: absolute;
box-shadow: 0px 0px 3px #000000;
}
#circle {
width: v-bind(height);
height: v-bind(height);
background-color: #ffffff;
border-radius: 50%;
position: absolute;
right: 0px;
}
#word {
width: v-bind(width);
font-size: v-bind(fontSize);
line-height: v-bind(height);
position: relative;
color: #ffffff;
}
.circle-left {
left: 0px;
}
.circle-right {
right: 0px;
}
.word-left {
text-align: left;
left: v-bind(lrdistance);
}
.word-right {
text-align: right;
right: v-bind(lrdistance);
}
.ecllipse-right {
background-color: #008000;
}
.ecllipse-left {
background-color: #416f41;
}
</style>
SwitchOn.vue自定义组件使用:App.vue
<script setup lang="js">
import SwitchButton from './SwitchButton.vue';
import { ref } from 'vue';
const toggled = ref(true);
function doToggleSwitch() {
toggled.value = !toggled.value;
}
</script>
<template>
<switch-button :toggle="toggled" @switch="doToggleSwitch"></switch-button>
</template>