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 类型文件中:

  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。

  render(h) {
    return h('span', 'hello world')
  }

或者直接return一个VNode

  render(h) {
    // return h('span', 'hello world')
    return (
      <div>
        这是render VNode
      </div>
    )
  }

class 与 style 的样式绑定,当咱们运用h函数 来完成咱们的模版时,经过TS的类型界说能够知道主要是VNodeData的这个类型。

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:


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

当咱们直接运用回来VNode 的方法时,class 绑定运用string的方法, style绑定和React JSX 的运用方法共同。
eg:

    return (
      <div class={'aaa'} style={{ lineHeight: '10px' }}>
        xxxxxx
      </div>
    )

在Vue2.7版别之下,假如想要体会Vue3的CompositionAPI 的组合式API的函数功用,咱们能够装置
@vue/composition-api包,然后大局运用插件。

import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI)

之后便能够大局运用API

// 运用 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'
导入咱们的组件界说方法:

// demo.tsx
import { defineComponent } from 'vue'
export default defineComponent({
  // type inference enabled
})

当咱们晋级到Vue2.7.x 版别的时候 能够运用setup 函数来完成咱们组件的基本功用,一起也是支撑TypeScript的类型检查的功用的。
组件安排方法:

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

能够看到咱们也是能够经过template模版和setup 函数回来VNode来完成咱们的组件的。

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

<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

// 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函数来界说即:


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

当咱们晋级到Vue2.7之后,便能够去掉Options 的方法的安排代码的形式,一起装置@vue/composition-api便能够运用到咱们的最新的Vue3特性的组合式API的方法来安排代码,例如ref,reactive等api。onMounted,onUpdated等生命周期hooks。 能够有用的整理咱们的代码和安排逻辑。复用组件以及自界说和复用hooks。装置 @vueuse/core 包等。

支撑SSR

当咱们晋级到 Vue2.7.x 上时,也是能够运用ComponsitionAPI 来构建一个SSR代码的。

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…