开发兼容vue2和vue3的组件

返回
Author Avatar
钢翼
2022-08-16
编程
218

网上很多尬吹vue-demi的,很怀疑是否真的用过,这玩意用起来限制还是蛮多的。
我觉得vue-demi原理可能就是api的重定向(没深入源码研究)。
所以你在vue3用的setup等语法在vue2中由于是没有的,你是不能用的。
vue-demi能兼容的主要原因是vue3有历史包袱,保留了大部分vue2的api。

所以我们不用vue-demi也可以开发兼容vue2和vue3的组件。 目标是一套代码一个包,同时兼容vue2和vue3。需要注意的是我们得用vue2的写法来写组件。还有不能用sfc,即template。 vue2的话需要升级到vue2.7以上版本。

步骤

1.使用vue3编写组件

基本就是改成vue2的写法,然后模板改为rander的h函数或jsx进行渲染,下面是h函数的写法

//xx.ts
import { h as h1, defineComponent } from 'vue';
import * as Vue from 'vue'
import config from '../../package.json'
export default defineComponent({
  name: "GeEcharts",
  version: config.version,
  props: {
    height: {
      type: [String, Number],
      require: false,
      default: 400
    },
	content:{
	  type: String
	}
  },
  data() {
    return {
      chartHeight: this.height,
    }
  },
  mounted() {
  
  },
  methods: {        

  },
  render(createElement:any) {
	const isVue2 = Vue.version.split('.')[0] == '2'
	//vue2 和vue3的v-html写法不太一样,需要区分
	if (isVue2) {
		//vue2
		const h = createElement
		return h('div', {
        	domProps: {
            	innerHTML: this.content
          	},
      		style: {
       	 		height: this.chartHeight + 'px'
      		}
    	})
	}else{
		//vue3
		const h = h1	
		return h('div', {
        	innerHTML: this.content,
      		style: {
       	 		height: this.chartHeight + 'px'
      		}
    	})
	}
    
  }
})

2.使用jsx

引用

npm install -D @vitejs/plugin-vue-jsx
# 或
yarn add -D @vitejs/plugin-vue-jsx

修改vite.config.ts

 import vue from '@vitejs/plugin-vue'
 import dts from 'vite-plugin-dts'
+import vueJsx from '@vitejs/plugin-vue-jsx'
 export default defineConfig({
   plugins: [vue(),
+	 vueJsx({ pragma:"h"}), //将createVNode改为h,在render中必须给h赋值。
	 dts({include:['src/index.ts']
   })],
  optimizeDeps: {
    exclude: ["vue-demi"],
  }, 
   build: {
     lib: {
       entry: './src/index.ts',
 	   formats: ['es', 'umd'],
       name: 'GeUI',
       fileName: (format) => `index.${format}.js`
     },
     rollupOptions: {
       external: ['vue'],
       output: {
         globals: {
           vue: 'Vue'
         }
       }
     }
   }
})

组件后缀从ts改为tsx。render改成jsx语法

//xx.tsx
 render(createElement:any) {
	//下面给h赋值,是由于h函数在vue2和vue3中不一致。
    const isVue2 = Vue.version.split('.')[0] == '2'
    const h = isVue2 ? createElement : Vue.createVNode
	//domProps是vue2的v-html写法 innerHTML是vue3的v-html写法,两个都写即可兼容
    return (<div style={{ height: this.chartHeight  + 'px' }} innerHTML={this.content} domProps={{ innerHTML: this.content }}></div>)
  }

总结:用习惯template,改用h函数和jsx还是不太方便。在h函数和jsx之间,推荐还是选jsx吧。至少比h函数容易维护。

参考:https://blog.csdn.net/ambit_tsai/article/details/104628676