如何在ReactJs中使用基于VueJs的Web组件

问题描述

我从VueJs创建了一个Web组件,然后使用命令yarn build对其进行了编译,然后复制了dist文件夹并将其粘贴到ReactJs项目中。但是,每当我尝试导入Web组件时,ReactJs应用程序就会中断并显示错误

error

我已经尝试了在互联网上找到的所有可能方法,但是并不能解决错误

我的VueJs项目代码

AdditionComponent.vue

<template>
  <div>
      <span><strong>Total:</strong> {{ total }}</span>
  </div>
</template>

<script>
export default {
    props: {
        num1: Number,num2: Number
    },computed: {
        total(){
            return parseInt(this.num1) + parseInt(this.num2);
        }
    }
}
</script>

main.js

import Vue from 'vue'
import wrap from '@vue/web-component-wrapper'

Vue.config.productionTip = false
Vue.config.devtools = false;

const CustomElement = wrap(Vue,() => import('./components/AdditionComponent.vue'));

window.customElements.define('addition-component',CustomElement)

package.json

{
  "name": "app-form","version": "0.1.0","private": true,"scripts": {
    "serve": "vue-cli-service serve","build": "vue-cli-service build  --target wc --inline-vue --name addition-component ./src/main.js","lint": "vue-cli-service lint"
  },"dependencies": {
    "core-js": "^3.6.5","vue": "^2.6.11"
  },"devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0","@vue/cli-plugin-eslint": "~4.5.0","@vue/cli-service": "~4.5.0","babel-eslint": "^10.1.0","eslint": "^6.7.2","eslint-plugin-vue": "^6.2.2","vue-template-compiler": "^2.6.11"
  },"eslintConfig": {
    "root": true,"env": {
      "node": true
    },"extends": [
      "plugin:vue/essential","eslint:recommended"
    ],"parserOptions": {
      "parser": "babel-eslint"
    },"rules": {}
  },"browserslist": [
    "> 1%","last 2 versions","not dead"
  ]
}

我的ReactJs项目代码

App.js

import React,{ useState } from 'react';
import logo from './logo.svg';
import './App.css';
import './components/dist/addition-component';


function App() {
  const [ n1,setN1 ] = useState(0);
  const [ n2,setN2 ] = useState(0);

  return (
    <div className="App">
      <input type="number" value={n1} onChange={ e => setN1(e.target.value)}/><br/>
      <input type="number" value={n2} onChange={ e => setN2(e.target.value)}/>
      <addition-component num1={n1} num2={n2} />
    </div>
  );
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,document.getElementById('root')
);

serviceWorker.unregister();

package.json

{
  "name": "app-form-test","dependencies": {
    "@testing-library/jest-dom": "^4.2.4","@testing-library/react": "^9.3.2","@testing-library/user-event": "^7.1.2","@webcomponents/webcomponentsjs": "^2.4.4","react": "^16.13.1","react-dom": "^16.13.1","react-scripts": "3.4.1","vendor-copy": "^2.0.0","vuera": "^0.2.7"
  },"scripts": {
    "postinstall": "vendor-copy","start": "react-scripts start","build": "react-scripts build","test": "react-scripts test","eject": "react-scripts eject"
  },"eslintConfig": {
    "extends": "react-app"
  },"browserslist": {
    "production": [
      ">0.2%","not dead","not op_mini all"
    ],"development": [
      "last 1 chrome version","last 1 firefox version","last 1 safari version"
    ]
  },"presets": [
    "react"
  ],"plugins": [
    "vuera/babel"
  ],"vendorcopy": [
    {
      "from": "node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js","to": "public/vendor/custom-elements-es5-adapter.js"
    },{
      "from": "node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js","to": "public/vendor/webcomponents-bundle.js"
    }
  ]
}

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <Meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <Meta name="viewport" content="width=device-width,initial-scale=1" />
    <Meta name="theme-color" content="#000000" />
    <Meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    
    <div id="root"></div>
  </body>
  <script src="%PUBLIC_URL%/vendor/webcomponents-bundle.js"></script>
  <script>if (!window.customElements) { document.write("<!--"); }</script>
  <script src="%PUBLIC_URL%/vendor/custom-elements-es5-adapter.js"></script>
  <!--! DO NOT REMOVE THIS COMMENT,WE NEED ITS CLOSING MARKER -->
</html>

解决方法

只有71%的人(现在已经有将近十年的时间)符合W3C WebComponents标准。

您必须自己开发29%的资源才能使WebComponents在React中工作

为什么Is it really necessary to make and use new custom elements and web components (HTML tags)?

71%得分Custom Elements eveyrwhere

React docs的建议是:

想使用WebComponents和React吗? 重写 Web组件以使用React语法...

这就像特斯拉在说:

您的电池没电了吗?然后安装旧的柴油发动机!

这就像现代的2020前端开发人员所说:

您无法选择DOM元素?好吧,那就用jQuery吧!

Vue,Angular,Svelte等人,Custom Elements eveyrwhere上的得分均为100%

,

webcomponents 中的 props 不能包含数字或大写字母。尝试更改道具名称。