远程加载组件,动态更新组件,主框架不更新

参考 https://gitee.com/fanzhengshao/remote-components-library

用vite创建一个vue项目

添加remote目录,存放远程组件
添加rollup.config.js,用来打包配置远程组件

//  rollup.config.js
import vuePlugin from 'rollup-plugin-vue'
import babel from '@rollup/plugin-babel'
import json from "@rollup/plugin-json";
import postcss from 'rollup-plugin-postcss'
const path = require('path')
const resolve = (p) => {return path.resolve(__dirname, p)
}
const getEntry = (component) => {return resolve(`./remote/${component}/index.js`)
}const titleCase = (strs) =>{let arr = strs.split('-')let newTitle =''arr.forEach(o=>{newTitle+= (o.slice(0,1).toUpperCase() + o.slice(1).toLowerCase())})return newTitle
}const basePlugins = [vuePlugin(),json(), // 可以将 .json 文件转换为 ES6 模块babel({babelHelpers: 'bundled',exclude: 'node_modules/**'}),]
const devPlugins= []
const prodPlugins = []
const generalPlugins = (name) => {return [...basePlugins,postcss({// extract: true,// Or with custom file nameextract: path.resolve(`remoteDist/${name}/remote-${name}.css`)})]
}
const externals = ["vue"]
const getPackageConfig = (name) => {return {input: getEntry(name),output: [{file: `remoteDist/${name}/remote-${name}.umd.js`,format: 'umd',name: `Remote_${titleCase(name)}`,globals: { // 设定全局变量的名称'vue': 'Vue',},exports: "named",},],plugins: [...generalPlugins(name)],external: [...externals]}
}
export default [getPackageConfig('button'),getPackageConfig('loading')
]

修改package.json

"scripts": {"dev:main": "vite",// 开发模式"build:remote": "rollup -c",// 打包远程组件"build:main": "vite build",// 打包项目"preview": "vite preview"
},
"dependencies": {"vue": "^3.2.25"
},
"devDependencies": {"@vitejs/plugin-vue": "^2.3.0","vite": "^2.9.0","postcss": "^8.3.11","@rollup/plugin-babel": "^5.3.0","@rollup/plugin-json": "^4.1.0","rollup-plugin-postcss": "^4.0.1","rollup-plugin-vue": "^6.0.0","@babel/core": "^7.15.8","@babel/preset-env": "^7.15.8"
}

开发远程组件

假设我们要开发一个button组件
在remote中新建一个Button文件夹,在文件夹中新建index.js,index.vue。

index.js
import ScadaButton from './index.vue';
const install = (app) => {app.component(ScadaButton.name, ScadaButton);
}
export default {install,ScadaButton
}
index.vue
<template><div><button class="scadaButton" @click="clickHandler">我是一个Button组件</button></div>
</template>
<script>
export default {name: 'ScadaButton',methods: {clickHandler() {console.log('点击了我的按钮哦');}}
}
</script><style>
.scadaButton{color: red;
}
</style>

在vue项目中使用这个组件,App.vue引入组件并使用,import ButtonTest from ‘…/remote/Button/index.vue’,得到如下界面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EFdWD5Aj-1665380594002)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a627ecb6b3cf4c6e975cd5164ed0bcfe~tplv-k3u1fbpfcp-watermark.image?)]

打包组件

运行 npm run build:remote,得到生成目录remoteDist

运行组件web服务

进入remoteDist目录,运行python -m http.serve 9001启动web服务

编写远程加载组件的组件

在components目录新建 Remote.vue

/**
* ======================================
* 远程加载组件
* author: admin
* file: Remote.vue
* date: 2022/4/11 16:46
* ======================================
*/
<template><component :is="mode" v-bind="$attrs"></component>
</template><script>
import {markRaw, onMounted, ref,toRefs} from "vue";export default {name: "Remote",// 如果你不希望组件的根元素继承特性,你可以在组件的选项中设置inheritAttrs: falseinheritAttrs: false,props: {componentInfo: {type: Object,default() {return {js: '',css: '',libraryName: '',componentName: ''}}}},setup(props, { emit }) {let mode = ref(null);const {js,css,libraryName,componentName} = toRefs(props.componentInfo)console.log("props",js,css,libraryName,componentName)/*** 使用动态 script方式加载远程js*/function asyncScript(url) {// 动态scriptreturn new Promise((resolve, reject) => {const script = document.createElement("script");const target = document.getElementsByTagName("script")[0] || document.head;script.type = "text/javascript";script.src = url;script.onload = resolve;script.onerror = reject;target.parentNode.insertBefore(script, target);});}/*** 加载js* @param url js文件地址* @param libraryName 库名* @param componentName 组件名* @return {Promise<void>}*/async function loadScript(url, libraryName,componentName) {// 动态scriptawait asyncScript(url);console.log(window[libraryName]);mode.value = markRaw(window[libraryName].default[componentName]);}/*** 加载样式* @param url css样式文件地址*/function loadStyles(url) {let link = document.createElement("link");link.rel = "stylesheet";link.type = "text/css";link.href = url;let head = document.getElementsByTagName("head")[0];head.appendChild(link);}onMounted(() => {// 加载cssloadStyles(css.value);// 加载jsloadScript(js.value,libraryName.value,componentName.value);});return {mode,};}
}
</script>

使用远程组件

在main.js中添加,将vue挂载全局

import('vue').then(res => {console.log("vue",res)window.Vue = res
})

然后在需要使用组件的地方添加

import Remote from "./components/Remote.vue"
<remote :component-info="componentInfo"/>componentInfo:{js:'http://localhost:9001/button/remote-button.umd.js',css:'http://localhost:9001/button/remote-button.css',libraryName:'Remote_Button',componentName:'ScadaButton'
}

得到如下界面,此时修改这个按钮组件文件,远程加载的不会在改变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AdtUmxwj-1665380594003)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ec4c3c06e96140ad8f0f676e709e014b~tplv-k3u1fbpfcp-watermark.image?)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTWVhFcN-1665380594004)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cb92690ea8d64ce3b00634fbfbe2a291~tplv-k3u1fbpfcp-watermark.image?)]

