手把手教你如何在vue3中使用tsx渲染组件(必看)

时间:2024-12-19 21:11:40

目录

一、使用

1、安装插件

2、在中引入

二、声明tsx组件的三种方式

1、函数式组件

 2、defineComponent() render的方式 Options API

 3、defineComponent() setup的方式 Composition API

三、使用tsx的语法

语法1(只允许一个根节点)

语法2(v-model、v-show)

语法3(v-if 无效,找替代)

语法4:v-for 使用map代替

语法5:插槽

语法6:事件绑定 on+事件名

语法7:通过props向子组件传参

语法8:emit 事件派发


一、使用

1、安装插件

  1. pnpm install @vitejs/plugin-vue-jsx -D
  2. 或 yarn add @vitejs/plugin-vue-jsx -D

2、在中引入

并在vue()后面添加上,所需的配置项 vueJsx,无配置就可以直接写为vueJsx()

  1. vueJsx({
  2. // options are passed on to @vue/babel-plugin-jsx
  3. // 选项配置也是通过babel去设置的
  4. }),

二、声明tsx组件的三种方式

1、函数式组件

  1. // 缺点:一些复杂的配置项无法设置
  2. export default () => <div>TestTsx</div>;

 2、defineComponent() render的方式 Options API

  1. export default defineComponent({
  2. // 其他配置,data/props...
  3. // 缺点:还要跟this打交道,访问变量需要用
  4. render() {
  5. return <div>TestTsx</div>;
  6. },
  7. });

 3、defineComponent() setup的方式 Composition API

  1. // defineComponent() setup Composition API
  2. export default defineComponent({
  3. // 其他配置,data/props...
  4. setup() {
  5. return () => <div>TestTsx1</div>;
  6. },
  7. });

三、使用tsx的语法

语法1(只允许一个根节点)

        vue3中允许多个根节点同时存在,tsx不允许,我们可以设置一个<></>空标签来包裹

语法2(v-model、v-show)

        v-model,v-show跟以前的用法类似,但注意后面不是双引号“”,而是大括号{}

        注意:v-model里面绑定变量需要加上 .value ,这也是与vue3的区别

  1. export default defineComponent({
  2. // 其他配置,data/props...
  3. setup() {
  4. const counter = ref(0);
  5. return () => (
  6. <>
  7. <div>TestTsx1</div>
  8. <input type="text" v-model={counter.value} />
  9. </>
  10. );
  11. },
  12. });

语法3(v-if 无效,找替代)

        需要用三目运算或&&来代替

 <div>{isflag ? <span>A</span> : <span>B</span>}</div>
  1. isActive && <p>123</p> //isActive === true的情况下,展示 && 后面的标签
  2. isActive && title==='123' && <p>123</p>
  3. //isActive === true && title==='123' 的情况下,展示 && 最后面的标签

语法4:v-for 使用map代替

  1. <div>
  2. {arr.value.map((item, i) => (
  3. <p key={i}>
  4. {item}--{i}
  5. </p>
  6. ))}
  7. </div>

 运行结果:

 语法5:插槽

        jsx 中想实现vue中的插槽写法也有很大不同,主要利用 v-slots 的指令来实现:

        插槽的三种接收方式:

 

  1. export default defineComponent({
  2. // 利用setup的第二个参数,可以接收插槽信息
  3. setup(props, { slots }) {
  4. return () => (
  5. <>
  6. 默认插槽:{slots.default && slots.default()}
  7. <br />
  8. 具名插槽:
  9. { && ()}
  10. {slots.content && slots.content()}
  11. <br />
  12. 作用域插槽:{ && ({ name: "作用域插槽内容" })}
  13. <br />
  14. </>
  15. );
  16. },
  17. });

 

  1. import Child from "./tchild";
  2. export default defineComponent({
  3. setup() {
  4. return () => (
  5. <>
  6. <Child
  7. v-slots={{
  8. title: () => <h2>我是标题</h2>, //具名插槽
  9. content: () => <h3>我是内容</h3>, //具名插槽
  10. suffix: (props: { name: string }) => <span>{}</span>, //作用域插槽
  11. }}
  12. >
  13. 我是默认插槽内容
  14. </Child>
  15. </>
  16. );
  17. },
  18. });

效果:

 疑问来了,那我不用 v-slots 其实也可以实现,为啥还要用。只是用v-slots显得比较正规好理解~

  1. <Child>
  2. {{
  3. default: "我是默认插槽的内容",
  4. title: () => <h2>我是标题</h2>,
  5. content: () => <h3>我是内容</h3>,
  6. suffix: (props: { name: string }) => <span>{}</span>,
  7. }}
  8. </Child>

语法6:事件绑定 on+事件名

        (小驼峰命名法)进行事件绑定

  1. export default defineComponent({
  2. emits: ["submit"],
  3. setup() {
  4. const handleClick = () => {
  5. alert("我被点击了");
  6. };
  7. return (props, { emit }) => (
  8. <>
  9. <buttion onClick={handleClick}>按钮</buttion>
  10. </>
  11. );
  12. },
  13. });

语法7:通过props向子组件传参

        看下面的例子,可以传递标签给子组件

  1. import Child from "./tchild";
  2. export default defineComponent({
  3. setup() {
  4. const msg = "我是来自父组件的消息";
  5. return () => (
  6. <>
  7. <Child msg={msg} childs={[<h3>我是一</h3>, <h3>我是二</h3>]}></Child>
  8. </>
  9. );
  10. },
  11. });

  1. export default defineComponent({
  2. props: {
  3. msg: String,
  4. childs: Array,
  5. },
  6. // 利用setup的第二个参数,可以接收插槽信息
  7. setup(props, { slots }) {
  8. (props);
  9. return () => (
  10. <>
  11. <p>{}</p>
  12. <p>{[0]}</p>
  13. </>
  14. );
  15. },
  16. });

语法8:emit 事件派发

vue中子向父传值都是emit的方式,这个在vue3中写法相似,只是多了一个定义emit的步骤,这也是为了后续的类型推导做准备

注意:父组件接收子组件发射的方法同样需要加上 on 

  1. import Child from "./tchild";
  2. export default defineComponent({
  3. setup() {
  4. const msg = "我是来自父组件的消息";
  5. const numClick = (val) => {
  6. alert(val);
  7. };
  8. return () => (
  9. <>
  10. <Child msg={msg} onNumClick={numClick}></Child>
  11. </>
  12. );
  13. },
  14. });

注意:子组件中需要添加 emits: ["numClick"],同vue3类似,vue3中也需要添加defineEmits将事件发射出去

  1. export default defineComponent({
  2. emits: ["numClick"],
  3. props: {
  4. msg: String,
  5. childs: Array,
  6. },
  7. // 利用setup的第二个参数,可以接收插槽信息
  8. setup(props, { emit }) {
  9. const count = ref(1);
  10. const childClick = () => {
  11. emit("numClick", count.value);
  12. };
  13. return () => (
  14. <>
  15. <Button onClick={childClick}>触发父组件事件</Button>
  16. </>
  17. );
  18. },
  19. });

 还有一些样式设置及进阶的知识,见下一篇文章哦~