vue3 中使用 jsx 开发(语法差异)

安装 JSX 插件

在 Vue2 中要想使用 jsx 开发,需要安装 @vue/babel-preset-jsx 等插件,之后在 babel 里指定即可,详细可以参考下面的 Vue2 GitHub 文档

Vue2:GitHub 文档 —— Babel Preset JSX

最近在使用 Vue3,突然想用 jsx 进行开发部分页面,顺便记录一下,也可以参考下面的 Vue3 GitHub 文档

Vue3:GitHub 文档 —— Babel Plugin JSX for Vue 3.0

构建工具使用的是 vite,要想使用 jsx 开发,需要安装 @vitejs/plugin-vue-jsx,之后配置 vite.config.js 里的 plugins 即可

// vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'
import { defineConfig } from 'vite'

export default defineConfig(() => {
  return {
    plugins: [vueJsx()]
  }
})

接下来着重说一下在使用 .vue 文件和 .jsx 文件在使用语法上的差异

使用语法差异

模板

之前在 template 里写的 html 代码需要放到 render 函数或 setup 函数里,Vue3 在 setup 里写会好一点

<!-- .vue -->
<template>
  <div>Hello World</div>
</template>

<!-- .jsx -->
<script>
export default defineComponent({
  setup() {
    return () => (
      <div>Hello World</div>
    )
  }
})
</script>

指令

需要把双引号改为单括号

  • v-ifv-showv-html 等同理
  • v-bind 也是一样的,不过需要把动态绑定需要去掉 :

注意:

  • .vue 文件中,ref 在模板中会自动进行解包,所以不需要使用 .value
  • 但是在 .jsx 文件中,ref 在模板中不会自动解包,所以需要使用 .value
<!-- .vue -->
<el-input v-model="queryParams.pageNumber" />
<el-form model="queryParams" :inline="true">...</el-form>

<!-- .jsx -->
<el-input v-model={queryParams.value.pageNumber} />
<el-form model={queryParams.value} inline={true}>...</el-form>

事件修饰符

  • 想使用事件修饰符可以把 v-model 改为一个数组,事件修饰符需要以数组的形式传递

    如果需要传递参数,需要在数组第二个参数中以字符串形式传递

  • 推荐:可以使用 _ 来分割事件修饰符,GitHub 里没有特殊声明,但是 Babel Plugin JSX for Vue 3.0 源码里做了判断,可以参考: parseDirectives.ts#L52-L61

<!-- .vue -->
<el-input v-model.trim={ queryParams.name } />

