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 设置

安装相关插件

shell 复制代码
npm i @vitejs/plugin-vue-jsx -D

vite.config.ts 设置

ts 复制代码
// vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'

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

创建组件

有以下几种方式创建组件

ts 复制代码
// 选项语法
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 等变量,可以进行管理和复用。

tsx 复制代码
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,能不用就不用,只适用于非常简单的组件,例如下面示例:

tsx 复制代码
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

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

tsx 复制代码
import { defineComponent } from 'vue'

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

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

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

FunctionalComponent

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

tsx 复制代码
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 传值一样,将就的话也能用。

基本使用

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

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>
			)
		}
	}
})

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

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

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

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

总结

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

相关推荐
前端小白从0开始2 小时前
Vue3项目实现WPS文件预览和内容回填功能
前端·javascript·vue.js·html5·wps·文档回填·文档在线预览
難釋懷3 小时前
Vue解决开发环境 Ajax 跨域问题
前端·vue.js·ajax
挑战者6668883 小时前
vue入门环境搭建及demo运行
前端·javascript·vue.js
程序猿ZhangSir5 小时前
Vue3 项目的基本架构解读
前端·javascript·vue.js
亲亲小宝宝鸭6 小时前
写了两个小需求,终于搞清楚了表格合并
前端·vue.js
Face6 小时前
路由Vue-router 及 异步组件
前端·javascript·vue.js
风之舞_yjf8 小时前
Vue基础(14)_列表过滤、列表排序
前端·javascript·vue.js
疯狂的沙粒8 小时前
uni-app 项目支持 vue 3.0 详解及版本升级方案?
前端·vue.js·uni-app
Lhuu(重开版9 小时前
Vue:Ajax
vue.js·ajax·okhttp
国家不保护废物9 小时前
从刀耕火种到现代框架:DOM编程 vs Vue/React 进化史
前端·vue.js·react.js