vue2 组件可以在 vue3 中使用么?

问题描述

我目前有一个封装好的Vue2组件库A,通过npm repo在几个项目中使用。现在基于Vue3的项目也要接入组件A,我要怎样通过一套代码发布,就可以同时在基于Vue2和Vue3版本的项目中使用?

自己尝试过哪些方法

临时解决方案是分为两个分支,一个分支依赖"vue": 2.x,一个分支依赖"vue": 3.x,每次有改动需要修改发布两次,维护两个分支。

相关代码

package.json

{

"name": "xxx",

"version": "4.0.1",

"description": "xxx",

"private": false,

"main": "xxx",

"scripts": {

"dev": "cross-env NODE_ENV=development webpack-dev-server",

"build": "cross-env NODE_ENV=production webpack --progress"

},

"dependencies": {

"vue": "^2.6.11"

},

"devDependencies": {

"@babel/core": "^7.16.12",

"@babel/preset-env": "^7.16.11",

"@babel/preset-stage-3": "^7.8.3",

"@babel/runtime": "^7.16.7",

"babel-loader": "^8.2.3",

"cross-env": "^7.0.3",

"css-loader": "^6.5.1",

"less": "^4.1.2",

"less-loader": "^10.2.0",

"postcss-loader": "^6.2.1",

"style-loader": "^3.3.1",

"svg-sprite-loader": "^6.0.11",

"vue-loader": "^15.9.8",

"vue-style-loader": "^4.1.3",

"vue-template-compiler": "^2.6.14",

"webpack": "^5.67.0",

"webpack-cli": "^4.9.1",

"webpack-dev-server": "^4.7.3"

},

"browserslist": [

"> 1%",

"last 2 versions",

"not dead"

]

}

webpack.config.js

var path = require('path')

var webpack = require('webpack')

const { VueLoaderPlugin } = require('vue-loader')

function resolve(dir) {

return path.join(__dirname, dir);

}

const NODE_ENV = process.env.NODE_ENV

module.exports = {

entry: NODE_ENV == 'development' ? './examples/main.js' : './src/index.js',

output: {

path: path.resolve(__dirname, './dist'),

publicPath: '/dist/',

filename: 'xxx.js',

library: 'xxx', // 指定的就是你使用require时的模块名

libraryTarget: 'umd', // libraryTarget会生成不同umd的代码,可以只是commonjs标准的,也可以是指amd标准的,也可以只是通过script标签引入的

umdNamedDefine: true //

},

module: {

rules: [{

test: /\.css$/,

use: [

'style-loader',

'css-loader'

],

},

{

test: /\.less$/,

use: [

'vue-style-loader',

'postcss-loader',

'css-loader',

'less-loader'

],

},

{

test: /\.vue$/,

loader: 'vue-loader',

options: {

loaders: {}

// other vue-loader options go here

}

},

{

test: /\.js$/,

loader: 'babel-loader',

exclude: /node_modules/,

options: {

presets: [

['@babel/preset-env', { targets: "defaults" }]

]

}

},

{

test: /\.svg$/,

loader: 'svg-sprite-loader',

include: [resolve('src/navigation/icons')],

options: {

symbolId: 'icon-[name]'

}

},

{

test: /\.(png|jpg|gif|svg|woff2?|eot|ttf|otf)$/,

type: 'asset',

exclude: [resolve('src/navigation/icons')]

}

]

},

resolve: {

alias: {

'vue$': 'vue/dist/vue.esm.js'

},

extensions: ['*', '.js', '.vue', '.json']

},

devServer: {

static: {

directory: path.join(__dirname, 'public'),

},

historyApiFallback: true,

allowedHosts: 'all',

host: 'localhost',

compress: true,

port: '8002',

client: {

overlay: true

}

},

performance: {

hints: false

},

devtool: 'eval-source-map',

plugins: [

// make sure to include the plugin!

new VueLoaderPlugin()

]

}

导出组件

// 导入导航组件

import xxx from './xxx'

// 存储组件列表

const components = [

xxx

]

// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册

const install = function (Vue) {

// 判断是否安装

if (install.installed) return

// 遍历注册全局组件

components.map(component => Vue.component(component.name, component))

}

// 判断是否是直接引入文件

if (typeof window !== 'undefined' && window.Vue) {

install(window.Vue)

}

export default {

// 导出的对象必须具有 install,才能被 Vue.use() 方法安装

install,

// 以下是具体的组件列表

xxx

}

打包后部分代码

!function(V,l){"object"==typeof exports&&"object"==typeof module?module.exports=l():"function"==typeof define&&define.amd?define("xxx",[],l):"object"==typeof exports?exports["xxx"]=l():V["xxx"]=l()}(self,(function(){return function(){var __webpack_modules__={482:function(__unused_webpack_module,__webpack_exports__,__webpack_require__){"use strict";eval('// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  "default": function() { return /* binding */ src; }\n});\n\n;// CONCATENATED MODULE: ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/x/x.vue?vue&type=template&id=862ecfc0&\nvar render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c(\'div\',{staticClass:"xxx",class:[_vm.transparent ? \'transparent\' : \'\', _vm.themeClass]}

报错位置

var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h

项目结构

.vue,.less,.js,font,svg,png
vue2 组件可以在 vue3 中使用么?

期待的结果和实际看到的错误信息

期望组件只用维护一套代码。目前在Vue3上使用报错信息如下:
vue2 组件可以在 vue3 中使用么?
vue2 组件可以在 vue3 中使用么?
我大概了解是因为Vue单文件template模板编译不兼容导致的,但是实在不知道怎么解决。

解决方案:最终采用卡卡军的方法

  1. 增加一个package.json和对应打包配置
    vue2 组件可以在 vue3 中使用么?
  2. 增加postinstall配置,用来下载时自动切换版本,内容copy的卡卡军的,然后同时构建生成两个版本
    vue2 组件可以在 vue3 中使用么?
    感觉如果不想构建两个版本的,只能在最初就全部用render(h)的形式写,(或者打包时不编译.vue?这种不会)


回答:

这个问题,我已经找到解决方法了,使用vue-demi, 但前提是封装好的组件需要重新用vue3书写, 然后打包成vue2和vue3都适用的版本, 但维护只需要维护一套,具体操作查看我写的这篇文章
https://juejin.cn/post/705526...

发布到npm的demo插件
https://github.com/kakajun/vu...


回答:

同时兼容 2 & 3 的话需要用到 vue-demi: https://github.com/vueuse/vue...

具体用法可以自己搜索了解一下。

以上是 vue2 组件可以在 vue3 中使用么? 的全部内容, 来源链接: utcz.com/p/937575.html

回到顶部