JSX与Vue Template(SFC):React比Vue2.x更适合集成TS,Vue3+TSX境况几何
Author:zhoulujun Date:
在看
Vue3 + TSX 最佳实践?不存在的 https://juejin.cn/post/7007731144418394149
Vue 3 和 React 16.8 到底能多像 https://juejin.cn/post/6998038537950429220
写给vue转react的同志们(5 https://juejin.cn/post/7020215941422137381
vue转react指南 https://juejin.cn/post/7023356946052808734
感慨蛮多,文章的精华部分如下:
父组件
TSX 要用 defineComponent 包裹,并且只使用 setup(没有 data、methods、computed 等一级声明),返回值要是一个 render function,里面采用 JSX 的写法;
TSX(defineComponent) 中 components、props、emits 等的声明是省不了的,props 的声明我们看下文 Child 的实现;
@click 在 TSX 中要变为 onClick,自定义 emit 也要由 @child-click 变为 onChildClick。不过这里要注意,正如“短篇”中提到的,如果用了 TSX,像 onClick 这种可能引起无效重复 render 的问题,就需要使用者自己解决了;
注:如果在 template 中同时传入 @childClick 和 :onChildClick 会发生什么呢?
答案是:不管传入顺序如何,:onChildClick 都会覆盖掉 @childClick,有兴趣的同学可以验证一下。所以在 template 中,事件还是老老实实的用 @ 的好。
TSX 中的 ref 对象还是需要使用 .value 结尾,有点麻烦,但是编辑器会自动补全;
如果有多个slots,TSX 要像例子中一样,通过一个对象传入子组件。对象的 key 为 slot 的名字,value 为要传入的组件;
特别注意的就是 emits 和 slots 的特殊处理。另外,上例当中还存在一个比较大的问题,即 onChildClick 实际上会被编译器提示 TS 校验错误,但代码又是可运行的。要想解决这个问题,只能要求子组件不声明 emits,全部用 props.onXXX 代替,即放弃使用 emits(感觉不太合适)。这点现在是最难受的,笔者还没有想到一个好的解决方案。
子组件
注意两者 emits 声明的不同,SFC 中参考官网的例子(仅限类型的 props/emit 声明),TSX 中 Emit 的声明一定要是 type 格式而不能是 interface,这是由 FunctionalComponent 内部泛型处理逻辑决定的;
TSX 中可以使用解构赋值,这是一个组件二次封装的场景下很常用的一个语法;
slots 在 TSX 中以函数的形式调用,注意例子中的容错写法,防止没有 slot 传入时的报错;综上,在 Functional Componet 的场景下,选择 TSX 是个不错的决定。如果用 defineComponet 的方式实现 Child 应该是什么样呢?也顺便解答一下上面留下的一个疑问,关于 props 声明的问题。
Child.tsx 的普通写法
import { CSSProperties, defineComponent, PropType } from "vue"; interface Props { count: number; style: CSSProperties; } export default defineComponent({ props: { style: { type: Object as PropType<Props["style"]>, default: undefined, }, count: { type: Number as PropType<Props["count"]>, default: undefined, }, }, emits: ["childClick"], setup(props, ctx) { const { slots, emit } = ctx; return () => ( <div style={props.style}> <h1>This is Child</h1> {slots?.header && slots.header()} <button onClick={() => emit("childClick")}>Child Count++</button> <p>Child count is: {props.count}</p> {slots?.default && slots.default()} <p>Props' keys are: {Object.keys(props).join(", ")}</p> </div> ); }, });
转载本站文章《JSX与Vue Template(SFC):React比Vue2.x更适合集成TS,Vue3+TSX境况几何》,
请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue/8707.html