直接在*.vue文件(SFC)中使用JSX/TSX渲染函数,真香!
前言
在日常开发中vue
的模版语法在大多数情况都能够满足我们的需求,但是在一些复杂的业务场景中使用模版语法就有些麻烦了。这个时候灵活的JSX/TSX
渲染函数就能派上用场了,大多数同学的做法都是将*.vue
文件改为*.tsx
或者*.jsx
文件。其实我们可以直接在*.vue
文件中直接使用JSX/TSX
渲染函数。
什么场景需要使用JSX/TSX渲染函数
假设我们现在有这样的业务场景,在我们的页面中有个list
数组。我们需要去遍历这个数组,根据每一项的item去渲染不同的组件。如果tem的数据满足条件A,那么就渲染组件A。如果item的数据满足条件B,那么就渲染组件B。如果item的数据满足条件C,那么就渲染组件C。
如果我们使用vue模版语法去实现这个需求,我们的Page.vue
文件的代码就需要是这样的:
<template>
<template v-for="item in list">
<ComponentA v-if="isComponentA(item)" />
<ComponentB v-else-if="isComponentB(item)" />
<ComponentC v-else-if="isComponentC(item)" />
</template>
</template>
<script setup lang="ts">
import ComponentA from "./component-a.vue";
import ComponentB from "./component-b.vue";
import ComponentC from "./component-c.vue";
const list: Array<number> = [1, 5, 3, 2, 1];
const isComponentA = (item): boolean => {
return item % 3 === 0;
};
const isComponentB = (item): boolean => {
return item % 3 === 1;
};
const isComponentC = (item): boolean => {
return item % 3 === 2;
};
</script>
这样虽然可以实现功能,但是明显不够优雅,领导code review时看了直呼摇头。
在*.jsx/tsx文件中使用JSX/TSX渲染函数
此时机智的小伙伴会说,我们可以使用vue
的setup
方法使用JSX/TSX
渲染函数实现。确实可以,我们来看看具体实现的代码:
import { defineComponent } from "vue";
import ComponentA from "./component-a.vue";
import ComponentB from "./component-b.vue";
import ComponentC from "./component-c.vue";
export default defineComponent({
setup() {
const list = [1, 5, 3, 2, 1, 0];
function renderDataList(data: Array<number>) {
return data?.map((val) => {
if (val % 3 === 0) {
return <ComponentA />;
} else if (val % 3 === 1) {
return <ComponentB />;
} else {
return <ComponentC />;
}
});
}
return () => {
return <div>{renderDataList(list)}</div>;
};
},
});
首先我们需要将原来的Page.vue
文件改为Page.tsx
文件,然后我们需要将原来写在template
中的代码摞到setup
中。这种写法有如下几个痛点:
由于没有使用vue
的模版语法,所以vue
内置的v-model
等指令和项目中自己封装的指令等都不能使用了,只能使用js去自己实现。
按照常规的思维,setup
直接返回一个值就行了,但是如果你这样写就会收到这样的报错:
[Vue warn]: setup() should not return VNodes directly - return a render function instead.
原因是setup()
函数在每个组件中只会被调用一次,而返回的渲染函数将会被调用多次。这样就导致我们的代码只能在外面包裹一层匿名函数:
return () => {
return <div>{renderDataList(list)}</div>;
};
在*.vue文件中使用JSX/TSX渲染函数
那么有没有方法可以让我们在使用JSX/TSX
渲染函数的同时,也可以在vue
文件中使用模版语法呢?答案是:当然可以!
首先我们需要导入@vitejs/plugin-vue-jsx
// vite.config.js
import vue from '@vitejs/plugin-vue'
export default {
plugins: [vue()],
}
然后我们需要将vue
文件的script
标签的lang
设置为tsx或者jsx
。具体的Page.vue
代码如下:
<template>
<RenderDataList :data="list" />
</template>
<script setup lang="tsx">
import ComponentA from "./component-a.vue";
import ComponentB from "./component-b.vue";
import ComponentC from "./component-c.vue";
const list = [1, 5, 3, 2, 1];
const RenderDataList = (props: { data: Array<number> }) => {
return props.data?.map((val) => {
if (val % 3 === 0) {
return <ComponentA />;
} else if (val % 3 === 1) {
return <ComponentB />;
} else {
return <ComponentC />;
}
});
};
</script>
在上面这个例子中我们定义了一个RenderDataList
,然后在template
中可以直接将RenderDataList
当作一个组件使用。vscode也会给出智能提示。
在react
中,这种场景我们可以将RenderDataList
当作一个函数去使用,然后在模版中直接调用这个函数就行了。但是在vue
中,RenderDataList
只能当做一个组件使用,不能当做函数调用。
还有一点需要避坑的是,假如我们的props中定义了一个驼峰命名法的变量,例如:pageNum
。在template
中传入pageNum
的时候必须写成:pageNum="xxx"
,不能写成:page-num="xxx"
。
总结
这篇文件介绍了如何在*.vue
文件中直接使用JSX/TSX
渲染函数,只需要导入@vitejs/plugin-vue-jsx
,然后将script
标签的lang
设置为tsx或者jsx
。就可以在script
中直接定义组件,然后在template
中直接使用组件就可以了。这样我们既可以使用JSX/TSX
渲染函数的灵活性,也可以使用vue
模版语法中内置的指令等功能。
如果我的文章对你有点帮助,欢迎关注公众号:【欧阳码农】,文章在公众号首发。你的支持就是我创作的最大动力,感谢感谢!
直接在*.vue文件(SFC)中使用JSX/TSX渲染函数,真香!的更多相关文章
- 如何在 vue3 中使用 jsx/tsx?
我们都知道,通常情况下我们使用 vue 大多都是用的 SFC(Signle File Component)单文件组件模式,即一个组件就是一个文件,但其实 Vue 也是支持使用 JSX 来编写组件的.这 ...
- Vue躬行记(7)——渲染函数和JSX
除了可通过模板创建HTML之外,Vue还提供了渲染函数和JSX,前者的编码自由度很高,后者对于开发过React的人来说会很熟悉.注意,Vue的模板最终都会被编译成渲染函数. 一.渲染函数 虽然在大部分 ...
- VScode 中 vue文件template中不能使用tab补齐标签
选择 文件-->首选项-->设置-->搜索 emmet,选择 编辑 setting.json, 添加下列代码: "emmet.includeLanguages" ...
- sublime text3支持Vue文件高亮显示
sublime text 默认打开.vue文件全部都是白色的,不是特别方便.安装插件可以做到代码高亮显示 1.插件vue-syntax-highlight 下载地址:github https://gi ...
- VSCode Vue文件格式化
参考文档:https://vuejs.github.io/vetur/formatting.html 自从将VSCode更新之后,vue文件的html格式化就失效了,而且vue文件中的js ,css格 ...
- 【C++】C++中的lambda表达式和函数对象
目录结构: contents structure [-] lambda表达式 lambda c++14新特性 lambda捕捉表达式 泛型lambda表达式 函数对象 函数适配器 绑定器(binder ...
- Vue基础-渲染函数-插槽
Vue 测试版本:Vue.js v2.5.13 先看个插槽的例子: <div id="app"> <child > <span slot-scope= ...
- 在Vue中使用JSX,很easy的
摘要:JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javasc ...
- vue中使用JSX报错,如何解决
Support for the experimental syntax 'jsx' isn't currently enabled (32:12): 30 | }, 31 | render() { & ...
- 在使用 vscode 时 eslint 检测 .vue 文件中的less 部分内容
问题: 在使用 vscode 以及 eslint 来检测 基于 webpack 的 vue-cli 的项目中,eslint 无法检测到 .vue 文件中的less 部分内容. 解答: 1.通过 下载 ...
随机推荐
- 洛谷题解 | P5660 数字游戏
目录 题目描述 输入格式 输出格式 输入输出样例 说明/提示 题目简化 题目思路 AC代码 题目描述 小 K 同学向小 P 同学发送了一个长度为 8 的 01 字符串来玩数字游戏,小 P 同学想要 ...
- Java面向对象编程的三大特性:封装、继承、多态。
一.封装 封装的核心在于私有化(private),大部分情况下,来封装对象的属性,很少有封装方法的.通过将对象的属性封装,提供对外的公共方法来访问属性是最常见的方式. public static cl ...
- Nodejs环境打包前端项目
Node.js 在Linux下安装和环境搭建/编译项目 安装nodejs:1.下载nodejs源码包 wget https://nodejs.org/dist/v14.16.0/node-v14.16 ...
- spring---面向切面(AOP @Pointcut 注解篇)
2.1 第一个实例 接下来,我们先看一个极简的例子:所有的get请求被调用前在控制台输出一句"get请求的advice触发了". 具体实现如下: 1.创建一个AOP切面类,只要在类 ...
- .NET的各种对象在内存中如何布局[博文汇总]
在过去一段时间里,我陆陆续续写一些关于.NET对象类型布局的文章,其中包括值类型和引用类型的内存布局.字符串对象和数组的内存布局等,这里作一个简单的汇总. [1] 如何计算一个实例占用多少内存? 我们 ...
- Codeforces 1566E Buds Re-hanging
原题链接 Codeforces Global Round 16 E. Buds Re-hanging 首先想到,如果我们把一个\(buds\)挂到一个叶子上,那么会使得叶子总数减\(1\). 还有就是 ...
- (Good topic)双指针:判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列. 你可以认为 s 和 t 中仅包含英文小写字母.字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=1 ...
- 暴力+DP:买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润. 注意:你不能在买入股票前卖出股票. ...
- 关联规则挖掘:Apriori算法的深度探讨
在本文中,我们深入探讨了Apriori算法的理论基础.核心概念及其在实际问题中的应用.文章不仅全面解析了算法的工作机制,还通过Python代码段展示了具体的实战应用.此外,我们还针对算法在大数据环境下 ...
- [编程]UML语言:理论之光与实践之惑
UML介绍及现状 UML(统一建模语言)是软件工程领域中具有悠久历史的一种模型化语言工具.它通过标准化的图形符号体系,使得软件系统的蓝图能够被更直观地表达出来.UML诞生于20世纪90年代,经过多年积 ...