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

目录

一、使用

1、安装插件

2、在vite.config.ts中引入

二、声明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、安装插件

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

2、在vite.config.ts中引入

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

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

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

1、函数式组件

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

 2、defineComponent() render的方式 Options API

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

 3、defineComponent() setup的方式 Composition API

// defineComponent() setup Composition API
export default defineComponent({
  // 其他配置,data/props...
  setup() {
    return () => <div>TestTsx1</div>;
  },
});

三、使用tsx的语法

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

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

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

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

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

export default defineComponent({
  // 其他配置,data/props...
  setup() {
    const counter = ref(0);
    return () => (
      <>
        <div>TestTsx1</div>
        <input type="text" v-model={counter.value} />
      </>
    );
  },
});

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

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

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

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

<div>
   {arr.value.map((item, i) => (
      <p key={i}>
          {item}--{i}
      </p>
    ))}
</div>

 运行结果:

 语法5:插槽

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

        插槽的三种接收方式:

  child.tsx

export default defineComponent({
  // 利用setup的第二个参数,可以接收插槽信息
  setup(props, { slots }) {
    return () => (
      <>
        默认插槽:{slots.default && slots.default()}
        <br />
        具名插槽:
        {slots.title && slots.title()}
        {slots.content && slots.content()}
        <br />
        作用域插槽:{slots.suffix && slots.suffix({ name: "作用域插槽内容" })}
        <br />
      </>
    );
  },
});

 parent.tsx

import Child from "./tchild";
export default defineComponent({
  setup() {
    return () => (
      <>
        <Child
          v-slots={{
            title: () => <h2>我是标题</h2>, //具名插槽
            content: () => <h3>我是内容</h3>, //具名插槽
            suffix: (props: { name: string }) => <span>{props.name}</span>, //作用域插槽
          }}
        >
          我是默认插槽内容
        </Child>
      </>
    );
  },
});

效果:

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

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

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

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

export default defineComponent({
  emits: ["submit"],
  setup() {
    const handleClick = () => {
      alert("我被点击了");
    };
    return (props, { emit }) => (
      <>
        <buttion onClick={handleClick}>按钮</buttion>
      </>
    );
  },
});

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

parent.tsx

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

import Child from "./tchild";
export default defineComponent({
  setup() {
    const msg = "我是来自父组件的消息";
    return () => (
      <>
        <Child msg={msg} childs={[<h3>我是一</h3>, <h3>我是二</h3>]}></Child>
      </>
    );
  },
});

child.tsx

export default defineComponent({
  props: {
    msg: String,
    childs: Array,
  },
  // 利用setup的第二个参数,可以接收插槽信息
  setup(props, { slots }) {
    console.log(props);
    return () => (
      <>
        <p>{props.msg}</p>
        <p>{props.childs[0]}</p>
      </>
    );
  },
});

语法8:emit 事件派发

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

parent.tsx

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

import Child from "./tchild";
export default defineComponent({
  setup() {
    const msg = "我是来自父组件的消息";
    const numClick = (val) => {
      alert(val);
    };
    return () => (
      <>
        <Child msg={msg} onNumClick={numClick}></Child>
      </>
    );
  },
});

child.tsx

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

export default defineComponent({
  emits: ["numClick"],
  props: {
    msg: String,
    childs: Array,
  },
  // 利用setup的第二个参数,可以接收插槽信息
  setup(props, { emit }) {
    const count = ref(1);
    const childClick = () => {
      emit("numClick", count.value);
    };
    return () => (
      <>
        <Button onClick={childClick}>触发父组件事件</Button>
      </>
    );
  },
});

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

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suoh's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值