概述
1、checkbox.vue
<template>
<div class="z-checkbox">
<span class="z-checkbox__input">
<input
type="checkbox"
v-model="model"
:checked="isChecked"
@change="handleChange"
:name="name"
:disabled="disabled"
:indeterminate="indeterminate"
:value="label"
/>
<!-- vue的特点 如果对于checkbox而言 绑定的数据是数组,那么value在v-model中的数据中则被选中 -->
</span>
<span class="z-checkbox-label">
<slot>{{label}}</slot>
</span>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { useCheckbox } from "./useCheckbox";
export default defineComponent({
name: "ZCheckbox",
props: {
// 属性校验 vue2 里面也是一样
name: String,
indeterminate: Boolean,
checked: Boolean,
disabled: Boolean,
label: [String, Number, Boolean],
modelValue: [String, Number, Boolean],
},
emits: ["update:modelValue", "change"], // ts没提示 而且方法会被绑定到根上
setup(props, { emit, attrs }) {
return useCheckbox(props);
},
});
</script>
2、checkbox.types
import { ComputedRef } from "vue";
export interface ICheckboxProps {
indeterminate?: boolean, // 是否半选
checked?: boolean, // 是否选中
name?: string, // 原生的name
disabled?: boolean, // 是否禁用
label?: string | number | boolean, // 目前没有 group中使用
modelValue?: string |number | boolean // 绑定checkbox的值
}
// ts中接口中的可有可无
export interface ICheckboxGroupProvide{
modelValue?:ComputedRef,
changeEvent?: (val:unknown) => void,
name?:string
}
2、useCheckbox.ts
import { computed, getCurrentInstance, inject, WritableComputedRef } from "vue";
import { ICheckboxGroupProvide, ICheckboxProps } from "./ckeckbox.types";
const useCheckboxGroup = () => {
const checkboxGroup = inject<ICheckboxGroupProvide>('ZCheckboxGroup', {})
const isGroup = checkboxGroup.name == 'ZCheckboxGroup'; // 判断有没有父亲叫ZCheckboxGroup
return {
isGroup,
checkboxGroup
}
}
const useModel = (props: ICheckboxProps) => {
// getCurrentInstance是vue3中用于获取组件的上下文
const { emit } = getCurrentInstance(); // 以前只有checkbox的时候 用户会传递modelValue
const { isGroup, checkboxGroup } = useCheckboxGroup();
const store = computed(() => checkboxGroup ? checkboxGroup.modelValue?.value : props.modelValue); // 从爸爸的modelValue取出来 传递给自己, type="checkbox" 可以绑定数组
const model = computed({
get() {
return isGroup ? store.value : props.modelValue
},
set(val) {
if(isGroup){ // 只要是组 就需要触发组的更新方法,不触发自己的
return checkboxGroup.changeEvent(val)
}
emit('update:modelValue', val);
}
});
return model
}
const useCheckboxStatus = (props: ICheckboxProps, model: WritableComputedRef<unknown>) => {
const isChecked = computed(() => {
const value = model.value; // 当前是不是选中的 [上海,深圳]
// todo...
if(Array.isArray(value)){ // 针对父组件传递过来的数组
return value.includes(props.label)
}else{ // 针对true false
return value
}
});
return isChecked
}
const useEvent = () => {
const { emit } = getCurrentInstance()
const handleChange = (e: InputEvent) => {
const target = e.target as HTMLInputElement;
emit('change', target.checked);
}
return handleChange
}
export const useCheckbox = (props: ICheckboxProps) => {
// 1.设计一个属性 这个属性采用的就是modelValue, 还能更改,更改的时候要触发一个事件,更新数据
let model = useModel(props);
// 2.需要给checkbox 设置一个checked的状态,等一会我们更改checkbox选中或者取消选中需要获取到checked状态
const isChecked = useCheckboxStatus(props, model);
// 3.创造一个change事件 可以触发绑定到自己身上的change
const handleChange = useEvent();
// 每次状态发生变化 都需要 调用changeEvent来触发更新
return {
model,
isChecked,
handleChange
}
}
3、checkbox-group.vue
<template>
<div class="z-checkbox-group">
<slot></slot>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, provide } from "vue";
export default defineComponent({
name: "ZCheckboxGroup",
props: {
modelValue: Array, // 还是需要 父组件将modelValue这个数组传递给儿子
},
emits: ["change", "update:modelValue"],
setup(props, { emit }) {
// vue3 provide inject computed watch getInstance
// 将props属性创造出一个新的来交给儿子
const modelValue = computed(() => props.modelValue);
const changeEvent = (val) => { // 儿子等会调用这个方法去通知更新
emit("change", val); // change
emit("update:modelValue", val); // v-model
};
provide('ZCheckboxGroup',{
name:'ZCheckboxGroup',
modelValue,
changeEvent
})
},
});
</script>
4.use.vue
<template>
<!-- 组件内部 会去 emit('update:modelValue',[]) checkVal = []-->
{{ checkVal }}
<z-checkbox-group v-model="checkVal" @change="checkboxChange">
<z-checkbox v-for="c in checks" :key="c" :label="c"></z-checkbox>
</z-checkbox-group>
</template>
5、useCheckbox.ts
import { ref } from "vue";
export function useCheckbox() {
// 定义数据尽量使用ref,方便视图更新
const checkVal = ref(['上海','深圳']);
const checks = ref(['上海','北京','天津','深圳']);
const checkboxChange = (val) =>{
console.log(val)
}
return {
checkVal,
checkboxChange,
checks
}
}
最后
以上就是含糊音响为你收集整理的vue3+ts实现checkbox-group组件的全部内容,希望文章能够帮你解决vue3+ts实现checkbox-group组件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复