微前端 - qiankun
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
本文主要记录下如何接入 qiankun 微前端。主应用使用 vue2,子应用使用 vue3、react。
一、主应用
主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start 即可。
1、创建项目
// @vue/cli 5.0.4
npm install @vue/cli -g
vue create main-vue
主应用选择 vue2.x 版本。 具体创建步骤,便不在此一一叙述。
s
项目创建之后,配置路由,页面布局等。整体效果如下图。
2、安装 qiankun
npm i qiankun -S
3、 注册微应用并启动
新建微应用子列表文件 micros/app.js
// src/micros/app.js
// 子应用列表
const apps = [
{
name: 'vue2-app', // 子应用app name 推荐与子应用的package的name一致
entry: '//localhost:8081/', // 子应用的入口地址,就是你子应用运行起来的地址
container: '#micro-container', // 挂载子应用内容的dom节点 `# + dom id`【见上面app.vue】
activeRule: '/vue2App' // 子应用的路由前缀
},
{
name: 'vue3-app',
entry: '//localhost:8082/',
container: '#micro-container',
activeRule: '/vue3App'
},
{
name: 'react-app',
entry: '//localhost:8083/',
container: '#micro-container',
activeRule: '/react'
}
]
export default apps
注册微应用
// src/micros/index.js
import { addGlobalUncaughtErrorHandler, registerMicroApps, start} from 'qiankun'
// 微应用的信息
import apps from './app'
/**
* 注册微应用
* 第一个参数 - 微应用的注册信息
* 第二个参数 - 全局生命周期钩子
*/
registerMicroApps(apps, {
// qiankun 生命周期钩子 - 微应用加载前
beforeLoad: (app) => {
// 加载微应用前,加载进度条
console.log('before load=====', app.name)
return Promise.resolve()
},
// qiankun 生命周期钩子 - 微应用挂载后
afterMount: (app) => {
// 加载微应用前,进度条加载完成
console.log('after mount=====', app.name)
return Promise.resolve()
}
}
)
/**
* 添加全局的未捕获异常处理器
*/
addGlobalUncaughtErrorHandler((event) => {
console.error(event)
const { message: msg } = event
if (msg && msg.includes('died in status LOADING_SOURCE_CODE')) {
console.error('微应用加载失败,请检查应用是否可运行')
}
})
// 导出 qiankun 的启动函数
export default start
配置主应用路由
// src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: () => import('@/components/Home.vue'),
children: [{
path: '/',
name: 'hello',
component: () => import('@/views/HomeView.vue')
},{
path: '/vue2App',
name: 'vue2App'
}, {
path: '/vue3App',
name: 'vue3App'
}, {
path: '/vue3App/list',
name: 'vueAppList'
}, {
path: '/react',
name: 'react'
}]
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
页面设置子应用的挂载节点
<template>
<div class="wrapper">
<MyHeader></MyHeader>
<el-container class="content">
<el-aside width="200px">
<MySider></MySider>
</el-aside>
<el-main>
<router-view></router-view>
<!-- 挂载子应用节点 -->
<div id="micro-container"></div>
</el-main>
</el-container>
</div>
</template>
<script>
import MyHeader from './Header.vue'
import MySider from './Sider.vue'
export default {
name: 'MyHome',
components: {
MyHeader,
MySider
},
data() {
return {
}
}
}
</script>
<style lang="less">
.content {
height: calc(100% - 50px);
}
</style>
在 main.js 中引入并启动 qiankun
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import '../src/assets/style/reset.less'
import './plugins/element.js'
import start from '@/micros'
// 启动
start()
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
二、微应用
微应用分为有 webpack 构建和无 webpack 构建项目,有 webpack 的微应用(主要是指 Vue、React、Angular)需要做的事情有:
新增 public-path.js 文件,用于修改运行时的 publicPath。
微应用建议使用 history 模式的路由,需要设置路由 base,值和它的 activeRule 是一样的。
在入口文件最顶部引入 public-path.js,修改并导出三个生命周期函数。
修改 webpack 打包,允许开发环境跨域和 umd 打包。
无 webpack 构建的微应用直接将 lifecycles 挂载到 window 上即可。
微应用无需安装 qiankun。
三、vue2-app 微应用
1、创建项目
// vue-cli 2.9.6
npm install vue-cli -g
npm install webpack-cli -g
npm init webpack vue-app
2、在 src 目录新增 public-path.js
// src/public-path.js
if(window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
修改路由文件,建议使用history 模式的路由,并设置路由 base,值和它的 activeRule 是一样的。
// src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
mode: 'history',
base: window.__POWERED_BY_QIANKUN__ ? "/vue2App" : "/",
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围。并导出三个生命周期函数。
// src/main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import "./public-path";
Vue.config.productionTip = false
// 定义一个Vue实例
let instance = null
// 渲染方法
function render(props = {}) {
const { container } = props
instance = new Vue({
router,
render: (h) => h(App)
}).$mount(container ? container.querySelector('#app'): '#app')
}
// 独立运行时
if(!window.__POWERED_BY_QIANKUN__) {
render()
}
//暴露主应用生命周期钩子
/**
* bootstrap : 在微应用初始化的时候调用一次,之后的生命周期里不再调用
*/
export async function bootstrap() {
console.log('vue2-app bootstraped');
}
/**
* mount : 在应用每次进入时调用
*/
export async function mount(props) {
console.log('vue2-app mount', props);
render(props);
}
/**
* unmount :应用每次 切出/卸载 均会调用
*/
export async function unmount() {
console.log("vue2-app unmount")
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
}
修改 webpack 打包,允许开发环境跨域和 umd 打包。
// build/webpack.base.conf.js
'use strict'
const config = require('../config')
const APP_NAME = require('../package.json').name
module.exports = {
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath,
// 微应用的包名,这里与主应用中注册的微应用名称一致
library: APP_NAME,
// 将你的 library 暴露为所有的模块定义下都可运行的方式
libraryTarget: "umd",
// 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可
jsonpFunction: `webpackJsonp_${APP_NAME}`,
},
...
}
// build/webpack.dev.conf.js
const devWebpackConfig = merge(baseWebpackConfig, {
...
devServer: {
...
// 关闭主机检查,使微应用可以被 fetch
disableHostCheck: true,
// 配置跨域请求头,解决开发环境的跨域问题
headers: {
"Access-Control-Allow-Origin": "*",
}
}
})
运行效果如下:
四、vue3-app 微应用
1、创建项目
// @vue/cli 5.0.4
npm install @vue/cli -g
vue create vue3-app
2、在 src 目录新增 public-path.ts
// src/public-path.ts
if ((window as any).__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
修改路由文件。
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
const routes: Array<RouteRecordRaw> = [
{
path: "/",
name: "home",
component: () => import("@/components/Home.vue"),
children: [
{
path: "/",
name: "index",
component: () => import("../views/HomeView.vue"),
},
{
path: "/list",
name: "list",
component: () => import("../views/AboutView.vue"),
},
],
},
];
const router = createRouter({
history: createWebHistory(
window.__POWERED_BY_QIANKUN__ ? "/vue3App" : process.env.BASE_URL
),
routes,
});
export default router;
入口文件 main.ts 修改
// src/main.ts
import Vue, { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import "./public-path.ts";
// 定义一个Vue实例
let instance: Vue.App<Element>;
// 需要定义该接口,否则`/src/router/index.ts`无法使用`Window.__POWERED_BY_QIANKUN__`
declare global {
interface Window {
__POWERED_BY_QIANKUN__?: string;
}
}
interface IRenderProps {
container: Element | string;
}
// 渲染方法
function render(props: IRenderProps) {
const { container } = props;
instance = createApp(App);
instance
.use(store)
.use(router)
.mount(
container instanceof Element
? (container.querySelector("#app") as Element)
: (container as string)
);
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render({ container: "#app" });
}
//暴露主应用生命周期钩子
/**
* bootstrap : 在微应用初始化的时候调用一次,之后的生命周期里不再调用
*/
export async function bootstrap() {
console.log("vue3-app bootstraped");
}
/**
* mount : 在应用每次进入时调用
*/
export async function mount(props: any) {
console.log("mount vue3-app", props);
render(props);
}
/**
* unmount :应用每次 切出/卸载 均会调用
*/
export async function unmount() {
console.log("unmount vue3-app app");
instance.unmount();
}
修改 webpack 打包,允许开发环境跨域和 umd 打包。
注意:webpack5 中 jsonpFunction 修改为 chunkLoadingGlobal
// vue.config.js
const path = require("path");
const APP_NAME = require("./package.json").name;
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
outputDir: "dist",
assetsDir: "static",
filenameHashing: true,
devServer: {
host: "localhost",
hot: true,
port: 8082,
client: {
overlay: {
errors: true,
warnings: false,
},
},
// 配置跨域请求头,解决开发环境的跨域问题
headers: {
"Access-Control-Allow-Origin": "*",
},
},
// 自定义webpack配置
configureWebpack: {
resolve: {
alias: {
"@": resolve("src"),
},
},
output: {
// 把子应用打包成 umd 库格式
// // 微应用的包名,这里与主应用中注册的微应用名称一致
library: APP_NAME,
// 将你的 library 暴露为所有的模块定义下都可运行的方式
libraryTarget: "umd",
// 按需加载相关,设置为 webpackJsonp_微应用名称 即可
chunkLoadingGlobal: `webpackJsonp_${APP_NAME}`,
},
},
};
运行效果如下:
五、react-app 微应用
1、创建项目,以 create-react-app 生成的 react 17 项目为例,搭配 react-router-dom 6.x。
npx create-react-app react-app --template typescript
npm i react-router-dom
在根目录下添加 .env 文件,设置项目监听的端口
// react-app/.env
PORT=8083
BROWSER=none
2⃣️、新建 public-path.ts
// src/public-path.ts
if ((window as any).__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
如上面代码报错,可以通过补充定义进行修复。以下代码最好放到全局引入的 TypeScript 定义文件中。
interface Window {
__POWERED_BY_QIANKUN__?: string
__INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string
}
declare let __webpack_public_path__: string | undefined
设置 history 模式路由的 base
// src/App.tsx
import React from 'react';
import { Routes, Route, BrowserRouter} from 'react-router-dom'
import './App.css';
import Home from './components/home';
function App() {
return (
<div>
{/* 设置路由命名空间 */}
<BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/react' : '/'}>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
修改入口文件 index.tsx
// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import './types.d.ts'
import "./public-path";
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap() {
console.log('react-app bootstraped');
}
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props: any) {
console.log('react-app mount');
ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount(props: any) {
console.log('react-app unmount');
ReactDOM.unmountComponentAtNode(props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}
/**
* 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
*/
export async function update(props: any) {
console.log('react-app update props', props);
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
修改 webpack 配置,安装插件 react-app-rewired
npm install react-app-rewired -D
修改 package.json
// react-app/package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
}
在 react-app-rewired 配置完成后,新建 config-overrides.js 文件来配置 webpack。
// react-app/config-overrides.js
const path = require("path");
const APP_NAME = require("./package.json").name;
module.exports = {
webpack: (config) => {
// 微应用的包名,这里与主应用中注册的微应用名称一致
config.output.library = APP_NAME;
// 将你的 library 暴露为所有的模块定义下都可运行的方式
config.output.libraryTarget = "umd";
// 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可
config.output.chunkLoadingGlobal = `webpackJsonp_${APP_NAME}`;
config.output.globalObject = 'window';
config.output.publicPath = `//localhost:${process.env.PORT}/`;
config.resolve.alias = {
...config.resolve.alias,
"@": path.resolve(__dirname, "src"),
};
return config;
},
devServer: function (configFunction) {
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost);
// 关闭主机检查,使微应用可以被 fetch
// config.disableHostCheck = true;
config.allowedHosts = "all";
// 配置跨域请求头,解决开发环境的跨域问题
config.headers = {
"Access-Control-Allow-Origin": "*",
};
// 配置 history 模式
config.historyApiFallback = true;
return config;
};
},
};
3、运行效果如下
原文链接:https://blog.csdn.net/lhz_333/article/details/123767105
相关文章:

微前端 - qiankun
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。 本文主要记录下如何接入 qiankun 微前端。主应用使用 vue2,子应用使用 vue3、react。 一、主应用 主应用不限技术栈,只需要提…...

前端编辑页面修改后和原始数据比较差异
在软件研发过程中,会遇到很多编辑页面,有时编辑页面和新增页面长的基本上一样,甚至就是一套页面供新增和编辑共用。编辑页面的场景比较多,例如: 场景一、字段比较多,但实际只修改了几个字段,如…...
docker第一次作业
docker第一次作业 1.安装docker服务,配置镜像加速器 yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i sdownload.docker.commirrors.aliy…...
Springboot3.0.0+集成SpringDoc并配置knife4j的UI
环境:JDK17,Springboot3,springdoc2,knife4j 4 Springdoc本身也是集成了Swagger3,而knife4j美化了Swagger3的UI Knife4j官网: 快速开始 | Knife4j Springdoc官网 OpenAPI 3 Library for spring-boot 1.pom配置 由于此knife4j内依赖了S…...

电脑运行缓慢?4个方法,加速电脑运行!
“我电脑才用了没多久哎!怎么突然就变得运行很缓慢了呢?有什么方法可以加速电脑运行速度吗?真的很需要,看看我吧!” 电脑的运行速度快会让用户在使用电脑时感觉愉悦,而电脑运行缓慢可能会影响我们的工作效率…...
3.Docker 搭建 MySQL8.0
1、docker仓库搜索mysql docker search mysql2、docker仓库拉取mysql8.0 docker pull mysql:8.0 备注: docker pull mysql //默认拉取最新版本3、查看本地仓库镜像是否下载成功 docker images mysql:8.04、安装运行mysql8.0容器 docker run -p 3306:3306 --name…...

Mybatis的SqlSource SqlNode BoundSql
学习链接 MyBatis SqlSource解析 【Mybatis】Mybatis源码之SqlSource#getBoundSql获取预编译SQL Mybatis中SqlSource解析流程详解 Mybatis TypeHandler解析 图解 Mybatis的SqlSource&SqlNode - processon DynamicSqlSource public class DynamicSqlSource implement…...

html动态爱心代码【二】(附源码)
目录 前言 效果演示 内容修改 完整代码 总结 前言 七夕马上就要到了,为了帮助大家高效表白,下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐,可用于520,情人节,生日,表白等场景,…...

【Rust】Rust学习 第十六章无畏并发
安全且高效的处理并发编程是 Rust 的另一个主要目标。并发编程(Concurrent programming),代表程序的不同部分相互独立的执行,而 并行编程(parallel programming)代表程序不同部分于同时执行,这两…...

系统报错mfc100u.dll丢失的解决方法(完美解决dll问题)
系统文件mfc100u.dll丢失和出错,极有可能是盗号木马、流氓软件等恶意程序所导致,其感染相关文件并加载起来,一旦杀毒软件删除被感染的文件,就会导致相关组件缺失,游戏等常用软件运行不起来,且提示“无法启动…...

docker compose的用法
目录 一、Docker-Compose介绍 1.1 Docker-Compose的概述 1.2 Docker-Compose 用来实现Docker容器快速编排 1.3 Docker-compose模板文件简介 二、YAML简介 2.1 YAML的概述 2.2 YAML的基本语法规则 2.3 YAML支持的数据架构 三、配置内部常用字段 四、Docker-compose 常…...

Linux: 使用 ssh 连接其他服务器
通过ifconfig 查看要连接的服务器地址: ubuntuubuntu1804-0172:/media/sangfor/vdc$ ssh ubuntu192.168.11.49 输入要连接的服务器密码: ubuntua192.168.1149 s password: 连接服务器成功:...

[.NET/WPF] CommunityToolkit.Mvvm 异步指令
我们在开发中, 经常会有这样的需求: 点击按钮后, 进行一些耗时的工作工作进行时, 按钮不可再次被点击工作进行时, 会显示进度条, 或者 “加载中” 的动画 RelayCommand CommunityToolkit.Mvvm 中的 RelayCommand 除了支持最简单的同步方法, 还支持以 Task 作为返回值的异步方…...

热烈祝贺汇隆成功入选航天系统采购供应商库
经过航天系统采购平台的严审,浙江汇隆晶片技术有限公司成功入选中国航天系统采购供应商库。航天系统采购平台是航天系统内企业采购专用平台,服务航天全球范围千亿采购需求,目前,已有华为、三一重工、格力电器、科大讯飞等企业、机…...

2019年3月全国计算机等级考试真题(C语言二级)
2019年3月全国计算机等级考试真题(C语言二级) 第1题 负责数据库中查询操作的数据库语言是 A. 数据定义语言 B. 数据管理语言 C. 数据操纵语言 D. 数据控制语言 正确答案:C 第2题 有关系如下图所示,其违反了哪一类完整性约束 …...
MySQL 游标
文章目录 1.游标是什么2.MySQL 游标3.定义游标4.打开游标5.提取数据6.关闭游标参考文献 1.游标是什么 游标(Cursor)是一种用于处理查询结果集的数据库对象,它允许开发者按照特定的顺序逐行遍历查询结果集中的数据。游标通常用于在数据库中执…...

ElasticSearch 7.4学习记录(DSL语法)
上文和大家一起初次了解了很多ES相关的基础知识,本文的内容将会是实际企业中所需要的吗,也是我们需要熟练应用的内容。 面对ES,我们最多使用的就是查询,当我负责这个业务时,现不需要我去考虑如何创建索引,添…...

全志orangepi-zero2驱动编写2,控制电平高低
使用驱动编写控制高低电平 可看我前俩篇文章: 【1】全志orangepi-zeor2驱动编写 【2】驱动函数框架详解 检索芯片手册关键信息 知道GPIO基地址 知道PC偏移地址 知道想要控制的端口的信息 知道数据位如何操作 代码实操 驱动代码 #include <linux/fs.h&…...
软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章四
软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章四 一、论软件的静态演化和动态演化及其应用1.论文题目2.写作要点和写作素材二、论大规模分布式系统缓存设计策略1.论文题目2.写作要点和写作素材三、论基于REST服务的Web应用系统设计1.论文题目2.写…...
06.利用Redis实现点赞功能
学习目标: 提示:学习如何利用Redisson实现点赞功能 学习产出: 解决方案: 点赞后的用户记录在Redis的set数据类型中 1. 准备pom环境 <dependency><groupId>org.springframework.boot</groupId><artifactI…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...