如何在 vue3 中使用 jsx/tsx?(上)

简介: 如何在 vue3 中使用 jsx/tsx?(上)

我们都知道,通常情况下我们使用 vue 大多都是用的 SFC(Signle File Component)单文件组件模式,即一个组件就是一个文件,但其实 Vue 也是支持使用 JSX 来编写组件的。这里不讨论 SFC 和 JSX 的好坏,这个仁者见仁智者见智。本篇文章旨在带领大家快速了解和使用 Vue 中的 JSX 语法,好让大家在 Vue 中遇到或使用 JSX 的时候能很快入手


JSX 如何用



这里以vite项目为例,要想在项目中使用 JSX,我们需要安装一个插件@vitejs/plugin-vue-jsx,这个插件可以让我们在项目中使用 JSX/TSX

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

安装完成之后在vite.config.ts进行一个配置即可

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx()],
});

接下来我们看一下如何使用 JXS?

首先第一种方式就是在.vue文件中使用,需要将 script 中的 lang 设置为tsx,在 setup 函数中返回模板

<script lang="tsx">
import { defineComponent } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    return () => <div>Hello World</div>;
  },
});
</script>

或者将.vue改成.tsx,注意:如果后缀为.tsx,需要将引入到这个组件的路径后缀去掉

import { defineComponent } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    return () => <div>Hello World</div>;
  },
});
//main.ts中引入
import { createApp } from "vue";
import "./style.css";
import App from "./App";
createApp(App).mount("#app");

此时页面上就会展示一个Hello World

第二种方式是函数式组件,因为函数式组件里没有 this 引用,所以 Vue 把 props 当作第一个参数传入,第二个参数 ctx 包含三个属性:attrs、emit 和 slots。它们分别相当于组件实例的 attrs、attrs、attrsemit 和 $slots 这几个属性。

//App.tsx
export default (props, ctx) => <div>Hello World</div>;

到这里我们不难发现,TSX 相比于 SFC 有一个特点,那就是它可以在一个文件中定义多个组件模板,比如

const Component1 = () => <div>Component1</div>;
const Component2 = () => <div>Component2</div>;
export default () => (
  <div>
    <Component1 />
    <Component2 />
  </div>
);

此时页面中便出现了我们定义的两个组件

image.png

接下来我们来看一下 JSX 在 vue 中的具体用法


插值



在 SFC 中使用插值的时候我们可以使用{{}}进行包裹,而在 JSX 中是使用{}进行包裹,例如

import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    const text = ref("Hello World");
    return () => <div>{text.value}</div>;
  },
});

这里需要注意的是在 SFC 模板中是不需要加.value的,但是 JSX 模板中则需要加.value


条件渲染(v-if)



在 SFC 中我们可以使用v-if进行条件渲染,如

<div>
  <div v-if="showyes">yes</div>
  <span v-else>no</span>
</div>

而在 JSX 中则没有了v-if,而是采用更接近原生的写法

import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    const showyes = ref(true);
    return () => <div>{showyes.value ? <div>yes</div> : <div>no</div>}</div>;
  },
});

除了v-if,大家可能还会想到另一个条件渲染方式v-show,JSX 中是支持使用v-show

import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    const showyes = ref(true);
    return () => (
      <div>
        <div v-show={showyes.value}>yes</div>
        <div v-show={!showyes.value}>no</div>
      </div>
    );
  },
});


列表循环(v-for)



在 SFC 中我们经常使用v-for进行列表循环渲染,如

<ul>
  <li v-for="{ index, item } in list" :key="index">{{ item }}</li>
</ul>

而在 JSX 中我们则需要改成使用 map 进行列表循环渲染

import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    const list = ref(["one", "two", "three"]);
    return () => (
      <div>
        {list.value.map((item, index) => (
          <div key={index}>{item}</div>
        ))}
      </div>
    );
  },
});

注意,JSX 中列表循环也是要加 key 的


事件绑定



事件绑定其实 JSX 与 SFC 就是写法上的区别,以click为例,在 SFC 中使用@click或者v-on:click进行事件绑定,在 JSX 中则使用onClick进行事件绑定

import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    return () => (
      <div
        onClick={() => {
          console.log("我被点击");
        }}
      >
        点击
      </div>
    );
  },
});

这里需要注意绑定的函数要使用箭头函数


事件修饰符



事件修饰符可以使用 vue 提供的withModifiers进行设置,如.self

import { defineComponent, ref, withModifiers } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    return () => (
      <div
        onClick={withModifiers(() => {
          console.log("我被点击");
        }, ["self"])}
      >
        点击
      </div>
    );
  },
});

但是对于 .passive、.capture 和 .once 事件修饰符,使用withModifiers并不生效,这里可以采用链式驼峰的形式进行设置,不如.once

import { defineComponent } from "vue";
export default defineComponent({
  name: "app",
  setup(props, ctx) {
    return () => (
      <div
        onClickOnce={() => {
          console.log("我被点击");
        }}
      >
        点击
      </div>
    );
  },
});
相关文章
|
2月前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
163 64
|
26天前
|
JavaScript API 数据处理
vue3使用pinia中的actions,需要调用接口的话
通过上述步骤,您可以在Vue 3中使用Pinia和actions来管理状态并调用API接口。Pinia的简洁设计使得状态管理和异步操作更加直观和易于维护。无论是安装配置、创建Store还是在组件中使用Store,都能轻松实现高效的状态管理和数据处理。
99 3
|
2月前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
57 8
|
2月前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
52 1
|
2月前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
58 1
|
20天前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
110 1
|
1月前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
2月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
56 1
vue学习第一章
|
2月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
52 1
|
2月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
46 1
vue学习第四章