浏览器网络请求中有这个组件的文件加载

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fDV8tDB4-1665380594004)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/382c115c0b0a4739812b3a7b6b2a823c~tplv-k3u1fbpfcp-watermark.image?)]

组件示例

/*** ======================================* 这是个示例* author: admin* file: RemoteBaseComponent.vue* date: 2022/4/11 16:46* ======================================*/
<template><div>当你看到这个时,远程组件应该可以工作了!<component :is="mode" v-bind="$attrs"></component></div>
</template><script>
import { markRaw,  onMounted, ref, defineComponent } from "vue";export default defineComponent({name: "RemoteBaseComponent",// inheritAttrs: false,props: {componentInfo: {type:Object,default(){return{js:'',css:'',libraryName:'',componentName:''}}},},setup(props, { emit }) {let mode = ref(null);const type = ref(props.type);/*** 使用动态 script方式加载远程js*/function asyncScript(url) {// 动态scriptreturn new Promise((resolve, reject) => {const script = document.createElement("script");const target =document.getElementsByTagName("script")[0] || document.head;script.type = "text/javascript";script.src = url;script.onload = resolve;script.onerror = reject;target.parentNode.insertBefore(script, target);});}/*** 加载js* @param url js文件地址* @param componentName 组件名* @return {Promise<void>}*/async function loadScript(url, componentName) {// 动态scriptawait asyncScript(url);console.log(window.Remote_Button);mode.value = markRaw(window.Remote_Button.default.ScadaButton);}/*** 加载样式* @param url css样式文件地址*/function loadStyles(url) {let link = document.createElement("link");link.rel = "stylesheet";link.type = "text/css";link.href = url;let head = document.getElementsByTagName("head")[0];head.appendChild(link);}onMounted(() => {// 加载cssloadStyles(`/button/remote-button.css`);// 加载jsloadScript(`/button/remote-button.umd.js`,"remoteButton");});return {mode,};},
});
</script>

