当前位置: 首页 > news >正文

手把手教你使用vue2搭建微前端micro-app

简述

本文主要讲述新手小白怎么搭建micro-app,几乎是每一步都有截图说明。上手应该很简单。

研究背景

这段时间在网上找了很多有关微前端相关的知识,起初本来是想着先搭建一个single-spa,但是奈何网上能找到的内容都是千篇一律。我也是搭了好久没搭出来。不知道为啥,反正就是一个劲的报错。
后面发现京东嫌弃single-spa太难用,他们自己搞了一套micro-app,那我想着这个应该比single-spa好用吧。很明显的好处就是,micro-app最起码能找到好理解的官网
但是对于项目的搭建,官网介绍的也是很粗糙,网上找到的也是一上来就npm,对于零基础的新手来说真的是太不友好了。说实话,渣渣的我看了都不知道npm在哪输入。不过还是在一步步的探索中取得了成功。
接下来先看一下搭建成功的效果图吧,图中展示了基座运行和两个子应用下运行的效果,即:可以单独运行,也可以整体运行:

​项目代码
演示效果
看完运行效果后,就开始搭建项目了

1、准备工作

1-1、创建项目

首先第一步就是先创建一个文件夹 ,如下图所示,我这边新建了一个叫micro-app-demo的文件夹,用webStrom打开,效果如下图所示:
​​​​​​​​​​在这里插入图片描述

1-2、创建vue项目

接下来就是创建vue,这个命令之前装single-spa的时候就遇到过,让我升级vue3。
所以你在安装时如果提示你升级,就按照提示进行升级,不然会报错。

vue create base

由于忘记截图,这个是之前搭single-spa时的截图,一样的道理,只是文件夹名称和create名称不一样而已,可以理解大概意思 。
在这里插入图片描述
提示vue create是vue cli3的唯一命令 ,而已使用的是vue cli 2.9.6 ,公司的电脑我也不敢随便改,怕影响到项目,所以接下来就算自己笔记本了。
创建时先升级到vue3

npm uninstall -g vue-cli
npm install -g @vue/cli

我笔记本只安装了vsCode,所以接下来的代码展示都是在vsCode中进行操作的。
接下来就步入正题,开始创建:

2、安装base(基座)

base我这边理解为基座,即:子应用都需要在base基座中配置,类似iframe框架

2-1、创建base,在micro-app-demo文件夹下安装

接上一步,使用vsCode将新建好的文件夹micro-app-demo打开,如下图所示,打开一个新终端,在下面输入命令创建base,创建时可选择vue2还是vue3,我这边以vue2为例,如果要选vue3的话,下面代码中的语法会不一样。
在这里插入图片描述
我这边选择vue2后,安装完成后,效果如下图所示:
在这里插入图片描述
可以从图中看到安装完后的整个目录,既然它有提示让我们运行,那就运行一下看看效果。运行效果如下:
在这里插入图片描述
接下来开始对base进行改造,注:下面的修改都是对base目录下的修改,别搞错地方了。

2-2、添加配置文件vue.config.js

在这里插入图片描述

module.exports = {devServer: {host: 'localhost', port: 3000}
}

2-3、安装micro-app插件,安装在base目录下

在这里插入图片描述

npm install @micro-zoe/micro-app --save

安装完成后可以在package.json文件下看到刚刚安装好的 插件
在这里插入图片描述

2-4、micro配置

接下来创建一个文件夹,文件夹里面有两个js文件
在这里插入图片描述
base/src/micro/index.js

import microApp from '@micro-zoe/micro-app'
import * as config from './config'/**启用 micro */
microApp.start({preFetchApps: config.MICRO_APPS, globalAssets: config.GLOBAL_ASSETS
})

base/src/micro/config.js

/**
* 子应用前缀
*/
export const CHILD_PREFIX = 'app'/**
* 子应用地址
*/
export const MICRO_APPS = [{ name: 'first-child', url: `http://localhost:3001/` }, { name: 'second-child', url: `http://localhost:3002/` }
]/**
* 全局资源
*/
export const GLOBAL_ASSETS = {js: [], css: []
}

2-5、安装路由

这里路由我装低一点的版本,安装完成后package.json中可以看到效果
在这里插入图片描述

npm install vue-router@3

2-6、修改main.js

