使用Vue2.x 书写JSX 的几种方式

JSX 是什么?

jsx 是javascript的语法拓展,最初由React框架发明了这种书写方式,在javascript 代码中灵活的书写xml语法,即兼容了JavaScript的语法的灵活性,同时也可以更好的书写我们的模版xml代码。

为什么要在Vue中用JSX语法编写代码?

由于当前的Vue2.x 已经长期性的停止维护了,在公司的许多的项目当中还是可以看到Vue2的Options 的组织的项目,在后续的项目升级改造当中,想要直接使用React的代码从而节省我们实际开发的时间,所以就想到了使用JSX的语法来直接改造Vue2的相关项目。

主要有以下的几种方式实现改造我们的Vue2项目的代码

1 使用vue2 Options API 加上render function的方式。

在Vue2.x 的源码当中可以看到其实是支持render写法的

.../types/options.d.ts 类型文件中:

js 复制代码
  data?: Data;
  props?: PropsDef;
  propsData?: object;
  computed?: Accessors<Computed>;
  methods?: Methods;
  watch?: Record<string, WatchOptionsWithHandler<any> | WatchHandler<any> | string>;

  el?: Element | string;
  // 这里可以看到其实是支持我们的 自定义template的模版的写法的
  template?: string;
  // hack is for functional component type inference, should not be used in user code
  // 这里可以看到可以用render 方法实现我们的模版的功能
  render?(createElement: CreateElement, hack: RenderContext<Props>): VNode; 
  renderError?(createElement: CreateElement, err: Error): VNode;
  staticRenderFns?: ((createElement: CreateElement) => VNode)[];

  beforeCreate?(this: V): void;
  created?(): void;
  beforeDestroy?(): void;
  destroyed?(): void;
  beforeMount?(): void;
  mounted?(): void;
  beforeUpdate?(): void;
  updated?(): void;
  activated?(): void;
  deactivated?(): void;
  errorCaptured?(err: Error, vm: Vue, info: string): boolean | void;
  serverPrefetch?(this: V): Promise<void>;

  directives?: { [key: string]: DirectiveFunction | DirectiveOptions };
  components?: { [key: string]: Component<any, any, any, any> | AsyncComponent<any, any, any, any> };
  transitions?: { [key: string]: object };
  filters?: { [key: string]: Function };

  provide?: object | (() => object);
  inject?: InjectOptions;

  model?: {
    prop?: string;
    event?: string;
  };

  parent?: Vue;
  mixins?: (ComponentOptions<Vue> | typeof Vue)[];
  name?: string;
  // TODO: support properly inferred 'extends'
  extends?: ComponentOptions<Vue> | typeof Vue;
  delimiters?: [string, string];
  comments?: boolean;
  inheritAttrs?: boolean;

eg:render 的默认写法 注意: 需要删除我们的单文件组件中的template块 ,默认应该是template的优先级要高于render方式定义的JSX。

js 复制代码
  render(h) {
    return h('span', 'hello world')
  }

或者直接return一个VNode

js 复制代码
  render(h) {
    // return h('span', 'hello world')
    return (
      <div>
        这是render VNode
      </div>
    )
  }

class 与 style 的样式绑定,当我们使用h函数 来实现我们的模版时,通过TS的类型定义可以知道主要是VNodeData的这个类型。

js 复制代码
export interface VNodeData {
  key?: string | number;
  slot?: string;
  scopedSlots?: { [key: string]: ScopedSlot | undefined };
  ref?: string;
  refInFor?: boolean;
  tag?: string;
  staticClass?: string;
  class?: any;
  staticStyle?: { [key: string]: any };
  style?: string | object[] | object;
  props?: { [key: string]: any };
  attrs?: { [key: string]: any };
  domProps?: { [key: string]: any };
  hook?: { [key: string]: Function };
  on?: { [key: string]: Function | Function[] };
  nativeOn?: { [key: string]: Function | Function[] };
  transition?: object;
  show?: boolean;
  inlineTemplate?: {
    render: Function;
    staticRenderFns: Function[];
  };
  directives?: VNodeDirective[];
  keepAlive?: boolean;
}

class 的绑定一般推荐使用 string 或者 string[] 类型, style 行内样式一般推荐使用 object 类型。 eg:

js 复制代码
let classList = ['aaa','ccc']
return h('span', {
  class: ['xxx', classList],
  {
      fontSize:'20px',
      height: '10px',
  }
});

当我们直接使用返回VNode 的方式时,class 绑定使用string的方式, style绑定和React JSX 的使用方式一致。 eg:

js 复制代码
    return (
      <div class={'aaa'} style={{ lineHeight: '10px' }}>
        xxxxxx
      </div>
    )

在Vue2.7版本之下,如果想要体验Vue3的CompositionAPI 的组合式API的函数功能,我们可以安装 @vue/composition-api包,然后全局使用插件。

