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 的 hcreateVNode)函数,用于创建虚拟节点(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 都是一个值得深入探索的工具。现在,不妨动手实践,感受它带来的开发体验!

最新发布