修改入口文件main.js,引入micro-app配置,在这里顺便将上一步安装的路由也引入
在这里插入图片描述

import './micro'
import Vue from 'vue'
import App from './App.vue'
import router from './router'Vue.config.productionTip = falsenew Vue({router,render: h => h(App),
}).$mount('#app')

2-7、修改App.vue文件

在这里插入图片描述

<template><div id="app"><div id="nav"><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link>|<router-link :to="`/${prefix}/first-child/home`">FirstChildHome</router-link>|<router-link :to="`/${prefix}/first-child/about`">FirstChildAbout</router-link>|<router-link :to="`/${prefix}/second-child/home`">SecondChildHome</router-link>|<router-link :to="`/${prefix}/second-child/about`">SecondChildAbout</router-link></div><div><micro-appv-if="isChild"v-bind="micro"destory@created='created'@beforemount='beforemount'@mounted='mounted'@unmount='unmount'@error='error'@datachange='handleDataChange'></micro-app><router-view v-else></router-view></div></div>
</template><script>
import { MICRO_APPS, CHILD_PREFIX } from './micro/config.js'export default {name: 'App',data () {return {isChild: false      /**是否为子模块 */, micro: {        url: ''       /**子模块地址 */, key: ''       /**vue 标签的 key 值,用于不同子模块间的切换时,组件重新渲染 */, name: ''      /**子模块名称,唯一 */, data: {}      /**子模块数据 */, baseroute: ''   /**子模块数据 */}, prefix: CHILD_PREFIX  /**子模块链接前缀 */}}, watch: {$route (val) { /**监听路由变化修改视图显示 */this.changeChild(val)}}, created () {this.changeChild(this.$route)}, methods: {created () { /**子模块创建 */console.log(`${this.micro.name}-created`)}, beforemount () { /**子模块挂载之前 */console.log(`${this.micro.name}-beforemount`)}, mounted () { /**子模块挂载 */this.loading = falseconsole.log(`${this.micro.name}-mounted`)}, unmount () { /**子模块卸载 */console.log(`${this.micro.name}-unmount`)}, error () { /**子模块异常 */console.log(`${this.micro.name}-error`)}, getAppUrl (name) { /**获取子模块 url 和 name */return MICRO_APPS.find(app => app.name === name) || {}}, changeChild (route) { /**修改子视图显示 */let path = route.path.toLowerCase(), paths = path.split('/')/**判断是否为子模块,子模块有固定的前缀,在 micro/config 设置 */this.isChild = paths.length > 2 && paths[1] === CHILD_PREFIXif (this.isChild) {let app = this.getAppUrl(paths[2])this.micro = {...app, data: { name: route.name }, key: `${app.name}`, baseroute: `/${CHILD_PREFIX}/${paths[2]}`}}}, handleDataChange (event) { /**获取子路由传递的信息 */let data = event.detail.dataif(data.route) this.$router.push({ name: data.route.name })}}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}#nav {padding: 30px;
}#nav a {font-weight: bold;color: #2c3e50;
}#nav a.router-link-exact-active {color: #42b983;
}
</style>

2-8、配置路由

我们虽然在2-5中安装了路由,但是没有对路由进行配置,所以这边要配置一下路由。
刚创建好的vue项目中没有对路由的配置,所以需要手动添加配置。
创建文件夹router,router中添加index.js文件
在这里插入图片描述
base/src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'import { CHILD_PREFIX } from '@/micro/config.js'Vue.use(VueRouter)const routes = [{path: '/', name: 'Home', component: () => import('../views/Home.vue')}, {path: '/about', name: 'About', component: () => import('../views/About.vue')}, {path: `/${CHILD_PREFIX}/first-child`, name: 'FirstChild', children: [{path: 'home', name: 'FirstHome'}, {path: 'about', name: 'FirstAbout'}]}, {path: `/${CHILD_PREFIX}/second-child`, name: 'SecondChild', children: [{path: 'home', name: 'SecondHome'}, {path: 'about', name: 'SecondAbout'}]}
]const router = new VueRouter({mode: 'history', routes
})export default router

2-9、创建视图(views)

创建views文件夹,文件夹下面有home和about两个文件,路由中有配置,所以也需要这个页面。

在这里插入图片描述
base/src/views/Home.vue