<!-- .jsx -->
<el-input v-model={ [queryParams.value.name, ['trim'] } />
<!-- 或 -->
<el-input v-model_trim={ refVal.value } />

自定义指令

如下示例为:添加 .event 事件修饰符并传递 arg 参数,直接打印 binding 效果如下:

image-20220901105132150

<!-- .vue -->
<el-button
  v-hasPermission:arg.event="['xxx:add']"
  type="primary"
  plain
  icon="Plus"
  @click="handleAdd"
>
  新增
</el-button>

<!-- .jsx -->
<el-button
  v-hasPermission={[['xxx:add'], 'arg', ['event']]}
  type='primary'
  plain
  icon="Plus"
  onClick={handleAdd}
>
  新增
</el-button>

v-for

  • v-for 无法直接使用,需要使用 map 去实现循环遍历渲染
<!-- .vue -->
<h1 v-for="item in list" :key="item">{{item}}</h1>

<!-- .jsx -->
<script>
{list.value.map(item => (
  <h1>{item}</h1>
))}
</script>

注意:

  • 如果遍历时需要判断每一项其是否显示,不能使用 v-if,需要使用三元运算符
  • v-forv-if 不能一起使用
<!-- .vue -->
<template v-for="col in columns">
  <el-table-column
    v-if="col.visible"
    :key="col.key"
    :label="col.label"
    :prop="col.field"
  />
</template>

<!-- .jsx -->
{columns.value.map(col =>
  col.visible ? (
    <el-table-column
      key={col.id}
      label={col.label}
      prop={col.field}
    />
  ) : null
)}

v-on

  • v-on 无法直接使用,需要使用原生绑定事件的方式去实现(@ -> on,之后进行驼峰)
<!-- .vue -->
<el-button @click="handleQuery">搜索</el-button>

<!-- .jsx -->
<el-button onClick={handleQuery}>搜索</el-button>

系统按键修饰符不能通过 .xxx 形式书写,需要自己进行判断,比如如下示例是按回车时进行搜索

  • 这里顺便说一下 style,由于里面是 : 形式表示,需要改为对象形式书写
<!-- .vue -->
<el-input
  v-model.trim="queryParams.number"
  clearable
  style="width: 180px"
  @keyup.enter="handleQuery"
/>

<!-- .jsx -->
<el-input
  v-model_trim={queryParams.value.number}
  clearable
  style={{ width: '180px' }}
  onKeyup={e => e.code === 'Enter' && handleQuery()}
/>

插槽

在 jsx 中,应该使用 v-slots 代替 v-slot,且插槽需要是函数式组件

<!-- .vue -->
<el-dialog
  v-model="configOpen"
  title="弹出框"
  append-to-body
  >
  <template #footer>
    <div class="dialog-footer">
      <el-button @click="configOpen = false">取 消</el-button>
    </div>
  </template>
</el-dialog>

<!-- .jsx -->
<el-dialog
  v-model={configOpen.value}
  title='弹出框'
  append-to-body
  v-slots={{
    footer: () => (
      <div class='dialog-footer'>
        <el-button
          onClick={() => {
            configOpen.value = false
          }}
        >
          取 消
        </el-button>
      </div>
    )
  }}
  >
  <!-- ... -->
</el-dialog>
<think>好的,我需要回答用户关于如何在Vue使用JSX语法结合Element UI组件的问题。首先,我应该回顾一下用户提供的引用内容,确保回答准确。 用户提到了三个引用。引用[1]提到在Vue 2中使用JSX需要配置Babel插件,所以第一步应该是安装和配置Babel。引用[2]展示了一个使用render函数和JSX的例子,特别是在组件中动态渲染内容,比如el-table的动态列。引用[3]则涉及Vue 3使用插槽和Element Plus的情况,比如在JSX中处理插槽的方法,比如使用v-slots属性。 接下来,我需要分步骤说明如何在Vue 2和Vue 3使用JSX与Element UI。首先,配置Babel是基础,需要安装相关插件,比如babel-plugin-transform-vue-jsx。然后,给出一个简单的例子,比如渲染一个el-button,展示JSX的基本用法。 对于动态组件渲染,比如动态生成el-table的列,用户可能想知道如何在JSX中循环生成多个列,这里需要用数组的map方法生成多个el-table-column组件,并绑定属性如prop和label。 另外,用户可能关心插槽的处理。在Vue 2中,可能需要通过this.$slots来访问插槽内容,而在Vue 3中,使用setup函数和useSlots方法,同时结合v-slots属性传递插槽函数。例如,在el-dialog中使用自定义的footer插槽,需要定义slots对象,并将其传递给组件的v-slots属性。 还要注意版本差异Vue 2对应的Element UI是element-ui,而Vue 3对应的是element-plus,所以需要分开说明。同时,在Vue 3使用JSX可能不需要额外配置,但需要确保正确的语法。 最后,需要总结一些常见问题,比如性能优化、插槽使用的注意事项,以及处理事件绑定的方法,比如使用onClick或onChange这样的驼峰命名方式。 整个过程中,要确保代码示例正确,并且符合用户提供的引用内容。同时,语言要简洁明了,结构清晰,分步骤讲解,让用户能够逐步理解和应用。</think>### 如何在 Vue 中通过 JSX 语法使用 Element UI 组件? #### 1. 环境配置(Vue 2) 在 Vue 2 中使用 JSX 需要配置 Babel 插件: ```bash npm install @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props --save-dev ``` 在 `.babelrc` 中添加配置: ```json { "presets": ["@vue/babel-preset-jsx"] } ``` #### 2. 基础组件使用 在 `.vue` 文件中,通过 `render` 函数返回 JSX 语法: ```jsx export default { render(h) { return ( <div> <el-button type="primary" onClick={this.handleClick}> 点击按钮 </el-button> </div> ); }, methods: { handleClick() { console.log("按钮被点击"); } } }; ``` #### 3. 动态渲染组件(以 el-table 为例) 结合 `v-for` 逻辑动态生成列: ```jsx export default { data() { return { columns: [{ prop: "name", label: "姓名" }, { prop: "age", label: "年龄" }], data: [{ name: "张三", age: 25 }, { name: "李四", age: 30 }] }; }, render(h) { return ( <el-table data={this.data}> {this.columns.map(col => ( <el-table-column prop={col.prop} label={col.label} /> ))} </el-table> ); } }; ``` #### 4. 插槽处理(Vue 3 + Element Plus) 在 Vue 3 中,使用 `v-slots` 属性传递插槽: ```jsx import { defineComponent } from "vue"; export default defineComponent({ setup(props, { slots }) { const customSlots = { default: () => slots.default?.(), footer: () => <span class="custom-footer">自定义底部内容</span> }; return () => ( <el-dialog v-slots={customSlots} visible={true}> {slots.default?.()} </el-dialog> ); } }); ``` #### 5. 注意事项 - **事件绑定**:使用驼峰命名,例如 `onClick` 代替 `@click`。 - **作用域插槽**:在 Vue 2 中需通过 `scopedSlots` 属性传递: ```jsx <el-table-column> <div slot-scope="scope">{scope.row.name}</div> </el-table-column> ``` - **版本兼容性**:Vue 3 默认支持 JSX,无需额外配置[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值