vue3 jsx(建议收藏)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言:Vue3与JSX的结合——前端开发的另一种可能
在前端框架的持续演进中,Vue3 以其响应式系统和 Composition API 的革新,成为开发者关注的焦点。而 JSX(JavaScript XML)作为一种将 HTML 结构与 JavaScript 逻辑融合的技术,与 Vue3 的结合为开发者提供了更灵活的开发方式。本文将从零开始,逐步解析 Vue3 中 JSX 的使用场景、核心语法及实际案例,帮助初学者和中级开发者快速掌握这一技术组合,同时为进阶开发提供参考视角。
一、Vue3与JSX:基础概念与核心价值
1.1 什么是JSX?
JSX 是一种 JavaScript 的语法扩展,允许开发者以类似 HTML 的方式编写 UI 结构。它并非 Vue 或 React 独有的技术,而是通过 Babel 等工具转换为纯 JavaScript 代码。例如:
const element = <h1>Hello World</h1>;
这段代码最终会被编译为 React.createElement('h1', null, 'Hello World')
,但 Vue3 的 JSX 实现略有不同,后续章节会详细说明。
1.2 Vue3 中的 JSX:为什么需要它?
Vue 的模板语法简洁直观,但某些场景下(如动态组件、复杂条件渲染)可能需要更灵活的逻辑控制。JSX 的优势在于:
- 与 JavaScript 的无缝融合:无需在模板和逻辑之间频繁切换,适合函数式编程思维。
- 类型检查与工具支持:配合 TypeScript 使用时,能提供更精准的类型提示。
- 跨框架迁移的便利性:熟悉 JSX 的开发者可快速适应 React、Vue 等框架的语法差异。
1.3 Vue3 JSX 的实现原理
Vue3 的 JSX 支持基于 @vue/babel-plugin-jsx
插件,它将 JSX 转换为 Vue 的渲染函数(Render Function)。例如:
// JSX 写法
const App = () => <div>Hello</div>;
// 转换后的渲染函数
const App = () => {
return h("div", null, "Hello");
};
这里的 h
是 Vue 的 h
(createVNode
)函数,用于创建虚拟节点(VNode)。
二、从零开始:Vue3 JSX 的快速入门
2.1 环境配置与项目搭建
要使用 Vue3 JSX,需在项目中安装以下依赖:
npm install vue@next @vue/babel-plugin-jsx @babel/core
并在 Babel 配置文件(如 .babelrc
)中添加插件:
{
"plugins": ["@vue/babel-plugin-jsx"]
}
若使用 Vite,则需在 vite.config.js
中配置:
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
export default {
plugins: [vue(), vueJsx()],
};
2.2 第一个 Vue3 JSX 组件
创建一个简单的组件 HelloWorld.jsx
:
import { h, defineComponent } from 'vue';
export default defineComponent({
setup() {
return () => <div>Hello Vue3 JSX!</div>;
},
});
这里 defineComponent
是 Vue3 的组件定义函数,setup
返回的渲染函数通过 h
创建 VNode。
2.3 JSX 与 Vue 模板的对比
以一个计数器组件为例,对比两种语法的写法:
Vue 模板写法:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
const increment = () => count.value++;
</script>
JSX 写法:
import { h, defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const count = ref(0);
const increment = () => count.value++;
return () => (
<div>
<p>Count: {count.value}</p>
<button onClick={increment}>+1</button>
</div>
);
},
});
两者功能一致,但 JSX 的逻辑与结构耦合度更高,适合需要复杂条件判断的场景。
三、核心语法详解:Vue3 JSX 的进阶用法
3.1 动态内容与表达式
在 JSX 中,通过花括号 {}
插入 JavaScript 表达式:
const message = "Hello";
return <div>{message}</div>; // 渲染为 <div>Hello</div>
若表达式包含 HTML 结构,需使用 Fragment
或 <> </>
简写:
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
3.2 条件渲染与循环
条件渲染
return (
<div>
{count.value > 5 ? <p>Count is over 5</p> : <p>Count is low</p>}
</div>
);
列表渲染
const items = [1, 2, 3];
return (
<ul>
{items.map(item => (
<li key={item}>{item}</li>
))}
</ul>
);
3.3 属性绑定与事件处理
表单属性绑定
const inputValue = ref("");
return (
<input
type="text"
value={inputValue.value}
onChange={(e) => (inputValue.value = e.target.value)}
/>
);
事件监听
const handleClick = () => console.log("Clicked!");
return <button onClick={handleClick}>Click Me</button>;
3.4 组件与自定义标签
在 JSX 中,自定义组件需以大写字母开头:
// 定义组件
const MyComponent = defineComponent({
// ...
});
// 使用组件
return <MyComponent prop="value" />;
若组件返回多个根元素,需包裹在 Fragment 中:
return (
<MyComponent>
<div>Child 1</div>
<div>Child 2</div>
</MyComponent>
);
四、进阶技巧:优化与性能提升
4.1 关键字 key
的重要性
在列表渲染中,为每个元素添加唯一 key
属性可帮助 Vue 识别哪些元素发生了变化,从而优化渲染性能。例如:
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
4.2 使用 memo
避免不必要的渲染
通过 memo
高阶组件,可控制子组件是否重新渲染:
import { memo } from 'vue';
const Child = memo(
defineComponent({
// 组件逻辑
})
);
4.3 与 TypeScript 的结合
在 TypeScript 项目中,JSX 的类型检查更为严格。例如:
interface Props {
name: string;
age?: number;
}
const User = defineComponent({
props: {
name: String as PropType<string>,
age: Number,
},
setup(props: Props) {
return () => (
<div>
<p>Name: {props.name}</p>
{props.age && <p>Age: {props.age}</p>}
</div>
);
},
});
五、实际案例:构建一个 Vue3 JSX 仪表盘
5.1 需求分析
假设要开发一个显示用户数据的仪表盘,包含以下功能:
- 显示用户列表
- 过滤用户
- 展示用户详情
5.2 代码实现
5.2.1 用户列表组件
import { h, defineComponent, ref } from 'vue';
const UserList = defineComponent({
props: {
users: {
type: Array as PropType<User[]>,
required: true,
},
},
setup(props) {
const selectedUser = ref(null);
const handleSelect = (user) => {
selectedUser.value = user;
};
return () => (
<div>
<ul>
{props.users.map(user => (
<li
key={user.id}
onClick={() => handleSelect(user)}
class={{ active: selectedUser.value === user }}
>
{user.name}
</li>
))}
</ul>
<UserDetail user={selectedUser.value} />
</div>
);
},
});
export default UserList;
5.2.2 用户详情组件
const UserDetail = defineComponent({
props: {
user: {
type: Object as PropType<User>,
required: true,
},
},
setup(props) {
return () => (
<div v-if="props.user">
<h2>User Detail</h2>
<p>Name: {props.user.name}</p>
<p>Email: {props.user.email}</p>
</div>
);
},
});
5.2.3 父组件集成
const App = defineComponent({
setup() {
const users = ref([
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
]);
return () => <UserList users={users.value} />;
},
});
export default App;
六、性能与最佳实践
6.1 避免频繁的 VNode 创建
在渲染函数中,尽量减少不必要的对象或函数创建。例如:
// 不好的写法:每次渲染都会创建新函数
return () => <button onClick={() => console.log("Clicked")}>Click</button>;
// 更优写法:在 setup 中定义函数
const handleClick = () => console.log("Clicked");
return () => <button onClick={handleClick}>Click</button>;
6.2 使用 v-once
避免重复渲染
对于静态内容,可添加 v-once
指令:
return <div v-once>Static Content</div>;
6.3 代码分割与懒加载
对于大型应用,可结合动态导入实现代码分割:
const LazyComponent = defineAsyncComponent(() => import('./LazyComponent.jsx'));
return () => <LazyComponent />;
结论:Vue3 JSX 的应用场景与未来展望
通过本文的讲解,读者应能掌握 Vue3 JSX 的基础语法、核心特性及实际应用。Vue3 与 JSX 的结合为开发者提供了更灵活的开发范式,尤其适合需要高度定制化逻辑或与 TypeScript 深度集成的场景。
随着 Vue3 的生态不断完善,JSX 的支持也在持续优化。未来,随着更多开发者采用这一组合,我们或许会看到:
- 更完善的工具链支持(如 IDE 的智能提示);
- 更多最佳实践文档和社区资源;
- 与 React 生态的进一步互通性提升。
无论是快速搭建原型,还是构建复杂企业级应用,Vue3 JSX 都是一个值得深入探索的工具。现在,不妨动手实践,感受它带来的开发体验!