Vue-Router源码实现详解
1.Hash模式
- hash就是url中#后面的部分
- hash改变时,页面不会从新加载,会触发hashchange事件,去监听hash改变,而且也会被记录到浏览器历史记录中
- vue-router的hash模式,主要是通过hashchange事件,根据hash值找到对应的组件去进行渲染(源码里会先判断浏览器支不支持popstate事件,如果支持,则是通过监听popstate事件,如果不支持,则监听hashchange事件)
hash模式页面跳转不刷新
根据http协议所示,url中hash改变请求是不会发送到服务端的,不管怎么location跳转,或者url上直接加上hash值回车,他都一样,请求是不会发送到服务端。
但是我们的系统里又引入了vue-router,其中hashchange这个事件监听到了hash的变化,从而触发了组件的更新,也就绘制出了相应的页面
2.History模式
- 通过history.pushstate去修改页面的地址
- 当history改变时,会触发popstate事件,所以可以通过监听popstate事件获取路由地址
- 根据当前路由地址找到对应组件渲染
history模式,切换路由时页面刷新
看一下正确的history模式下,首页刷新到显示的整体流程:
1.将这个完整的url发到服务器nginx2.ngix需要配置用这个uri在指给前端index.html(因为根本没有任何一个服务器提供了这个url路由,如果直接访问的话就是404,所以就要指回给前端,让前端自己去根据path来显示)
location / {root /usr/share/nginx/html/store;//项目存放的地址index index.html index.htm;try_files $uri $uri/ /index.html;//history模式下,需要配置它
}所以try_files $uri $uri/的意思就是,比如http://test.com/example先去查找单个文件example,如果example不存在,则去查找同名的文件目录/example/,如果再不存在,将进行重定向index.html(只有最后一个参数可以引起一个内部重定向)凡是404的路由,都会被重定向到index.html,这样就显示正确了3.此时nginx将这个请求指回了前端的index.html,index.html中开始加载js,js中已有vue-router的代码,vue-router自动触发了popstate这个事件,在这个事件回调中,绘制了这个path下对应的页面组件
3.实现vue-router
VueRouter需要做以下这些事情
- 实现VueRouter根据不同模式进行不同处理
- 根据传入的路由配置,生成对应的路由映射
- init函数监听hashchange或
popState
事件,浏览器记录改变时重新渲染router-view
组件 - 实现install静态方法
- 给Vue实例挂载router实例
- 注册全局组件和,
router-view
组件通过当前url找到对应组件进行渲染,并且url改变时,重新渲染组件,router-link则渲染为a标签 - 使用
Object.defineProperty
在Vue的原型上定义$router
和$route
属性
代码实现
首先在创建文件 router/index.js,router/my-router.js
在index中我就不做多讲解了,和平常vue-router一样的配置,只是不需要vue-router,我们自己实现
一下都会有详细的注释,每一项的作用
import Vue from 'vue'
import VueRouter from './my-router'; //实现router文件
import HomeView from '../views/HomeView.vue' //home文件
import about from '../views/AboutView.vue' //about文件Vue.use(VueRouter) //注意! 这是我们自己实现的文件,只是名字叫vuerouterconst routes = [ //这是我们的路由表{path: '/home',name: 'home',component: HomeView},{path: '/about',name: 'about',// route level code-splitting// this generates a separate chunk (about.[hash].js) for this route// which is lazy-loaded when the route is visited.component: about}
]const router = new VueRouter({ //创建实例mode: 'history', //模式 hash historyroutes //路由表给实例传过去
})export default router //最后到处router
接下来就是正式实现router
首先在my-router最顶部,声明一个变量
Vue
并将其初始化为null
//my-router.js
let Vue = null; //保存Vue的构造函数,在插件中要使用,保留在将来为Vue分配一个值,减少全局命名空间的污染
定义一个HistoryRoute的类,并在其构造函数中将
this.current
也初始化为null
用途:
- 状态管理:
this.current
用于存储当前路由的状态或信息,比如当前激活的路由路径、参数等。- 初始化:通过将其初始化为
null
,你可以在类的其他方法中根据需要更新this.current
的值,而不会受到未初始化属性的影响。- 灵活性:将
this.current
初始化为null
提供了灵活性,允许你在类的生命周期中的任何时刻为其分配一个具体的值。
//my-router.js
let Vue = null; //保存Vue的构造函数,在插件中要使用,保留在将来为Vue分配一个值,减少全局命名空间的污染
class HistoryRoute {constructor() {this.current = null;}
}
定义一个HistoryRoute的类
构造函数:
constructor(options)
:接收一个options
对象,该对象包含两个属性:mode
和routes
。mode
指定路由模式(hash
或history
),routes
是一个路由配置数组,每个路由配置对象包含path
和component
属性。this.changeMap
:将routes
数组转换为一个对象(Map),以path
为键,component
为值,方便后续根据路径快速查找对应的组件。Vue.util.defineReactive(this, "history", new HistoryRoute());
和this.history = new HistoryRoute();
:这里设置了history
属性,后者覆盖了前者。HistoryRoute
类用于管理当前路由状态。
class VueRouter {// 可以看到,暂时传入了两个,一个是mode,还有一个是routes数组。因此,我们可以这样实现构造器constructor(options) {this.mode = options.mode || "hash"; //默认是hashthis.routes = options.routes || []; //默认为空// 由于直接处理数组比较不方便,所以我们做一次转换,采用path为key,component为value的方式this.routesMap = this.changeMap(this.routes);// 我们还需要在vue-router的实例中保存当前路径(在包含一些例如params信息,其实就是$route),所以我们为了方便管理,使用一个对象来表示:Vue.util.defineReactive(this, "history", new HistoryRoute());this.history = new HistoryRoute();}changeMap(routes) {// 使用render函数我们可以用js语言来构建DOMreturn routes.reduce((pre, next) => {console.log(pre);pre[next.path] = next.component;console.log(pre);return pre;}, {});}
}
添加init 方法:
- 根据
mode
的不同,为window
添加相应的事件监听器,以监听路由变化(hashchange
或popstate
事件),并更新history.current
属性。- 在页面加载时(
load
事件),也根据当前URL设置history.current
。
class VueRouter {// 可以看到,暂时传入了两个,一个是mode,还有一个是routes数组。因此,我们可以这样实现构造器constructor(options) {this.mode = options.mode || "hash";this.routes = options.routes || [];// 由于直接处理数组比较不方便,所以我们做一次转换,采用path为key,component为value的方式this.routesMap = this.changeMap(this.routes);// 我们还需要在vue-router的实例中保存当前路径(在包含一些例如params信息,其实就是$route),所以我们为了方便管理,使用一个对象来表示:Vue.util.defineReactive(this, "history", new HistoryRoute());this.history = new HistoryRoute();this.init();}init() {// 如果是hash模式if (this.mode === "hash") {location.hash ? void 0 : (location.hash = "/");window.addEventListener("load", () => {this.history.current = location.hash.slice(1);});window.addEventListener("hashchange", () => {console.log(location.hash.slice(1))this.history.current = location.hash.slice(1);});}// 如果是history模式if (this.mode === "history") {location.pathname ? void 0 : (location.pathname = "/");window.addEventListener("load", () => {console.log(location.pathname)this.history.current = location.pathname;});window.addEventListener("popstate", () => {console.log(location.pathname)this.history.current = location.pathname;});}}changeMap(routes) {// 使用render函数我们可以用js语言来构建DOMreturn routes.reduce((pre, next) => {console.log(pre);pre[next.path] = next.component;console.log(pre);return pre;}, {});}
Vue Router作为一个Vue插件,需要创建instll方法
- 设置Vue实例:
Vue = v;
:将传入的Vue实例赋值给全局变量Vue
,以便后续使用。- 全局混入:
- 使用
Vue.mixin
在Vue的生命周期钩子beforeCreate
中注入代码,用于处理路由相关的初始化。- 在根组件中,保存
_router
和_root
属性,分别指向VueRouter实例和根组件自身。- 对于非根组件,通过
$parent
找到根组件,从而访问到_router
和_root
。
VueRouter.install = (v) => {Vue = v;// vue-router还自带了两个组件,分别是router-link和router-view 在Vue.use(VueRouter)的时候加载的 所以我们要写在install里面// 新增代码Vue.mixin({beforeCreate() {// 如果是根组件if (this.$options && this.$options.router) {console.log(this.$options)// 将根组件挂载到_root上this._root = this;this._router = this.$options.router;// 拦截router-linkthis._router.mode === "history" && document.addEventListener("click", (e) => {if (e.target.className === "router-link-to") {// 阻止默认跳转事件e.preventDefault();// 手动改变url路径console.log(e.target.getAttribute("href"))history.pushState(null, "", e.target.getAttribute("href"));// 为current赋值url路径this._router.history.current = location.pathname;}});} else {// 如果是子组件// 将根组件挂载到子组件的_root上this._root = this.$parent && this.$parent._root;console.log(this._root);}},});
};
- 使用
Object.defineProperty
在Vue的原型上定义$router
和$route
属性,以便在任何Vue组件中通过this.$router
和this.$route
访问到VueRouter实例和当前路由信息。- 在install方法里面写就行
// 定义$routerObject.defineProperty(Vue.prototype, "$router", {get() {console.log(this);return this._root._router;},});// 定义$routeObject.defineProperty(Vue.prototype, "$route", {get() {return this._root._router.history.current;},});
定义全局组件(install方法里面添加)
router-link
:一个用于导航的<a>
标签组件,根据路由模式(hash
或history
)自动添加#
或正常路径。点击时,如果是history
模式,会阻止默认跳转行为,改为手动更新URL和路由状态。router-view
:一个用于渲染当前路由对应组件的占位符组件。它根据history.current
和routesMap
找到对应的组件,并使用Vue的render
函数渲染。
Vue.component("router-link", {props: {to: String,},render(h) {const mode = this._root._router.mode;let to = mode === "hash" ? "#" + this.to : this.to;return h("a",{attrs: {href: to,},// 新增代码class: "router-link-to",},this.$slots.default);},});Vue.component("router-view", {render(h) {const current = this._root._router.history.current;const routesMap = this._root._router.routesMap;return h(routesMap[current]);},});
完整代码
/** @Author: hukai huzhengen@gmail.com* @Date: 2023-06-08 17:49:08* @LastEditors: hukai huzhengen@gmail.com* @LastEditTime: 2024-10-24 11:08:00* @FilePath: \vue源码\vue-router-yuanma\src\router\my-router.js* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE*/
let Vue = null;
class HistoryRoute {constructor() {this.current = null;}
}
// 因为router时new出来的 并且穿了一个对象 配置的路由由此可知router是一个class类
class VueRouter {// 可以看到,暂时传入了两个,一个是mode,还有一个是routes数组。因此,我们可以这样实现构造器constructor(options) {this.mode = options.mode || "hash";this.routes = options.routes || [];// 由于直接处理数组比较不方便,所以我们做一次转换,采用path为key,component为value的方式this.routesMap = this.changeMap(this.routes);// 我们还需要在vue-router的实例中保存当前路径(在包含一些例如params信息,其实就是$route),所以我们为了方便管理,使用一个对象来表示:Vue.util.defineReactive(this, "history", new HistoryRoute());this.history = new HistoryRoute();this.init();}init() {// 如果是hash模式if (this.mode === "hash") {location.hash ? void 0 : (location.hash = "/");window.addEventListener("load", () => {this.history.current = location.hash.slice(1);});window.addEventListener("hashchange", () => {console.log(location.hash.slice(1))this.history.current = location.hash.slice(1);});}// 如果是history模式if (this.mode === "history") {location.pathname ? void 0 : (location.pathname = "/");window.addEventListener("load", () => {console.log(location.pathname)this.history.current = location.pathname;});window.addEventListener("popstate", () => {console.log(location.pathname)this.history.current = location.pathname;});}}changeMap(routes) {// 使用render函数我们可以用js语言来构建DOMreturn routes.reduce((pre, next) => {console.log(pre);pre[next.path] = next.component;console.log(pre);return pre;}, {});}
}// 通过Vue.use 知道里面有一个install方法 并且第一个参数是Vue实例
VueRouter.install = (v) => {Vue = v;// vue-router还自带了两个组件,分别是router-link和router-view 在Vue.use(VueRouter)的时候加载的 所以我们要写在install里面// 新增代码Vue.mixin({beforeCreate() {// 如果是根组件if (this.$options && this.$options.router) {console.log(this.$options)// 将根组件挂载到_root上this._root = this;this._router = this.$options.router;// 拦截router-linkthis._router.mode === "history" && document.addEventListener("click", (e) => {if (e.target.className === "router-link-to") {// 阻止默认跳转事件e.preventDefault();// 手动改变url路径console.log(e.target.getAttribute("href"))history.pushState(null, "", e.target.getAttribute("href"));// 为current赋值url路径this._router.history.current = location.pathname;}});} else {// 如果是子组件// 将根组件挂载到子组件的_root上this._root = this.$parent && this.$parent._root;console.log(this._root);}},});// 定义$routerObject.defineProperty(Vue.prototype, "$router", {get() {console.log(this);return this._root._router;},});// 定义$routeObject.defineProperty(Vue.prototype, "$route", {get() {return this._root._router.history.current;},});Vue.component("router-link", {props: {to: String,},render(h) {const mode = this._root._router.mode;let to = mode === "hash" ? "#" + this.to : this.to;return h("a",{attrs: {href: to,},// 新增代码class: "router-link-to",},this.$slots.default);},});Vue.component("router-view", {render(h) {const current = this._root._router.history.current;const routesMap = this._root._router.routesMap;return h(routesMap[current]);},});
};
export default VueRouter;
最后在main.js中注册一下就行
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'Vue.config.productionTip = false
new Vue({router,store,render: h => h(App)
}).$mount('#app')
APP.vue中
<template><div id="app"><nav><router-link to="/home">Home</router-link> |<router-link to="/about">About</router-link></nav><router-view/></div>
</template>
<script>
export default {name:"Router",mounted(){console.log(this.$router)}
}
</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>
总结
这段代码通过定义VueRouter类和install方法,实现了一个简化版的Vue Router。它允许开发者定义路由规则,并在Vue应用中通过和组件实现页面导航和组件渲染。尽管这个实现相对简单,但它展示了Vue Router的核心概念和工作原理。
相关文章:
Vue-Router源码实现详解
1.Hash模式 hash就是url中#后面的部分hash改变时,页面不会从新加载,会触发hashchange事件,去监听hash改变,而且也会被记录到浏览器历史记录中vue-router的hash模式,主要是通过hashchange事件,根据hash值找…...
程序员节日的日期是10月24日程序员日
程序员节日的日期是10月24日。 这一天被称为中国程序员日或1024程序员节,由博客园、CSDN等自发组织设立,旨在纪念程序员对科技世界的贡献。 程序员节日的由来和意义 1024程序员节的由来可以追溯到2010年,最初由网友提出设立一个…...
联邦学习中的数据异构性
在联邦学习(Federated Learning, FL)领域中, 异构数据(Heterogeneous Data) 是指不同客户端所持有的本地数据在特征分布、类别分布、数量等方面存在差异的数据。这种数据的异质性是联邦学习面临的一大挑战,…...
Python小程序 - 替换文件内容
1. 写入文件c:\a.txt 1)共写入10行 2)每行内容 0123456789 # 1 ls 0123456789 ln 10 with open("c:/a.txt", w,encodingUTF-8) as f:for i in range(ln):f.write(ls\n)######################################### 2 ln 10…...
k8s备份恢复(velero)
velero简介 velero官网: https://velero.io/ velero-github: https://github.com/vmware-tanzu/velero velero的特性 备份可以按集群资源的子集,按命名空间、资源类型标签选择器进行过滤,从而为备份和恢复的内容提供高度的灵活…...
LED户外屏:面对复杂环境的七大挑战
户外LED显示屏作为现代城市广告和信息传播的重要媒介,其应用范围越来越广泛。然而,与室内环境相比,户外环境的复杂多变对LED显示屏提出了更高的要求。本文将探讨户外LED显示屏在设计和应用过程中必须考虑的七个关键问题。 1. 高分辨率 户外LE…...
LabVIEW自动化流动返混实验系统
随着工业自动化的不断发展,连续流动反应器在化工、医药等领域中的应用日益广泛。传统的流动返混实验操作复杂,数据记录和处理不便,基于LabVIEW的全自动流动返混实验系统能自动测定多釜反应器、单釜反应器和管式反应器的停留时间分布ÿ…...
【性能优化】安卓性能优化之CPU优化
【性能优化】安卓性能优化之CPU优化 CPU优化及常用工具原理与文章参考常用ADB常用原理、监控手段原理监控手段多线程并发解决耗时UI相关 常见场景排查CPU占用过高常用系统/开源分析工具AndroidStudio ProfilerSystraceBtracePerfettoTraceView和 Profile ANR相关ANR原理及常见场…...
springboot二手图书交易系统-计算机设计毕业源码88413
目 录 摘要 1 绪论 1.1研究背景 1.2研究意义 1.3论文结构与章节安排 2 二手图书交易系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 二手…...
解决ElasticSearch启动成功却无法在浏览器访问问题
目录 前言: 问题复现 : 解决问题: 1、修改sysctl.conf文件 2、在sysctl.conf文件增加这段东西 3、 然后保存退出,输入以下命令使其生效 结语: 前言: 这篇文章是小白我今天突然启动es,发现e…...
稀土有色包芯线良好的导电性
稀土有色包芯线是一种结合了稀土元素和有色金属(如铜、铝、镁等)的特殊线材。以下是对稀土有色包芯线的详细介绍: 一、组成与结构 芯线:由稀土元素和有色金属组成的合金制成。稀土元素(如镧、铈、镁等)的添加量在一定范围内,以确保合金性能的…...
SIP 业务举例之 Call Forwarding Unconditional(无条件呼转)
目录 1. Call Forwarding Unconditional 简介 2. RFC5359 的 Call Forwarding Unconditional 信令流程 PS:Dialog 建立条件 Dialog 会话完全建立 3. Call Forwarding Unconditional 过程总结 博主wx:yuanlai45_csdn 博主qq:2777137742 想要 深入学习 5GC IMS 等通信知识…...
基于stm32的esp8266的WIFI控制风扇实验
实验案例WIFI控制风扇 项目需求 电脑通过esp8266模块远程遥控风扇。 项目框图 风扇模块封装 #include "sys.h" #include "fan.h"void fan_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟…...
java中的ScheduledExecutorService介绍和使用案例
ScheduledExecutorService 是 Java 并发包 java.util.concurrent 中的一个接口,它提供了一种机制,允许我们安排一个任务在给定的延迟后运行,或者定期地执行。 主要特点 单次调度:可以安排任务在一定的延迟后执行一次。周期性调度…...
4天涨粉14万!这个AI小众赛道粉丝涨疯了吧?保姆级教程免费教会你!
测一下你的搞钱灵敏度有多高,看下面两张截图,有没有发现什么异常值? 发现了吧? 第一张是10月17号截的,第二张是21号,4天时间粉丝从2.8万飙到16.6万,涨粉14万! 这个号我几天之前就发…...
RK3588 技术分享 | 在Android系统中使用NPU实现Yolov5分类检测
随着人工智能和大数据时代的到来,传统嵌入式处理器中的CPU和GPU逐渐无法满足日益增长的深度学习需求。为了应对这一挑战,在一些高端处理器中,NPU(神经网络处理单元)也被集成到了处理器里。NPU的出现不仅减轻了CPU和GPU…...
itext 转换word文档转pdf
itext 转换word文档转pdf <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version><scope>compile</scope></dependency> <dependency><groupId>org.a…...
WSL-默认root登录
WSL-默认root登录 使用管理员,打开powershell PS C:\WINDOWS\system32> wsl -l 适用于 Linux 的 Windows 子系统分发版: Ubuntu-22.04 (默认) PS C:\WINDOWS\system32> ubuntu2204.exe config --default-user root PS C:\WINDOWS\system32>修改之后&…...
ASIO网络调试助手之四:浅谈QTcpServer性能
网络上有些质疑Qt Network模块性能的声音,本文将从理论和压测两个方面对比ASIO tcp server和QTcpServer在Windows上的性能,最后给出结论。 一.理论 QTcpServer在Windows上的实现是基于select模型,源码位置:5.12.6\Src\qtbase\src\network\socket\qnativesocketengine_win…...
快手 日常实习一面面经
官网投递,三天约面 线上面试 (60mins): 1. 自我介绍 2. 问实习 介绍自己做的业务上一段实习的公司框架和开源的 RPC 框架的区别负责的业务与核心业务的依赖关系场景题 -> 设计高并发下的负载均衡 3. 项目拷打 手写 双检锁…...
Cursor零基础小白教程系列 - 创建你的第一个Cursor 项目
最适合小白零基础的Cursor教程 网站lookai.top相同作者,最新文章会在网站更新,欢迎收藏书签 创建你的第一个Cursor 项目 实操视频 概述 开始使用Cursor进行编程的第一步是创建或导入一个项目。本指南将帮助您了解如何在Cursor中创建新项目、导入现有项…...
通用序列化和反序列化实现思路
本文简单的记录一下采用模板来实现序列化与反序列的思路, 同时采用C20标准的concept和requires来简化模板函数的选择。 首先了解一下自定义类支持序列化的两种方式: 一、序列化自定义类型(侵入式) struct Test {std::string na…...
书生营第四期L0G2000 Python 基础知识
闯关任务 Leetcode 383(笔记中提交代码与leetcode提交通过截图) class Solution:def canConstruct(self, ransomNote: str, magazine: str) -> bool:note [0]*26maga [0]*26for s in ransomNote:note[ord(s)-ord(a)] 1for s in magazine:maga[ord(s)-ord(a)] 1for i in…...
Day12-数据库服务冗余架构
Day-12-数据库服务高可用集群 1、数据库MGR组复制实践2、数据库高可用MHA应用介绍3、数据库高可用MHA环境准备4、数据库高可用MHA原理机制5、数据库高可用MHA功能配置 1、数据库MGR组复制实践 (强一致性主从同步) 2、数据库高可用MHA应用介绍 3、数据库高可用MHA环境…...
js监听div尺寸,ResizeObserver
示例: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><style>.observedDiv {width: 40vw;height: 50vh;background-color: lightblue;}</style></head><body><div id"…...
STM32与openmv的串口通信
OpenMV与STM32的通信是嵌入式系统和物联网领域中的一项重要技术。OpenMV是一种开源的微型机器视觉模块,基于ARM Cortex-M7微控制器,支持多种图像处理功能,如颜色识别、形状检测等。而STM32是STMicroelectronics公司推出的基于ARM Cortex内核的…...
C#基于SkiaSharp实现印章管理(11)
PdfSharpCore支持类似GDI方式在PDF页面绘制文字、矩形、圆形、多边形、路径、图片等内容,本文学习基于PdfSharpCore将结构化印章数据导出为PDF文件的基本用法,评估其使用可行性。 PdfSharpCore创建PDF文件很方便,调用PdfDocument类创建实…...
Spring使用@Async出现循环依赖原因以及解决方案
场景复现 1、首先项目需要打开spring的异步开关,在application主类上加EnableAsync 2、创建一个包含了Async方法的异步类MessageService: Service public class MessageService {Resource private TaskService taskService; Async public void…...
如何训练 RAG 模型
训练 RAG(Retrieval-Augmented Generation)模型涉及多个步骤,包括准备数据、构建知识库、配置检索器和生成模型,以及进行训练。以下是一个详细的步骤指南,帮助你训练 RAG 模型。 1. 安装必要的库 确保你已经安装了必…...
鸿蒙网络编程系列34-Wifi热点扫描及连接示例
1. Wifi热点简介 Wifi热点是移动设备接入网络的重要形式,特别是在不具备固定网络接入点的情况下,可以通过Wifi热点灵活方便的接入网络,因此在日常生活中具有广泛的应用。鸿蒙系统也提供了方便的Wifi管理API,支持热点扫描…...
给女友做的网站 源码/网站关键词优化公司
1332. 删除回文子序列 难度简单126收藏分享切换为英文接收动态反馈 给你一个字符串 s,它仅由字母 a 和 b 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。 返回删除给定字符串中所有字符(字符串为空)的最小删除次数。 「子序列」…...
虎丘网站建设/英文网站设计公司
一、Linux环境下的线程相对于其他操作系统,Linux系统内核只提供了轻量级进程的支持,并未实现线程模型。Linux是一种“多进程单线程”的操作系统,Linux本身只有进程的概念,而其所谓的“线程”本质上在内核里仍然是进程。进程是资源…...
做艺术字的网站/seo公司官网
首先,程序中引用两个工具类 import java.util.Scanner; import java.util.Random; 之后产生一个[1-100)内的数字,有两种方法 int num (int)(Math.random()*90 10); 或者是使用Random()工具类的方法 1.随机产生一个100以内的整数 Random rand new…...
美工网站/百家号关键词排名优化
「博客专家」申请及审核执行标准 博客等级,博客积分规则...
网站建设课程设计/搜索引擎优化网站
转载:http://blog.csdn.net/jia20003/article/details/7666795 基于OSGi的Virgo Server最简单spring web实例 一:开发工具下载与环境搭建 1. 下载并安装JDK6u30版本,下载地址如下: http://www.oracle.com/technetwork/ja…...
织梦的网站数据还原怎么做/北京云无限优化
一、报错“The package esbuild-linux-64’could not be found,and is need by esbuild” 1、报错 Linux下运行npm run dev 报错“The package esbuild-linux-64’could not be found,and is need by esbuild” 2、分析 vite构建项目时,esbuild定死了包版本esbuild…...