<template><div class="home"><img src="../assets/logo.png"><h1>基座-home page</h1></div>
</template><script>
export default {name: 'Home'
}
</script>

base/src/views/About.vue

<template><div class="about"><h1>基座-about page</h1></div>
</template>

到此基座就搭建完成了,因为基座中有对子应用的配置,而子应用还没开始搭建,所以 这边暂时先不运行。

3、创建app_first(子应用1)

子应用为刚刚搭建完base的子应用,在例子中我们搭建两个子应用,为了方便起见,接下来的操作中我们一起把两个子应用都创建好,在去修改里面的配置。

创建之前需要注意的是,子应用与基座的层级关系是并列的,所以创建子应用时目录需要回到micro-app-demo目录下,具体操作如下:

3-1、创建app_first,cd…回到micro-app-demo文件夹下

在这里插入图片描述

cd ..  // 返回上一级目录
vue create app_first

3-2、创建app_second

这边为了减少麻烦我直接把app_second也创建了,等会就不用创建app_second了
在这里插入图片描述

vue create app_second

到这里子应用就都创建完成了,接下来开始对子应用开始配置,因为一下子有了三个目录文件,很容易搞错,所以配置的时候一定要看清楚哪个文件夹下的哪个文件。
接下来开始对app_first(子应用1)的修改,注:接下来的所有修改都在app_first文件夹下

3-3、修改vue.config.js

修改vue.config.js文件,设置允许跨域
在这里插入图片描述

