vue3中怎么巧妙的去运用jsx?

发布时间:2023年12月26日

概要

我们都知道vue3是支持用jsx/tsx,但是好像从来都没有人告诉我们应该怎么运用到项目当中,下面是我觉得不错的一种使用方式,分享给大家。

JSX / TSX?

GTP:

在Vue中,通常使用JSX来描述组件的模板。JSX是JavaScript XML的缩写,它允许你在JavaScript中编写类似HTML的代码,用于描述UI。TSX则是TypeScript的扩展,用于在TypeScript中编写JSX。虽然Vue通常使用单文件组件(.vue文件),但是你也可以选择使用JSX来编写Vue组件。 TSX则是用于在TypeScript中编写JSX的文件扩展名。

vue3官网 #JSX / TSX:传送门

安装

我们先把plugin-vue-jsx安装到项目中

npm i @vitejs/plugin-vue-jsx -D

or

yarn add @vitejs/plugin-vue-jsx -D

配置

提示:文章会以vue3 + vite + ts项目诉说

安装完插件后,我们需要在vite.config.tsplugins中配置一下,之后就可以正常使用了。

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';

export default defineConfig({
  plugins: [
    vue(),
    vueJsx()
  ]
})

封装JsxRender.vue

我们先封装一个用来渲染jsx的组件

src
	|-components
		|-JsxRender
			|-JsxRender.vue

代码很简单,就抛出一个render回调钩子去渲染jsx

<script lang="ts">
export default {
    props: {
        params: {
            type: Object,
        },
        render: {
            type: Function,
        },
    },
    render() {
        return this.render(this.params)
    },
}
</script>

使用JsxRender.vue

封装完之后,我们可以轻而易举的以组件的形式去渲染jsx了,是不是特别简单?需要注意的是script标签里的语言要写成lang="tsx",另外demo项目用来unplugin-vue-components,所以components文件夹下的组件不用引入就可直接使用,没用过的后续可以下载我的demo看看

代码:

<script setup lang="tsx">
const jsxRenderParams = {
  title: '这是jsx渲染出来的文本'
}
function renderFn(data) {
  return <p class="jsx-render">{data.title}</p>
}
</script>

<template>
  <jsxRender :params="jsxRenderParams" :render="renderFn" />
</template>

<style lang="scss" scoped>
.jsx-render {
  color: #41B883;
}
</style>

效果:
在这里插入图片描述

怎么巧妙的去使用它?

比方说我们做项目经常用到的element table表单,我们就可以留一个口子给jsx去动态的设置el-table-column,代码如下:

src
	|-components
		|-JsxTable
			|-JsxTable.vue

JsxTable.vue:

<script lang="ts" setup>
interface Columns {
  prop: string
  label: string
  renderCell?: Function
}
interface Props {
  columns: Columns[]
  data: Record<string, any>[]
}
const props = withDefaults(defineProps<Props>(), {
  columns: () => [],
  data: () => [],
})

</script>

<template>
  <el-table :data="props.data">
    <el-table-column v-for="item in props.columns" :key="item.prop" :label="item.label">
      <template #default="{ row }">
        <jsxRender v-if="item.renderCell" :params="row" :render="item.renderCell" />
        <span v-else>{{ row[item.prop] }}</span>
      </template>
    </el-table-column>
  </el-table>
</template>

接着我能就可以在columns属性绑定的数组对象里写jsx代码了,我们JsxTable组件里封装的渲染函数叫renderCell,所以当我们想要动态渲染某一列时,只需要在renderCell方法里返回jsx代码就好了,
代码如下:

<script setup lang="tsx">
const columns = [
  {
    prop: 'num',
    label: '序号',
  },
  {
    prop: 'tooltip',
    label: 'el-tooltip',
    renderCell: (row) => {
      return (
        <el-tooltip
          content={row.tooltip.content}
        >
          <span>{row.tooltip.name}</span>
        </el-tooltip>
      )
    }
  },
  {
    prop: 'progress',
    label: 'el-progress',
    renderCell: (row) => {
      return (
        <el-progress percentage={row.progress.percentage} status={row.progress.status} />
      )
    }
  },
  {
    prop: 'operate',
    label: '操作',
    renderCell: (row) => {
      return (
        <el-button type="primary" link onClick={() => clickOperate(row)}>编辑</el-button>
      )
    }
  }
]
const tableData = [
  {
    num: '1',
    tooltip: {
      name: '雷总',
      content: '雷军造车,天命所归,雷字带电,军字带车。'
    },
    progress: {
      percentage: 100,
      status: 'success'
    },
    msg: '这TMD绝对是捣乱的是吧'
  },
  {
    num: '2',
    tooltip: {
      name: '卢总',
      content: '新手还在看小米,老手已经开始等红米汽车了'
    },
    progress: {
      percentage: 50,
      status: ''
    },
    msg: '干翻友商小米'
  },
]
function clickOperate(item) {
  ElMessage({
    message: item.msg,
    type: 'success',
  })
}
</script>

<template>
  <JsxTable :columns=columns :data=tableData />
</template>

demo效果:(之后如果你遇到类似的组件如el-descriptions,你就可以根据这个风格去封装组件了?(?????)?)
在这里插入图片描述

Demo下载

有积分交一下公粮,没积分的去gitee

?CSDN:vue3-tsx 传送门

?Gitee:vue3-tsx 传送门

文章来源:https://blog.csdn.net/weixin_42063951/article/details/135171661
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。