【vue3】远程组件加载相关推荐

  1. 分享下自己写的一个微信小程序请求远程数据加载到页面的代码

    分享下自己写的一个微信小程序请求远程数据加载到页面的代码 1  思路整理 就是页面加载完毕的时候  请求远程接口,然后把数据赋值给页面的变量 ,然后列表循环 2 js相关代码  我是改的 onload ...

  2. webpack配置vue组件加载器

    前言 App.vue单文件组件代码 <template><div><h1>App根组件</h1></div> </template&g ...

  3. 【Flutter】Icons 组件 ( 加载 Flutter 内置的图标 | 材料设计图标完整展示 )

    文章目录 一.加载 Flutter 内置的图标 三.完整代码示例 三.相关资源 四.Icons 图标参考 ( 超长截图 | 材料设计图标完整展示 ) 一.加载 Flutter 内置的图标 Flutte ...

  4. Ogre 编辑器二(用Ogre的地形组件加载天龙八部地形)

    主界面如上文设计完成后,场景刚开始添加了是Ogre例子里的,发现场景里实物太少,于是想到直接把天龙的场景拿下来,天龙网上有源码,参考了下,把天龙的地形用Ogre的地形组件完成了下,如下是效果图: 因为 ...

  5. 【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting)

    基于 Create React App路由4.0的异步组件加载 本文章是一个额外的篇章,它可以在你的React app中,帮助加快初始的加载组件时间.当然这个操作不是完全必要的,但如果你好奇的话,请随 ...

  6. web.xml 组件加载顺序

    转载自  web.xml 组件加载顺序 在配置项目组件的过程中, 了解Tomcat加载组件顺序很有必要. 例如某些框架如Quartz的集群功能需要数据库的支持, 数据库的加载肯定要在框架组件加载之前. ...

  7. 【转载】使用Imaging组件加载GIF动画

    Mobil手机加载GIF动态图像的方法有两种,一个就是使用GIF89a标准算法,另一个就是使用SDK自带的Imaging组件,这两种方法是很典型的手机图像处理技术的实践.使用Imaging组件加载GI ...

  8. 加载顺序_Java的web.xml组件加载顺序

    在配置项目组件的过程中, 了解Tomcat加载组件顺序很有必要. 例如某些框架如Quartz的集群功能需要数据库的支持, 数据库的加载肯定要在框架组件加载之前. 经过查阅和Debug发现, web.x ...

  9. 【es】es Plugin 组件加载 PluginsService

    1.概述 转载并且补充:[9]elasticsearch源码深入分析--Plugin组件加载 2.开篇 本篇开始将会详细解释Node实例化的过程中PluginsService的相关内容,PluginS ...

最新文章

  1. MySQL:互联网公司常用分库分表方案汇总!
  2. oracle 常用语句
  3. ITK:仅将过滤器应用于图像的指定区域
  4. 如何计算一个神经网络在使用momentum时的hessian矩阵(论文调研)
  5. 什么是js的严格模式
  6. 阿里云数据库mysql 创建数据库服务器_如何使用mysql创建数据库服务器
  7. asp.net回调javascript
  8. Qt入门(六)——抽奖系统的实现
  9. C#调用Bing的在线翻译接口Translator
  10. 唐宇迪数据分析学习笔记
  11. python数据库模糊查询_python中的mysql数据库like模糊查询
  12. [郝斌/王卓]数据结构C语句—链表
  13. 一文带你玩转 DataStore
  14. 【数据结构与算法】| Map和Set
  15. sqlserver数据库限制用户登录失败次数
  16. 如何安装Jenkins
  17. 华为云设计语言_让开发者相见恨晚?!华为云软件开发云实现云上敏捷开发
  18. 【JavaScript】性能优化
  19. 属于db模式缺点的是什么_浅析工程总承包发包模式的投资控制思路(三)
  20. 车载导航不支持播放全部的mp3音乐的解决办法--------fwqlzz love is for ever

热门文章

  1. 从键盘输入一个四位数,输出该四位数的个位,十位,百位和千位数分别是什么。
  2. 防火墙虚拟化技术详解(上)
  3. 数据仓库数据存储与处理
  4. linux shell 入门学习笔记3 shebang
  5. 2024浙江大学计算机考研信息汇总
  6. Assembly 调用的目标发生了异常
  7. php 判断字符串乱码,php如何检测乱码字符
  8. Spring @InitBinder注解
  9. 修改设置 打造安全的个人电脑(转)
  10. Android:Handler中的Idle Handler