module.exports = {devServer: {host: 'localhost', port: 3001, headers: { // 设置本地运行的跨域权限'Access-Control-Allow-Origin': '*',}}
}

3-4、micro配置

和基座一样,在src下创建文件夹micro/index.js。不同的是,子应用不需要config.js了
在这里插入图片描述
app_first/src/micro/index.js

// 设置 webpack 的公共路径
__webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__ || '/'

3-5、修改main.js

在这里插入图片描述

/**引入 publicPath 设置 */
import './micro'import Vue from 'vue'
import App from './App.vue'
import router from './router'Vue.config.productionTip = false// new Vue({
//  router,
//  render: function (h) { return h(App) }
// }).$mount('#app')let app/**
* 挂载函数
*/
function mount () {app = new Vue({el: '#app',router,render: function (h) { return h(App) }})
}/**
* 卸载函数
*/
function unmount () {app.$destroy()app.$el.innerHTML = ''app = null
}/**微前端环境下,注册mount和unmount方法 */
if (window.__MICRO_APP_ENVIRONMENT__)window[`micro-app-${window.__MICRO_APP_NAME__}`] = { mount, unmount }
elsemount()

3-6、安装路由

在这里插入图片描述

cd app_first // 1.先进入子应用1目录下
npm install vue-router@3 // 2.安装路由

3-7、修改App.vue文件

在这里插入图片描述

<template><div id="app"><div id="nav"><router-link :to="`${prefix}/home`">子应用1Home</router-link> |<router-link :to="`${prefix}/about`">子应用1About</router-link> |<button @click="goto('SecondHome')">SecondHome</button> |<button @click="goto('SecondAbout')">SecondAbout</button></div><router-view /></div>
</template><script>
export default {name: 'App', data () {return {prefix: window.__MICRO_APP_BASE_ROUTE__ || ''}}, methods: {dataListener (data) {if (data.name !== this.$route.name) /** 不判断时会报一个“冗余导航【NavigationDuplicated】”的异常 */this.$router.push({ name: data.name })}, goto (name) {// 向基项目发送数据window.microApp && window.microApp.dispatch({ route: { name } })}},created () {/** 绑定数据【data属性】监听事件 */window.microApp && window.microApp.addDataListener(this.dataListener)}, destroyed () {/** 移除数据【data属性】监听事件 */window.microApp && window.microApp.removeDataListener(this.dataListener)}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}#nav {padding: 30px;
}#nav a {font-weight: bold;color: #2c3e50;
}#nav a.router-link-exact-active {color: #42b983;
}
</style>

3-8、配置路由

创建router文件夹,配置路由
在这里插入图片描述
app_first/src/router/index

import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)const routes = [{path: window.__MICRO_APP_BASE_ROUTE__ || '/' /**根据项目运行的不同环境,设置路径的前缀 */, name: 'Home', redirect: { name: 'FirstHome' }, component: () => import('../views/Empty.vue'), children: [{path: 'home', name: 'FirstHome', component: () => import('../views/Home.vue')}, {path: 'about', name: 'FirstAbout', component: () => import('../views/About.vue')}]}
]const router = new VueRouter({mode: 'history',routes
})export default router

3-9、创建视图(views)

在这里插入图片描述
app_first/src/views/About.vue

<template><div class="about"><h1>First Child About Page</h1></div></template>  

app_first/src/views/Empty.vue

<template><router-view />
</template>

app_first/src/views/Home.vue

<template><div class="home"><imgalt="Vue logo"src="../assets/logo.png"><h1>First Child Home Page</h1></div>
</template><script>
export default {name: 'Home'
}
</script>

到此app_first就算改造完成了,怀着忐忑的心情运行一下,果然,,,没让我失望,是真的在认真报错。

npm run serve

3-10、报错处理

在这里插入图片描述
可以看到有4条错误,先从第一条开始解决吧

bug1:mircro/index.js百度找到要加if条件。就修改了一下,修改完成后就剩3个bug了
在这里插入图片描述

if (window.__MICRO_APP_ENVIRONMENT__) {// eslint-disable-next-line__webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__ || '/'}

bug2:从报错可以看出是view命名的问题,需要驼峰命名啥的,应该是eslint引起的,继续百度解决方法
需要在package.json中修改
在这里插入图片描述

"vue/multi-word-component-names": 0 // 多字符组件名称,不设置检测

修改完成后继续跑,又报错,没路由,奇怪,我刚刚明明装了路由,有上面的截图 为证,但是就是不见了,可能在修改上面bug的时候百度好多种解决方法,试着试着不小心删掉了吧,既然没了那就重装一下吧。
在这里插入图片描述
安装完后又出现了
在这里插入图片描述
安装完成后在重新跑,,,耶耶耶耶耶耶,成功了,效果如下图所示,可以看到子应用1的效果:
在这里插入图片描述

4、创建app_second(子应用2)

接下来开始修改子应用2,(在上面3-2中已经创建好了子应用2),有了1的辛酸历程后,2的修改应该会很轻松,几乎和1一模一样,虽然我不想在写一遍了。但是既然文章叫手把手教学,那就在啰嗦一遍吧。

4-1、修改vue.config.js

修改vue.config.js文件,设置允许跨域访问,和app_first不同的是端口修改成3002
在这里插入图片描述

module.exports = {devServer: {host: 'localhost', port: 3002, headers: { // 设置本地运行的跨域权限'Access-Control-Allow-Origin': '*',}}
}

4-2、micro配置

和基座一样,在src下创建文件夹micro/index.js。不同的是,子应用不需要config.js了
这边已经将子应用1中的bug修改掉,加上了if
在这里插入图片描述
app_second/src/micro/index.js

// 设置 webpack 的公共路径
if (window.__MICRO_APP_ENVIRONMENT__) {// eslint-disable-next-line__webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__ || '/'
}

4-3、修改main.js

在这里插入图片描述

/**引入 publicPath 设置 */
import './micro'import Vue from 'vue'
import App from './App.vue'
import router from './router'Vue.config.productionTip = false// new Vue({
//  router,
//  render: function (h) { return h(App) }
// }).$mount('#app')let app/**
* 挂载函数
*/
function mount () {app = new Vue({el: '#app',router,render: function (h) { return h(App) }})
}/**
* 卸载函数
*/
function unmount () {app.$destroy()app.$el.innerHTML = ''app = null
}/**微前端环境下,注册mount和unmount方法 */
if (window.__MICRO_APP_ENVIRONMENT__)window[`micro-app-${window.__MICRO_APP_NAME__}`] = { mount, unmount }
elsemount()

4-3、安装路由

在这里插入图片描述

ctrl+c // 中断app_first的运行
cd .. // 返回上级目录
cd app_second // 1.先进入子应用2目录下
npm install vue-router@3 // 2.安装路由
"rules": {"vue/multi-word-component-names": 0}

4-4、修改App.vue文件

在这里插入图片描述

<template><div id="app"><div id="nav"><router-link :to="`${prefix}/home`">子应用2Home</router-link> |<router-link :to="`${prefix}/about`">子应用2About</router-link> |<button @click="goto('SecondHome')">SecondHome</button> |<button @click="goto('SecondAbout')">SecondAbout</button></div><router-view /></div>
</template><script>
export default {name: 'App', data () {return {prefix: window.__MICRO_APP_BASE_ROUTE__ || ''}}, methods: {dataListener (data) {if (data.name !== this.$route.name) /** 不判断时会报一个“冗余导航【NavigationDuplicated】”的异常 */this.$router.push({ name: data.name })}, goto (name) {// 向基项目发送数据window.microApp && window.microApp.dispatch({ route: { name } })}},created () {/** 绑定数据【data属性】监听事件 */window.microApp && window.microApp.addDataListener(this.dataListener)}, destroyed () {/** 移除数据【data属性】监听事件 */window.microApp && window.microApp.removeDataListener(this.dataListener)}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}#nav {padding: 30px;
}#nav a {font-weight: bold;color: #2c3e50;
}#nav a.router-link-exact-active {color: #42b983;
}
</style>

4-5、配置路由

创建router文件夹,配置路由
在这里插入图片描述
app_second/src/router/index
注:这边路由中的name需要修改成Second…,与base中设置的子路由名称保持一致,我这边刚开始搭建的时候就漏掉了,后面在学习代码过程中发现了,又重新做了修改

import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)const routes = [{path: window.__MICRO_APP_BASE_ROUTE__ || '/' /**根据项目运行的不同环境,设置路径的前缀 */, name: 'Home', redirect: { name: 'SecondHome' }, component: () => import('../views/Empty.vue'), children: [{path: 'home', name: 'SecondHome', component: () => import('../views/Home.vue')}, {path: 'about', name: 'SecondAbout', component: () => import('../views/About.vue')}]}
]const router = new VueRouter({mode: 'history',routes
})export default router

4-6、创建视图(views)

在这里插入图片描述
app_second/src/views/About.vue

<template><div class="about"><h1>Second Child About Page</h1></div></template>  

app_second/src/views/Empty.vue

<template><router-view />
</template>

app_second/src/views/Home.vue

<template><div class="home"><imgalt="Vue logo"src="../assets/logo.png"><h1>Second Child Home Page</h1></div>
</template><script>
export default {name: 'Home'
}
</script>

到此app_second也算改造完了,接下来运行一下

npm run serve

嘿嘿嘿,果然有了1的慢吞吞后,2就快多了,也没让我失望,一下子就成功了,结果如下:
在这里插入图片描述

5、运行基座目录

通过前面的操作后,子应用1和子应用2都已经运行出来了,在运行基座目录之前,先解决一下子应用中遇到的那个bug
在这里插入图片描述

"rules": {"vue/multi-word-component-names": 0}

改造完成后,就可以运行基座了,当然我发现如果要运行基座,且想在基座中看到子应用,那么两个子应用也要一起运行,所以我在vsCode中开三个终端,将三个都运行了
在这里插入图片描述
分别看一下每一个的运行吧:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
好了,运行完后,接下来看一下浏览器的显示效果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

总结

我这篇文章写的很啰嗦,如果照着一步步操作应该是不会遇到什么大问题的,因为我这边也是一步步探索出来的结果。纯小白探索,所以如果想搭建micro-app的话,我这篇文章应该很适合小白操作。
当然我也有参考文章,就是参考文章写的没有我这边这么细致,对于新手来说,还是不太友好的。
下一篇micro-app在本文基座上的一些学习笔记

相关文章:

手把手教你使用vue2搭建微前端micro-app

​ 简述 本文主要讲述新手小白怎么搭建micro-app&#xff0c;几乎是每一步都有截图说明。上手应该很简单。 研究背景 这段时间在网上找了很多有关微前端相关的知识&#xff0c;起初本来是想着先搭建一个single-spa&#xff0c;但是奈何网上能找到的内容都是千篇一律。我也是…...

DDR3(MIG核配置官方demoFPGA代码实现及仿真)

由于直接对 DDR3 进行控制很复杂&#xff0c;因此一般使用 MIG IP 来实现&#xff0c;同时为了更简单地使用 MIG IP&#xff0c;我们采用 AXI4 总线协议进行控制。下面首先介绍 MIG IP 的配置&#xff0c;然后看看官方 demo &#xff08;里面包含一个仿真要用到的 DDR3 模型&am…...

传奇人物《周兴和》书连载之67 不辱神圣的使命

不辱神圣的使命 这里&#xff0c;先前还是一个十分神秘的地方。 外人和车辆要想进入这片区域&#xff0c;那是绝对不允许的。这片区域隐于群山之中&#xff0c;且戒备森严&#xff0c;外人若想进入&#xff0c;那是要经过好几道政治审查和随身检查的。近年来&#xff0c;随着…...

Spring框架中的单例Beans是线程安全的么?

在Spring框架中&#xff0c;单例Beans默认是线程安全的。 当你在Spring框架中声明一个单例Bean并配置为默认的单例作用域时&#xff0c;Spring会确保对该Bean的并发访问是线程安全的。以下是一个简单的代码演示&#xff1a; 假设我们有一个名为 SingletonBean 的单例 Bean 类…...

AI脚本插件开发-链接图自动建立档名-插件制作源码-illustrator插件开发

文章目录 1.illustrator1.1.app.activeDocument1.2.selection2.模块分析3.源码工程4.功能描述5.作者答疑本文主要分析一款插件的源码,链接图自动建立档名,代码一般较长,读者耐心阅读,对于学习插件开发具有不小的帮助。先介绍了一下基础资料,如有不懂的地方,就去这些资料里…...

rust智能指针

智能指针 智能指针虽然也号称指针&#xff0c;但是它是一个复杂的家伙&#xff1a;通过比引用更复杂的数据结构&#xff0c;包含比引用更多的信息&#xff0c;例如元数据&#xff0c;当前长度&#xff0c;最大可用长度等。引用和智能指针的另一个不同在于前者仅仅是借用了数据…...

Git、Gitee、Github、Gitlab区别与联系

Git&#xff1a;本地软件&#xff0c;无需联网即可使用&#xff0c;实现本地代码的管理。 分布式版本控制系统&#xff0c;是一种工具&#xff0c;用于代码的存储和版本控制。 将本地文件通过一定的操作将其同步上传到Github或Gitee Gitee&#xff1a;是一家中…...

接口优化的策略

1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场景的接口中&#xff0c;可以在批处理执行完成后一次性插入或更新数据库&#xff0c;避免多次IO。 //批量入库 batchInsert();List的安全操作有以下几种方式&#xff1a; 使…...

android 隐藏底部虚拟按键

方法一 滑动屏幕 可重新显示出来 protected void hideBottomUIMenu() { //隐藏虚拟按键&#xff0c;并且全屏 if (Build.VERSION.SDK_INT <11 && Build.VERSION.SDK_INT < 19) { // lower api View v this.getWindow().getDecorView(); v.setSyst…...

基于电流控制的并网逆变器(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

learn_C_deep_9 (汇编角度理解return的含义、const 的各种应用场景)

return 关键字 不知道我们大家是否有一个疑惑&#xff1a;我们下载一个大型游戏软件&#xff08;王者荣耀&#xff09;&#xff0c;都要花几个小时去下载&#xff0c;但是一旦我们游戏连输&#xff0c;想要删除这个软件的时候&#xff0c;它仅仅只需要十几秒&#xff0c;这是为…...

基于深度学习的OCR技术

随着数字化时代的到来&#xff0c;图片识别技术越来越受到人们的关注。其中&#xff0c;OCR技术作为图片处理的一个重要分支&#xff0c;可以将扫描的图片进行自动识别和分类&#xff0c;极大地提高了工作效率。本文将介绍有道实况OCR技术的相关内容&#xff0c;帮助读者更好地…...

『python爬虫』09. bs4实战之下载精美壁纸(保姆级图文)

目录 爬取思路代码思路1.拿到主页面的源代码. 然后提取到子页面的链接地址, href2.通过href拿到子页面的内容. 从子页面中找到图片的下载地址 img -> src3.下载图片 3. 完整实现代码总结 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 欢迎关注 『python爬虫』 专栏&…...

【Linux学习】多线程——线程控制 | 线程TCB

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 线程控制 | 线程TCB &#x1f9f0;线程控制&#x1f3b4;线程创建&#x1f3b4;线程结束&#x1…...

Node 10 接口

接口 简介 接口是什么 接口是 前后端通信的桥梁 简单理解&#xff1a;一个接口就是 服务中的一个路由规则 &#xff0c;根据请求响应结果 接口的英文单词是 API (Application Program Interface)&#xff0c;所以有时也称之为 API 接口 这里的接口指的是『数据接口』&#…...

大型互联网企业大流量高并发电商领域核心项目已上线(完整流程+项目白皮书)

说在前面的话 面对近年来网络的飞速发展&#xff0c;大家已经都习惯了网络购物&#xff0c;从而出现了一些衍生品例如&#xff1a;某宝/某东/拼夕夕等大型网站以及购物APP~ 并且从而导致很多大型互联网企业以及中小厂都需要有完整的项目经验&#xff0c;以及优秀处理超大流量…...

汇编语言学习笔记六

flag 寄存器 CF:进位标志位&#xff0c;产生进位CF1&#xff0c;否则为0 PF:奇偶位&#xff0c;如010101b&#xff0c;则该数的1有3个&#xff0c;则PF0,如果该数的1的个数为偶数&#xff0c;则PF1。0也是偶数 ZF:在相关指令执行后&#xff08;运算和逻辑指令&#xff0c;传送指…...

多商户商城系统-v2.2.3版本发布

likeshop多商户商城系统-v2.2.3版本发布了&#xff01;主要更新内容如下 新增 1.用户端退出账号功能 优化 1.平台添加营业执照保存异常问题 2.平台端分销商品优化-只显示参与分销的商品 3.优化订单详情显示营销价格标签 4.平台交易设置增加默认值 5.种草社区评论调整&a…...

科研人必看入门攻略(收藏版)

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 本文主要以如何做科研&#xff0c;日常内功修炼&#xff0c;常见科研误区&#xff0c;整理日常‘好论文’四个部分做以介绍&#xff0c;方便刚入门的科研者进行很好的规划。 1.如何做科研 1.1 选方向 当我…...

第5章 循环和关系表达式

1. strcmp()//比较字符串数组是否相等| string 可以直接用“”来判断 char word[5] "aaaa"; strcmp(word,"aaab");//相同输出0&#xff0c;不同输出1; 2. 延时函数 #include<ctime>float sec 2.3;long delay sec*CLOCKS_PER_SEC;long start c…...

Scalable Vector Graphics (SVG)中的svg、clipPath、mask元素

Scalable Vector Graphics (SVG)是一种用于描述二维向量图形的XML基础标记语言。使用SVG可以实现丰富的图形效果&#xff0c;而不需要像使用位图那样考虑分辨率和像素密度的问题&#xff0c;可以在不同设备上展示出相同的高质量图像。 在SVG中&#xff0c;除了基本形状如circl…...

Java基础(十五)集合框架

1. 集合框架概述 1.1 生活中的容器 1.2 数组的特点与弊端 一方面&#xff0c;面向对象语言对事物的体现都是以对象的形式&#xff0c;为了方便对多个对象的操作&#xff0c;就要对对象进行存储。另一方面&#xff0c;使用数组存储对象方面具有一些弊端&#xff0c;而Java 集合…...

安装gitea

1、安装包&#xff08;gitea-1.13.1-linux-amd64&#xff09;上传到服务器&#xff0c;并添加执行权限 链接&#xff1a;https://pan.baidu.com/s/1SAxko0RhVmmD21Ev_m5JFg 提取码&#xff1a;ft07 chmod x gitea-1.13.1-linux-amd64 2、执行 ./gitea-1.13.1-linux-amd64 web…...

Java异常处理传递规范总结

java 异常分类 Thorwable类&#xff08;表示可抛出&#xff09;是所有异常和错误的超类&#xff0c;两个直接子类为Error和Exception&#xff0c;分别表示错误和异常。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常&#xff0c; 这两种异常有很大的区别…...

2d俯视视角游戏,可以切换多种枪械

文章目录 一、 介绍二、 人物移动、鼠标控制转向三、子弹脚本四、子弹随机抛壳五、 爆炸特效六、 发射子弹七、 子弹、弹壳对象池八、 散弹枪九、 火箭弹、发射火箭十、 下载工程文件 一、 介绍 2d俯视视角游戏。 人物视角跟随鼠标移动 多种枪械 抛壳效果 多种设计效果 对象池…...

大四的告诫

保研/考研方向就绩点&#xff0c;&#xff08;各种&#xff09;比赛&#xff0c;&#xff08;考研&#xff09;刷题为主 工作就算法&#xff08;比赛&#xff09;&#xff0c;项目&#xff0c;实习为主 &#x1f442; LOCK OUT - $atori Zoom/KALONO - 单曲 - 网易云音乐 &…...

滚珠螺杆在设备上的应用

滚珠螺杆跟直线导轨一样&#xff0c;是很多机械设备上不可或缺的重要部件&#xff0c;它是确保机器能够具备高加工精度的前提条件&#xff0c;因此本身对于精度的要求也相当地高。今天&#xff0c;我们就来了解一下滚珠螺杆在不同设备上的应用吧&#xff01; 1、大型的加工中心…...

Day41线程同步

线程同步 案例&#xff1a;三个窗口卖100张票 //定义一个类SellTicket实现Runnable接口&#xff0c;定义成员变量100张票 public class SellTicket implements Runnable{private int tickets 100;//重写run方法Overridepublic void run(){while (true){ //没有票后&…...

设计模式之享元模式

参考资料 曾探《JavaScript设计模式与开发实践》&#xff1b;「设计模式 JavaScript 描述」享元模式设计模式之享元模式Javascript 设计模式 - 享元模式 定义 享元模式的英文叫&#xff1a;Flyweight Design Pattern。享元设计模式是用于性能优化的模式&#xff0c;这种设计…...

【GAMES101】05 Rasterization(Triangles)

光栅化过程&#xff1a;将一系列变换后的三角形转换为像素的过程。 三角形在图形学中得到很多的应用。 最基础的多边形&#xff08;边数最少&#xff09;。任何多边形都可以拆成三角形。性质&#xff1a;三角形内部一定是平面的。三角形内外部定义非常清楚。定义三个顶点后&a…...

零售户电商网站订货网址/美业推广平台

它发生在我们所有人身上 —— 生活变得忙碌&#xff0c;我们与朋友失去联系。偶尔的电话和短信只够勉强了解他们的生活和家庭。 我们求助于通过社交媒体来跟随他们&#xff0c;在这里我们看到他们渡过美好假期、搬到新房子或换了工作。即使您无法参加聚会&#xff0c;你也能看到…...

网站开发php工程师/线上营销策略有哪些

CREATE procedure News_Class --资讯新闻百万级分页 ( StrWhere varchar(100),--条件 PageSize int, --页面大小 PageIndex int --页面索引 ) AS declare strSQL varchar(2000) -- 主语句 declare strCountSQL varchar(2000) -- 总记录主语句 declare strTmp varchar(1000) -- …...

南昌做企业网站/六种常见的网站类型

用 Python 快速实现 HTTP 服务器 有时你需临时搭建一个简单的 Web Server&#xff0c;但你又不想去安装 Apache、Nginx 等这类功能较复杂的 HTTP 服务程序时。这时可以使用 Python 内建的 SimpleHTTPServer 模块快速搭建一个简单的 HTTP 服务器。 SimpleHTTPServer 模块可以把你…...

php网站做代理服务器/网络优化培训骗局

本来是不太想动的...无可奈何&#xff0c;看到一句话【业精于勤, 荒于嬉】便还是动手写一写加深理解的同时给以后的自己留个备份吧...element-ui Tree组件如何给具有懒加载的tree设置半选效果&#xff1f;这也是让我很头疼的一个问题...因为数据不是一口气都请求回来的&#xf…...

两个wordpress用户/2023免费b站推广大全

文章目录0 效果1 题目2 思路3 代码0 效果 1 题目 2 思路 排序后&#xff0c;以此判断两个相邻元素是否相等。 3 代码 int cmp(const void* p1, const void* p2){return *(int*)p1 - *(int*)p2; }bool containsDuplicate(int* nums, int numsSize){qsort(nums, numsSize, s…...

公司做网站怎么样/网站seo批量查询工具

智慧 毅力 无所不能 正确性、健壮性、可靠性、效率、易用性、可读性、可复用性、兼容性、可移植性... Lua和C交互详细总结 转自&#xff1a;http://cn.cocos2d-x.org/tutorial/show?id1474 一、Lua堆栈 要理解Lua和C交互&#xff0c;首先要理解Lua堆栈。 简单来说&#xff0…...