react-vue-tsx 基本使用

本文主要面向 react 开发人员快速上手 vue 的 .tsx 组件开发

Tsx

在 vue 项目中,如果不太熟悉、不想使用 .vue 模板语法的开发方式,可以通过 vite 相关插件,使用 tsx 进行组件编写。

优点:

  1. 可以使用更加灵活的 jsx 来进行开发;
  2. 可以单个文件里可以输出多个小组件;
  3. 更加灵活的 js 开发方式,不需要记 .vue 模版里的的魔法配置;
  4. 减少 all in one(页面组件代码 4000 + 行) 概率,文件内可以各种变量导出,重复内容也可以很方便的进行管理;
  5. 使用 model.confirm 等函数方式调用组件,可以很方便的个性化自定义标签,不需要频繁塞进 template 里,再声明 ref 来进行各种控制;

缺点:

  1. 无法使用 css scope,可以使用 css-modules 或者其他方式来进行样式隔离,组内习惯了 :deep 等方式透传的开发人员消费时,可能会不太适应;
  2. 其他成员难维护,未接触过 react 框架的 vue 开发人员,大概率无法接受和学习开发,需要靠你自己维护或者培训他们;
  3. .tsx 引用自己项目创建的 .vue 的组件,没有相关类型声明,需要自己手动或者通过其他手段添加声明类型;
  4. vue 重点还是放在 .vue 组件,后续 .tsx 更新优化力度不会太大;
  5. ref.value 这个 .value 使用时还是有点烦,绑定时经常需要注意;

Babel 设置

安装相关插件

npm i @vitejs/plugin-vue-jsx -D

vite.config.ts 设置

// vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'

export default {
  plugins: [
    vueJsx({
      // options are passed on to @vue/babel-plugin-jsx
    }),
  ],
}

创建组件

有以下几种方式创建组件

// 选项语法
function defineComponent(
  component: ComponentOptions
): ComponentConstructor

// 函数语法 (需要 3.3+)
function defineComponent(
  setup: ComponentOptions['setup'],
  extraOptions?: ComponentOptions
): () => any


// 函数组件
export const Button = props => {
  return <div>{props.name}</div>;
};

defineComponent

选项语法和函数语法只是写法不一样,看个人习惯,props 等变量,可以进行管理和复用。

import { ExtractPropTypes } from "vue";

export const ButtonProps = {
	name: {
		type: String,
		default: 'hello'
	}
}

export type ButtonPropsType = ExtractPropTypes<typeof ButtonProps>;

// 函数语法
export default defineComponent((props, { emit }) => {
  return () => {
    return <div>{props.name}</div>;
  };
}, {
  props: ButtonProps
});

// 选项语法
export const Button = defineComponent({
	props: ButtonProps,
	setup(props, ctx) {
		return () => {
			return <div></div>
		}
	}
})

函数组件

该方式无法函数内创建 State,能不用就不用,只适用于非常简单的组件,例如下面示例:

import { ref } from 'vue'

const RcButton = () => {
	const count = ref(0)
	function onClick() {
		count.value++
	}
	return (
		<div>
			<div> 数字 : {count.value}</div>
			<button onClick={onClick}>点我+1</button>
		</div>
	)
}

点击按钮后,视图仍然显示为 0,点击事件无任何作用。

是否能使用 React.FC<Props> 方式创建函数组件

是否能像 const component: FC<Props> = (props) => <div></div> 快速生成组件。只能说,看起来可以,但基本上不行,还是要写传统的 Props 变量来进行约束,如下所示:

defineComponent

看起来似乎可以传定义过去,而且使用时,编辑器也有相关提示

import { defineComponent } from 'vue'

interface ButtonProps {
	type: 'primary' | 'ghost',
	content: string
}

export default defineComponent<ButtonProps>((props) => {
	return () => {
		return <div>{props.content}</div>
	}
})

react-vue-tsx 基本使用

但组件使用后,传的值并没有传到 props 上,而是 attrs 上,只是看起来像生效了而已。

react-vue-tsx 基本使用

FunctionalComponent

虽然可以通过泛型来快速定义,props 也有值,编辑器有类型提示,但无法定义 State,基本上无用。

interface ButtonProps {
	type: string
}
const RcButton: FunctionalComponent<ButtonProps> = (props, { attrs }) => {
	console.log('props', props)
	console.log('attrs', attrs)
	return (
		<div>
			<div>{props.type}</div>
		</div>
	)
}

propsattrs 传值一样,将就的话也能用。

react-vue-tsx 基本使用

基本使用

简单的点击按钮,数字加一,代码如下所示:

import { defineComponent, type PropType } from 'vue'
import { useVModel } from '@vueuse/core'

export default defineComponent({
	props: {
		type: String as PropType<'primary' | 'warning'>,
		modelValue: {
			type: Number,
			required: true
		}
	},
	emits: ['update:modelValue'],
	setup(props, { emit }) {
      
		const count = useVModel(props, 'modelValue', emit, {
			defaultValue: 0
		})
		function onButtonClick() {
			count.value += 1
		}

		return () => {
			return (
				<div >
					<div>数字是 {count.value}</div>
					<button onClick={onButtonClick}>点我+1</button>
				</div>
			)
		}
	}
})

使用下来,结构上大概可以分三个区域:

react-vue-tsx 基本使用

第一区域:用于定义 propsemitslots 等相关外部属性。

第二区域:用于定义声明 state 组件内部状态,比如创建各种变量、refwatchcomputed 等相关操作,一些性质类似
于 React.Component 的 constructor,可以定义类型,只执行一次,不过能添加 watch,生命周期等相关操作。

第三区域:可以理解为 render 的函数,只要发生渲染,就会执行,不可以在这里进行 ref 声明,watch 相关操作等。

总结

刚开始接触 vue 的 .tsx 组件开发,可能很难绕过来弯,多实验几次,就能了解规则了。

原文链接:https://juejin.cn/post/7345404998165250059 作者:想吃糯米饭

(0)
上一篇 2024年3月13日 下午4:31
下一篇 2024年3月13日 下午4:42

相关推荐

发表回复

登录后才能评论