JSX 详细说明(VUE方向) 作者:马育民 • 2026-05-19 08:40 • 阅读:10000 # 介绍 JSX 是一种**JavaScript 语法扩展**,允许在 JS 代码中直接写类 HTML 标签,Vue 3 完全支持 JSX/TSX,是 Vue 模板语法的**灵活替代品**,适合复杂逻辑渲染、高阶组件、函数式组件场景。 # 概念 1. **Vue + JSX 本质** 用 JavaScript 的完整能力写 Vue 渲染函数,替代 `` 模板,所有 Vue 响应式、指令、组件特性都能在 JSX 中使用。 2. **适用场景** - 复杂条件渲染、循环嵌套(模板写起来繁琐) - 高阶组件、函数式组件 - 需要动态生成标签/属性的场景 - TS 类型支持更友好(TSX) 3. **环境支持** - Vue 3 + Vite:默认支持 `.jsx`/`.tsx`,无需额外配置 - Vue CLI:已内置支持 --- # 基础语法 ### 1. 文件与结构 Vue 组件用 JSX 时,**去掉 ``**,直接在 `setup` 或 `render` 中返回 JSX: ```jsx // 1. 基础 JSX 组件(Hello.jsx) import { ref } from 'vue' // 组件直接导出函数 export default () => { const msg = ref('Hello Vue JSX') // 直接返回 JSX return {msg.value} } ``` ```tsx // 2. TSX 版本(Hello.tsx,带类型) import { ref, defineComponent } from 'vue' export default defineComponent({ setup() { const msg = ref('Hello TSX') return () => {msg} // Vue 3 可自动解包 ref,不用 .value } }) ``` ### 2. 插值表达式 和模板一致,用 `{}` 包裹 JS 变量/表达式: ```jsx const name = 'Vue' const count = ref(10) return ( {/* 文本插值 */} 你好,{name} {/* 表达式插值 */} 计数:{count.value + 1} ) ``` ### 3. 标签与属性 - 单标签必须闭合:``、`` - 属性用**驼峰命名**(class → className,for → htmlFor) - 动态属性直接用 `{}`,不用 `v-bind` ```jsx const isDisabled = ref(false) const bgClass = 'box' return ( JSX 属性 ) ``` --- # Vue 核心特性在 JSX 中的写法 这是**最常用**的部分,直接对照模板语法学习: ### 1. 条件渲染(v-if / v-show) JSX 中**没有 v-if**,用 **JS 三元表达式/逻辑与运算符** 替代: ```jsx const show = ref(true) const type = ref(1) return ( {/* 等价 v-show */} v-show {/* 等价 v-if / v-else */} {show.value ? 显示 : 隐藏} {/* 多条件 */} {type.value === 1 ? 类型1 : type.value === 2 ? 类型2 : 其他} ) ``` ### 2. 列表渲染(v-for) 用 **JS map() 循环** 替代 `v-for`,必须加 key: ```jsx const list = ref([{ id: 1, name: '苹果' }, { id: 2, name: '香蕉' }]) return ( {list.value.map(item => ( {item.name} // key 必须写 ))} ) ``` ### 3. 事件绑定(v-on / @) 用 **on+驼峰事件名** 替代 `@`: - `@click` → `onClick` - `@input` → `onInput` - `@change` → `onChange` ```jsx const count = ref(0) const add = () => count.value++ return ( 计数:{count.value} ) ``` **带参数/事件对象**: ```jsx const handleClick = (e, id) => { e.preventDefault() console.log(id) } return handleClick(e, 123)}>点击 ``` ### 4. 双向绑定(v-model) - 基础用法:直接用 `v-model={变量}` - 自定义组件/指定属性:`v-model:propName={变量}` ```jsx const text = ref('') const visible = ref(false) return ( 输入:{text.value} {/* 自定义组件 v-model */} ) ``` ### 5. 插槽(slot) JSX 中插槽用**子组件/对象**传递,替代 `template #插槽名`: #### 默认插槽 ```jsx // 父组件 import Child from './Child.jsx' export default () => { return ( 这是默认插槽内容 ) } // 子组件 Child.jsx export default (_, { slots }) => { // slots.default() 渲染默认插槽 return {slots.default()} } ``` #### 具名插槽 + 作用域插槽 ```jsx // 父组件 export default () => { return ( {{ // 具名插槽 header header: () => 标题, // 作用域插槽(子组件传数据) default: (scope) => 子组件数据:{scope.msg} }} ) } // 子组件 export default (_, { slots }) => { return ( {slots.header?.()} {slots.default({ msg: '我是子组件' })} ) } ``` --- # Props 与 Emits(TSX 推荐) ### 1. Props 声明 ```tsx import { defineComponent } from 'vue' export default defineComponent({ // 声明 props props: { title: { type: String, default: '默认标题' }, count: Number }, setup(props) { // 直接使用 props return () => ( {props.title} {props.count} ) } }) ``` ### 2. 自定义事件(emits) ```tsx export default defineComponent({ emits: ['change'], setup(_, { emit }) { const handleChange = () => emit('change', '新值') return () => 触发事件 } }) ``` --- # 高级用法 ### 1. 动态组件 用 `resolveComponent` 配合 `h` 函数: ```jsx import { resolveComponent, h } from 'vue' const ComName = 'Button' const Button = resolveComponent(ComName) return 动态组件 ``` ### 2. Teleport(传送门) ```jsx import { Teleport } from 'vue' return ( 模态框 ) ``` ### 3. 函数式组件(无状态、高性能) ```jsx // 无响应式,纯接收 props 渲染 export default (props) => { return {props.text} } ``` --- # 模板 vs JSX 对比 | 特性 | 模板语法 | JSX 语法 | |------|----------|----------| | 学习成本 | 低,接近 HTML | 中,需要 JS 基础 | | 复杂逻辑 | 繁琐,指令嵌套 | 灵活,原生 JS 逻辑 | | TS 支持 | 一般(需额外配置) | 完美,TSX 原生支持 | | 编译优化 | Vue 自动优化 | 需手动优化 | | 适用场景 | 通用页面、简单组件 | 复杂组件、高阶组件 | --- # 常见坑点 1. **class / for 改名** - `class` → `className` - `for` → `htmlFor` 2. **样式必须写对象** - 错误:`style="color:red"` - 正确:`style={{color:'red'}}` 3. **循环必须加 key** - map 循环必须绑定唯一 key,否则警告 4. **指令大部分废弃** - 无 `v-if`/`v-for`,用 JS 原生语法替代 5. **ref 自动解包** - JSX 中直接写 `{count}`,Vue 会自动解包,不用 `.value`(setup 内返回 JSX) --- # 总结 1. Vue JSX 是**模板的增强方案**,用 JS 原生能力实现复杂渲染; 2. 核心替换:`v-if`→三元、`v-for`→map、`@click`→onClick; 3. 适合**复杂组件/TS 项目**,简单页面优先用模板; 4. Vue 3 对 JSX 支持极友好,Vite 开箱即用,无额外配置成本。 原文出处:http://malaoshi.top/show_1GW3L0xTEcPP.html