包含以下内容
- tsx泛型
- defineComponent备用函数签名(Vue 3.3+)
- v-if v-for v-on v-model
- 作用域插槽
- 模板引用
- 自定义事件
直接上代码
父组件 Father.tsx
import { defineComponent, ref } from "vue";
import Child from "./Child";
/*
1.Vue 模板中 ref 变量是可以直接解构的,但是在 jsx 中不行,需要添加 .value
2.ctx 上下文对象是非响应式的,可以安全地解构:
3.
*/
const FatherTsx = defineComponent(
(props, { attrs, slots, emit, expose }) => {
const arr = ref<number[]>(Array.from(new Array(10).keys()));
const fatherHandler = () => {
console.log("father handler");
};
const child = ref()
const triggerChildMethod =()=>{
child.value?.childMethod()
}
const testAttrs = {
name:'testAttrs'
}
const testVModel = ref('initial value')
const updateVModel = (value:string)=>{
testVModel.value = value
}
return () => (
<>
<Child arr={arr.value} ref={child} onFatherHandler={fatherHandler} {...testAttrs} onClick={triggerChildMethod} modelValue={testVModel.value} onUpdate:modelValue={updateVModel}>{{
header: ({name}:{name:string}) => <div>{name}</div>,
default: ({name}:{name:string}) => `${name} slot`,
footer: ({name}:{name:string}) => [<div>{name} - one </div>, <div>{name} - two</div>]
}}</Child>
<button onClick={triggerChildMethod}>triggerChildMethod</button>
</>
);
},
{
}
);
export default FatherTsx;
子组件 Child.tsx
import { defineComponent, SetupContext, SlotsType, PropType, ref } from "vue";
interface IProps<T> {
arr: Array<T>;
modelValue: string;
}
interface IEmits {
fatherHandler(name: string): void;
click(e: MouseEvent): any;
"update:modelValue": (value: string) => void;
}
interface ISlots {
default: { name: string };
header: { name: string };
footer: { name: string };
}
/*
1.泛型语法与tsx语法重复,因此不能单独写<T>,要么写 <T,> 要么写 <T extends xxx>
2.onClick需要在自定义组件上的emits中进行声明,否则类型校验有问题
*/
const Child = defineComponent(
// Vue3.3+ defineComponent备用函数签名,可以使用泛型
<T extends number | string>(
props: IProps<T>,
{ attrs, slots, emit, expose }: SetupContext<IEmits, SlotsType<ISlots>>
) => {
function childMethod() {
console.log("childMethod");
}
function triggerVModel(e: any) {
emit("update:modelValue", e.target.value);
}
const testVif = ref(true);
expose({ childMethod });
console.log({ attrs, props });
return () => (
<>
{/* props, emitted events, event handlers, v-if v-model v-for*/}
<div {...attrs}>
{slots.header && slots.header({ name: "header" })}
{slots.default && slots.default({ name: "default" })}
{slots.footer && slots.footer({ name: "footer" })}
<button onClick={() => emit("fatherHandler", "123")}>
trigger emits
</button>
{testVif.value ? <div>v-if</div> : <div>v-else</div>}
<ul>
{props.arr.map((item: T) => {
return <li>{item}</li>;
})}
</ul>
<input
type="text"
value={props.modelValue}
onInput={triggerVModel}
placeholder="test V-Model"
/>
</div>
</>
);
},
{
props: {
arr: Array as PropType<Array<number | string>>,
modelValue: String,
},
slots: Object as SlotsType<ISlots>,
emits: ["fatherHandler", "click", "update:modelValue"],
}
);
export default Child;
如果对你有帮助的话就请点个赞吧