// main.js
/*
import * as Vue from 'vue';
import * as echarts from 'echarts';
window.Vue = Vue;
window.Echarts = echarts;
*/
// 远程组件加载示例
{/*
<template>
<component: is="componentKey" ></component>
</template >
<script>
import {
defineComponent,
defineAsyncComponent
} from "vue";
export default defineComponent({
setup(props) {
const componentKey = defineAsyncComponent(
() =>
new Promise(
(resolve, reject) => {
if (window.__SATISFACTION_REMOTE_COMPONENT_TABLE_SELECTION_TRANSFER) {
resolve(window.__SATISFACTION_REMOTE_COMPONENT_TABLE_SELECTION_TRANSFER);
}
// 注意url需要转防xss安全处理:如下处理方法
const strReplaceXss = (str) => {
const specailToStr = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
',': ',',
';': ';',
'(': '(',
')': ')',
};
return (str || '').replace(/[&<>"',;()]/g, (val) => specailToStr[val]);
};
encodeURI(strReplaceXss(url));
// 注意url需要转防xss安全处理
fetch('/CommonComponentFront/satisfaction_table_selection_transfer.0.0.1.umd.js', {
method: 'GET',
mode: 'cors',
})
.then(response => response.text())
.then(text => {
const script = document.createElement('script');
script.text = text;
document.body.appendChild(script);
resolve(window.__SATISFACTION_REMOTE_COMPONENT_TABLE_SELECTION_TRANSFER);
})
.catch(reject);
}
),
);
return {
componentKey
}
},
});
</script> */}
// 语法糖形式
{/*
<script setup>
import { ref,toRefs, markRaw, unref, watch } from 'vue';
defineOptions({
inheritAttrs: false,
});
const props = defineProps({
url:{
type: String,
default: '/CommonComponentFront/satisfaction_remote_component_table_selection_transfer.0.0.1.umd.js?name=__SATISFACTION_REMOTE_COMPONENT_TABLE_SELECTION_TRANSFER'
}
});
const { url } = toRefs(props);
const componentKey = ref(null);
// 特殊字符转义
const strReplaceXss = (str) => {
const specailToStr = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
',': ',',
';': ';',
'(': '(',
')': ')',
};
return (str || '').replace(/[&<>"',;()]/g, (val) => specailToStr[val]);
};
const loadScript = (url) => {
const str = unref(url);
// url编码后参数name提取
const params = new URLSearchParams(`?${encodeURI(strReplaceXss(str).split('.js?')[1] || '')}`);
const name = params.get('name');
if (!name) {
return;
}
if (window[name]) {
componentKey.value = markRaw(window[name]);
} else {
fetch(str, {
method: 'GET',
mode: 'cors',
}).then((res) => {
if (res.status === 200) {
res.text().then((code) => {
const script = document.createElement('script');
script.text = code;
document.body.appendChild(script);
componentKey.value = markRaw(window[name]);
});
}
});
}
return;
};
watch(
() => url,
(val) => {
loadScript(val);
},
{ deep: true, immediate: true }
);
</script>
*/}
//将name直接配置在url参数上的方案代码:
/**********开始**********
url = /CommonComponentFront/famliyPorutin__selection_transfer.0.0.1.umd.js?name=__FMAILYPORUTIN_GROUP_SELFTEST_ECHARTS
const params = new URLSearchParams(`?${encodeURI(strReplaceXss(url).split('.js?')[1] || '')}`);
const name = params.get('name');
if (!name) {
return;
}
if (window[name]) {
mode.value = markRaw(window[name]);
} else {
fetch(url, {
method: 'GET',
mode: 'cors',
}).then(response => response.text()).then(text => {
const script = document.createElement('script');
script.text = text;
document.body.appendChild(script);
resolve(window[name]);
});
}
**********结束**********/
// vite.config.js配置
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { resolve } from 'path';
import pkg from './package.json';
export default defineConfig({
define: {
'process.env.NODE_ENV': '"production"'
},
build: {
cssCodeSplit: true,
reportCompressedSize: false,
// minify: 'terser',
// terserOptions: {
// compress: {
// drop_console: true,
// drop_debugger: true,
// },
// },
outDir: 'CommonComponentFront',
lib: {
target: 'esnext',
formats: ['es', 'umd'],
entry: resolve(__dirname, 'src/components/remote/BaseTableSelectionTransfer.vue'),
name: '__SATISFACTION_REMOTE_COMPONENT_TABLE_SELECTION_TRANSFER',
fileName: (format) => `satisfaction_table_selection_transfer.${pkg.version}.${format}.js`
},
rollupOptions: {
external: ['vue', 'elementPlus', 'echarts'],
output: {
globals: {
vue: 'Vue',
elementPlus: 'ElementPlus',
echarts: 'Echarts'
}
}
}
},
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': resolve(__dirname, './src')
}
}
});
/*********************************************************************************/
// package.json
{
"name": "satisfaction_remote_component_table_selection_transfer",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"axios": "1.6.1",
"echarts": "5.4.2",
"element-plus": "2.3.12",
"vue": "3.3.4",
"vue-router": "4.2.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.1.1",
"less": "^4.1.3",
"postcss-import": "^15.1.0",
"postcss-url": "^10.1.3",
"vite": "^4.3.5"
}
}
// vite.config.js配置
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { resolve } from 'path';
import pkg from './package.json';
export default defineConfig({
define: {
'process.env.NODE_ENV': '"production"'
},
build: {
cssCodeSplit: true,
outDir: 'CommonComponentFront',
reportCompressedSize: false,
lib: {
target: 'esnext',
formats: ['es', 'umd'],
entry: resolve(__dirname, 'src/components/index.vue'),
name: `__${pkg.name.toLocaleUpperCase()}`,
fileName: (format) => `${pkg.name}.${pkg.version}.${format}.js`
},
rollupOptions: {
external: ['vue', 'elementPlus', 'echarts'],
output: {
globals: {
vue: 'Vue',
elementPlus: 'ElementPlus',
echarts: 'Echarts'
}
}
}
},
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': resolve(__dirname, './src')
}
}
})
// App.vue
<template>
<component :is="mode" ></component>
</template>
<script setup>
import { ref,toRefs, markRaw, unref, watch } from 'vue';
defineOptions({
inheritAttrs: false,
});
const props = defineProps({
// 远程js地址
url:{
type: String,
default: '/CommonComponentFront/satisfaction_remote_component_table_selection_transfer.0.0.1.umd.js?name=__SATISFACTION_REMOTE_COMPONENT_TABLE_SELECTION_TRANSFER'
}
});
const { url } = toRefs(props);
const mode = ref(null);
// 特殊字符转义
const strReplaceXss = (str) => {
const specailToStr = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
',': ',',
';': ';',
'(': '(',
')': ')',
};
return (str || '').replace(/[&<>"',;()]/g, (val) => specailToStr[val]);
};
// 加载远程js
const loadScript = (url) => {
const str = unref(url);
// url编码后参数name提取
const params = new URLSearchParams(`?${encodeURI(strReplaceXss(str).split('.js?')[1] || '')}`);
const name = params.get('name');
if (!name) {
return;
}
if (window[name]) {
mode.value = markRaw(window[name]);
} else {
fetch(str, {
method: 'GET',
mode: 'cors',
}).then((res) => {
if (res.status === 200) {
res.text().then((code) => {
const script = document.createElement('script');
script.text = code;
document.body.appendChild(script);
mode.value = markRaw(window[name]);
});
}
});
}
return;
};
watch(
() => url,
(val) => {
loadScript(val);
},
{ deep: true, immediate: true }
);
</script>
<style lang="less">
#app,body,html{
width: 100%;
height: 100%;
}
</style>
// main.js
import { createApp } from 'vue';
import * as Vue from 'vue';
import * as echarts from 'echarts';
import App from './App.vue';
import ElementPlus from 'element-plus';
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
import 'element-plus/dist/index.css';
window.Vue = Vue;
window.Echarts = echarts;
const app = createApp(App);
app.use(ElementPlus, {
locale: zhCn
});
app.mount('#app');
/*********************************************************************************/
console