js 复制代码
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)

之后便可以全局使用API

js 复制代码
// 使用 API
import { ref, reactive } from '@vue/composition-api'

包括支持 TSX | JSX的详细的定义模式可参考:

Vue < 2.7.x 使用组合式API 指南

2 升级Vue2.7 的同时,使用Composition API 和 setup function来实现改造我们的Vue项目。

首先,更新我们的项目Vue版本为Vue2.7.x ,Vue2.7.x 以上版本内置了组合式API 的功能,因此我们可以直接使用 import { defineComponent } from 'vue' 导入我们的组件定义方式:

js 复制代码
// demo.tsx
import { defineComponent } from 'vue'

export default defineComponent({
  // type inference enabled
})

当我们升级到Vue2.7.x 版本的时候 可以使用setup 函数来实现我们组件的基本功能,同时也是支持TypeScript的类型检查的功能的。 组件组织方式:

js 复制代码
 setup?: (
    this: void,
    props: Props,
    ctx: SetupContext
  ) => Promise<RawBindings> | RawBindings | ((h: CreateElement) => VNode) | void

可以看到我们也是可以通过template模版和setup 函数返回VNode来实现我们的组件的。

1 xxx.vue 方式的单文件组件:

js 复制代码
<template>
xxxxx
</template>
<script>
import { defineComponent,ref,reactive } from 'vue'

export default defineComponent({
  // type inference enabled
})

</script>
<style lang='scss' scoped>
xxx
</style>

2 jsx | tsx 方式的组件组织形式: 返回一个VNode

js 复制代码
// demo.(j|t)sx
import style from './HelloWorld.module.css';
import { defineComponent, PropType } from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      required: true,
    },
    eventClick: {
      type: (null as unknown) as PropType<(event: MouseEvent) => void>,
    }
  },
  setup(props) {
    return (h) => (
      <div>
        <h1 onClick={props.eventClick}>{props.msg}</h1>
        <h3 class={style.listTitle}>Installed CLI Plugins</h3>
      </div>
    );
  },
});

根据类型文件可知,我们在setup函数中返回的Vnode 也可以使用h函数来定义即:

js 复制代码
setup(props){
    return (h)=>{
       return h('span', { class: ['xxx', classList], { fontSize:'20px', height: '10px', } });
    }
}

当我们升级到Vue2.7之后,便可以去掉Options 的方式的组织代码的形式,同时直接使用 import { ref,reactive,defineComponent } from 'vue' 等方式引入我们的ComponsitionAPI,例如ref,reactive等api。onMounted,onUpdated等生命周期hooks。 能够有效的梳理我们的代码和组织逻辑。复用组件以及自定义和复用hooks。安装 @vueuse/core 包等。

支持SSR

当我们升级到 Vue2.7.x 上时,也是可以使用ComponsitionAPI 来构建一个SSR代码的。

js 复制代码
import { onServerPrefetch } from 'vue'

export default {
  setup(props, { ssrContext }) {
    const result = ref()

    onServerPrefetch(async () => {
      result.value = await callApi(ssrContext.someId)
    })

    return {
      result,
    }
  }
}

总结

本文详细的介绍了我们如何使用Vue2.x的项目,来改造升级成JSX|TSX代码格式的组件格式。方便我们迁移React jsx| tsx 的相关代码。同时也对一些组件格式和Vue组件编写的方式做了一定的探讨。 相关链接

Vue2.x升级: v2.cn.vuejs.org/v2/guide/mi...

VueUse: www.vueusejs.com/guide/

Vue3: cn.vuejs.org/guide/reusa...

相关推荐
持续前行7 小时前
vscode 中找settings.json 配置
前端·javascript·vue.js
JosieBook7 小时前
【Vue】11 Vue技术——Vue 中的事件处理详解
前端·javascript·vue.js
安逸点7 小时前
Vue项目中使用xlsx库解析Excel文件
vue.js
一只小阿乐7 小时前
vue 改变查询参数的值
前端·javascript·vue.js·路由·router·网文·未花中文网
小酒星小杜8 小时前
在AI时代下,技术人应该学会构建自己的反Demo地狱系统
前端·vue.js·ai编程
Code知行合壹8 小时前
Pinia入门
vue.js
今天也要晒太阳4738 小时前
element表单和vxe表单联动校验的实现
vue.js
依赖_赖9 小时前
前端实现token无感刷新
前端·javascript·vue.js
hhcccchh10 小时前
学习vue第十三天 Vue3组件深入指南:组件的艺术与科学
javascript·vue.js·学习
zhengxianyi51510 小时前
ruoyi-vue-pro本地环境搭建(超级详细,带异常处理)
前端·vue.js·前后端分离·ruoyi-vue-pro