皮皮网
皮皮网

【售铺网源码】【函数源码的详解】【什么叫发源码】大纲网页源码_网站大纲怎么写

来源:微信号发布源码 发表时间:2024-11-27 20:37:38

1.umi3源码解析之核心Service类初始化
2.web前端框架有哪些?大纲大纲
3.效率提升利器:一个在线的.NET源码查询网站
4.Selenium基础 — 浏览器弹窗操作

大纲网页源码_网站大纲怎么写

umi3源码解析之核心Service类初始化

       前言

       umi是一个插件化的企业级前端应用框架,在开发中后台项目中应用颇广,网页网站确实带来了许多便利。源码借着这个契机,大纲大纲便有了我们接下来的网页网站“umi3源码解析”系列的分享,初衷很简单就是源码售铺网源码从源码层面上帮助大家深入认知umi这个框架,能够更得心应手的大纲大纲使用它,学习源码中的网页网站设计思想提升自身。该系列的源码大纲如下:

       开辟鸿蒙,今天要解析的大纲大纲就是第一part,内容包括以下两个部分:

       邂逅umi命令,网页网站看看umidev时都做了什么?

       初遇插件化,源码了解源码中核心的大纲大纲Service类初始化的过程。

       本次使用源码版本为?网页网站3.5.,地址放在这里了,源码接下来的每一块代码笔者都贴心的为大家注释了在源码中的位置,先clone再食用更香哟!

邂逅umi命令

       该部分在源码中的路径为:packages/umi

       首先是第一部分umi命令,umi脚手架为我们提供了umi这个命令,当我们创建完一个umi项目并安装完相关依赖之后,通过yarnstart启动该项目时,执行的命令就是umidev

       那么在umi命令运行期间都发生了什么呢,先让我们来看一下完整的流程,如下图:

       接下来我们对其几个重点的步骤进行解析,首先就是对于我们在命令行输入的umi命令进行处理。

处理命令行参数//packages/umi/src/cli.tsconstargs=yParser(process.argv.slice(2),{ alias:{ version:['v'],help:['h'],},boolean:['version'],});if(args.version&&!args._[0]){ args._[0]='version';constlocal=existsSync(join(__dirname,'../.local'))?chalk.cyan('@local'):'';console.log(`umi@${ require('../package.json').version}${ local}`);}elseif(!args._[0]){ args._[0]='help';}

       解析命令行参数所使用的yParser方法是基于yargs-parser封装,该方法的两个入参分别是进程的可执行文件的绝对路径和正在执行的JS文件的路径。解析结果如下:

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}

       在解析命令行参数后,对version和help参数进行了特殊处理:

       如果args中有version字段,并且args._中没有值,将执行version命令,并从package.json中获得version的值并打印

       如果没有version字段,args._中也没有值,将执行help命令

       总的来说就是,如果只输入umi实际会执行umihelp展示umi命令的使用指南,如果输入umi--version会输出依赖的版本,如果执行umidev那就是接下来的步骤了。

       提问:您知道输入umi--versiondev会发什么吗?

       运行umidev

//packages/umi/src/cli.tsconstchild=fork({ scriptPath:require.resolve('./forkedDev'),});process.on('SIGINT',()=>{ child.kill('SIGINT');process.exit(0);});//packages/umi/src/utils/fork.tsif(CURRENT_PORT){ process.env.PORT=CURRENT_PORT;}constchild=fork(scriptPath,process.argv.slice(2),{ execArgv});child.on('message',(data:any)=>{ consttype=(data&&data.type)||null;if(type==='RESTART'){ child.kill();start({ scriptPath});}elseif(type==='UPDATE_PORT'){ //setcurrentusedportCURRENT_PORT=data.portasnumber;}process.send?.(data);});

       本地开发时,大部分脚手架都会采用开启一个新的线程来启动项目,umi脚手架也是如此。这里的函数源码的详解fork方法是基于node中child_process.fork()方法的封装,主要做了以下三件事:

       确定端口号,使用命令行指定的端口号或默认的,如果该端口号已被占用则prot+=1

       开启子进程,该子进程独立于父进程,两者之间建立IPC通信通道进行消息传递

       处理通信,主要监听了RESTART重启和UPDATE_PORT更新端口号事件

       接下来看一下在子进程中运行的forkedDev.ts都做了什么。

//packages/umi/src/forkedDev.ts(async()=>{ try{ //1、设置NODE_ENV为developmentprocess.env.NODE_ENV='development';//2、InitwebpackversiondeterminationandrequirehookinitWebpack();//3、实例化Service类,执行run方法constservice=newService({ cwd:getCwd(),//umi项目的根路径pkg:getPkg(process.cwd()),//项目的package.json文件的路径});awaitservice.run({ name:'dev',args,});//4、父子进程通信letclosed=false;process.once('SIGINT',()=>onSignal('SIGINT'));process.once('SIGQUIT',()=>onSignal('SIGQUIT'));process.once('SIGTERM',()=>onSignal('SIGTERM'));functiononSignal(signal:string){ if(closed)return;closed=true;//退出时触发插件中的onExit事件service.applyPlugins({ key:'onExit',type:service.ApplyPluginsType.event,args:{ signal,},});process.exit(0);}}catch(e:any){ process.exit(1);}})();

       设置process.env.NODE_ENV的值

       initWebpack(接下来解析)

       实例化Service并run(第二part的内容)

       处理父子进程通信,当父进程监听到SIGINT、SIGTERM等终止进程的信号,也通知到子进程进行终止;子进程退出时触发插件中的onExit事件

       initWebpack

//packages/umi/src/initWebpack.tsconsthaveWebpack5=(configContent.includes('webpack5:')&&!configContent.includes('//webpack5:')&&!configContent.includes('//webpack5:'))||(configContent.includes('mfsu:')&&!configContent.includes('//mfsu:')&&!configContent.includes('//mfsu:'));if(haveWebpack5||process.env.USE_WEBPACK_5){ process.env.USE_WEBPACK_5='1';init(true);}else{ init();}initRequreHook();

       这一步功能是检查用户配置确定初始化webpack的版本。读取默认配置文件.umirc和config/config中的配置,如果其中有webpack5或?mfsu等相关配置,umi就会使用webpack5进行初始化,否则就使用webpack4进行初始化。这里的mfsu是webpack5的模块联邦相关配置,umi在3.5版本时已经进行了支持。

初遇插件化

       该部分在源码中的路径为:packages/core/src/Service

       说起umi框架,最先让人想到的就是插件化,这也是框架的核心,该部分实现的核心源码就是Service类,接下来我们就来看看Service类的实例化和init()的过程中发生了什么,可以称之为插件化实现的开端,该部分的大致流程如下

       该流程图中前四步,都是在Service类实例化的过程中完成的,接下来让我们走进Service类。

Service类的实例化//packages/core/src/Service/Service.tsexportdefaultclassServiceextendsEventEmitter{ constructor(opts:IServiceOpts){ super();this.cwd=opts.cwd||process.cwd();//当前工作目录//repoDirshouldbetherootdirofrepothis.pkg=opts.pkg||this.resolvePackage();//package.jsonthis.env=opts.env||process.env.NODE_ENV;//环境变量//在解析config之前注册babelthis.babelRegister=newBabelRegister();//通过dotenv将环境变量中的变量从.env或.env.local文件加载到process.env中this.loadEnv();//1、getuserconfigconstconfigFiles=opts.configFiles;this.configInstance=newConfig({ cwd:this.cwd,service:this,localConfig:this.env==='development',configFiles});this.userConfig=this.configInstance.getUserConfig();//2、getpathsthis.paths=getPaths({ cwd:this.cwd,config:this.userConfig!,env:this.env,});//3、getpresetsandpluginsthis.initialPresets=resolvePresets({ ...baseOpts,presets:opts.presets||[],userConfigPresets:this.userConfig.presets||[],});this.initialPlugins=resolvePlugins({ ...baseOpts,plugins:opts.plugins||[],userConfigPlugins:this.userConfig.plugins||[],});}}

       Service类继承自EventEmitter用于实现自定义事件。在Service类实例化的过程中除了初始化成员变量外主要做了以下三件事:

       1、解析配置文件

//packages/core/src/Config/Config.tsconstDEFAULT_CONFIG_FILES=[//默认配置文件'.umirc.ts','.umirc.js','config/config.ts','config/config.js',];//...if(Array.isArray(opts.configFiles)){ //配置的优先读取this.configFiles=lodash.uniq(opts.configFiles.concat(this.configFiles));}//...getUserConfig(){ //1、找到configFiles中的第一个文件constconfigFile=this.getConfigFile();this.configFile=configFile;//潜在问题:.local和.env的配置必须有configFile才有效if(configFile){ letenvConfigFile;if(process.env.UMI_ENV){ //1.根据UMI_ENV添加后缀eg:.umirc.ts-->.umirc.cloud.tsconstenvConfigFileName=this.addAffix(configFile,process.env.UMI_ENV,);//2.去掉后缀eg:.umirc.cloud.ts-->.umirc.cloudconstfileNameWithoutExt=envConfigFileName.replace(extname(envConfigFileName),'',);//3.找到该环境下对应的配置文件eg:.umirc.cloud.[ts|tsx|js|jsx]envConfigFile=getFile({ base:this.cwd,fileNameWithoutExt,type:'javascript',})?.filename;}constfiles=[configFile,//eg:.umirc.tsenvConfigFile,//eg:.umirc.cloud.tsthis.localConfig&&this.addAffix(configFile,'local'),//eg:.umirc.local.ts].filter((f):fisstring=>!!f).map((f)=>join(this.cwd,f))//转为绝对路径.filter((f)=>existsSync(f));//clearrequirecacheandsetbabelregisterconstrequireDeps=files.reduce((memo:string[],file)=>{ memo=memo.concat(parseRequireDeps(file));//递归解析依赖returnmemo;},[]);//删除对象中的键值require.cache[cachePath],下一次require将重新加载模块requireDeps.forEach(cleanRequireCache);this.service.babelRegister.setOnlyMap({ key:'config',value:requireDeps,});//requireconfigandmergereturnthis.mergeConfig(...this.requireConfigs(files));}else{ return{ };}}

       细品源码,可以看出umi读取配置文件的什么叫发源码优先级:自定义配置文件?>.umirc>config/config,后续根据UMI_ENV尝试获取对应的配置文件,development模式下还会使用local配置,不同环境下的配置文件也是有优先级的

       例如:.umirc.local.ts>.umirc.cloud.ts>.umirc.ts

       由于配置文件中可能require其他配置,这里通过parseRequireDeps方法进行递归处理。在解析出所有的配置文件后,会通过cleanRequireCache方法清除requeire缓存,这样可以保证在接下来合并配置时的引入是实时的。

       2、获取相关绝对路径

//packages/core/src/Service/getPaths.tsexportdefaultfunctiongetServicePaths({ cwd,config,env,}:{ cwd:string;config:any;env?:string;}):IServicePaths{ letabsSrcPath=cwd;if(isDirectoryAndExist(join(cwd,'src'))){ absSrcPath=join(cwd,'src');}constabsPagesPath=config.singular?join(absSrcPath,'page'):join(absSrcPath,'pages');consttmpDir=['.umi',env!=='development'&&env].filter(Boolean).join('-');returnnormalizeWithWinPath({ cwd,absNodeModulesPath:join(cwd,'node_modules'),absOutputPath:join(cwd,config.outputPath||'./dist'),absSrcPath,//srcabsPagesPath,//pagesabsTmpPath:join(absSrcPath,tmpDir),});}

       这一步主要获取项目目录结构中node_modules、dist、src、pages等文件夹的绝对路径。如果用户在配置文件中配置了singular为true,那么页面文件夹路径就是src/page,默认是src/pages

       3、收集preset和plugin以对象形式描述

       在umi中“万物皆插件”,preset是对于插件的描述,可以理解为“插件集”,是为了方便对插件的管理。例如:@umijs/preset-react就是一个针对react应用的插件集,其中包括了plugin-access权限管理、plugin-antdantdUI组件等。

//packages/core/src/Service/Service.tsthis.initialPresets=resolvePresets({ ...baseOpts,presets:opts.presets||[],userConfigPresets:this.userConfig.presets||[],});this.initialPlugins=resolvePlugins({ ...baseOpts,plugins:opts.plugins||[],userConfigPlugins:this.userConfig.plugins||[],});

       在收集preset和plugin时,首先调用了resolvePresets方法,其中做了以下处理:

       3.1、调用getPluginsOrPresets方法,进一步收集preset和plugin并合并

//packages/core/src/Service/utils/pluginUtils.tsgetPluginsOrPresets(type:PluginType,opts:IOpts):string[]{ constupperCaseType=type.toUpperCase();return[//opts...((opts[type===PluginType.preset?'presets':'plugins']asany)||[]),//env...(process.env[`UMI_${ upperCaseType}S`]||'').split(',').filter(Boolean),//dependencies...Object.keys(opts.pkg.devDependencies||{ }).concat(Object.keys(opts.pkg.dependencies||{ })).filter(isPluginOrPreset.bind(null,type)),//userconfig...((opts[type===PluginType.preset?'userConfigPresets':'userConfigPlugins']asany)||[]),].map((path)=>{ returnresolve.sync(path,{ basedir:opts.cwd,extensions:['.js','.ts'],});});}

       这里可以看出收集preset和plugin的来源主要有四个:

       实例化Service时的入参

       process.env中指定的UMI_PRESETS或UMI_PLUGINS

       package.json中dependencies和devDependencies配置的,需要命名规则符合?/^(@umijs\/|umi-)preset-/这个正则

       解析配置文件中的,即入参中的userConfigPresets或userConfigPresets

       3.2、调用pathToObj方法:将收集的plugin或preset以对象的形式输出

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}0

       umi官网中提到过:每个插件都会对应一个id和一个key,id是路径的简写,key是进一步简化后用于配置的唯一值。便是在这一步进行的处理

       形式如下:

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}1

       思考:为什么要将插件以对象的形式进行描述?有什么好处?

执行run方法,初始化插件

       在Service类实例化完毕后,会立马调用run方法,run()执行的第一步就是执行init方法,init()方法的功能就是完成插件的初始化,主要操作如下:

       遍历initialPresets并init

       合并initpresets过程中得到的plugin和initialPlugins

       遍历合并后的plugins并init

       这里的initialPresets和initialPlugins就是上一步收集preset和plugin得到的结果,在这一步要对其逐一的汕尾小程序源码init,接下来我们看一下init的过程中做了什么。

       Initplugin

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}2

       这段代码主要做了以下几件事情:

       getPluginAPI方法:newPluginAPI时传入了Service实例,通过pluginAPI实例中的registerMethod方法将register方法添加到Service实例的pluginMethods中,后续返回pluginAPI的代理,以动态获取最新的register方法,以实现边注册边使用。

//输入umidev经yargs-parser解析后为:/

web前端框架有哪些?

       对于想转行的小伙伴,小蜗这里整理了一份系统的学习路线,可按照这份大纲一步一步来学习,先将基础打好,再学习框架部分,希望可以帮到你~

       第一阶段:专业核心基础

       阶段目标:

       1. 熟练掌握HTML5、CSS3、Less、Sass、响应书布局、移动端开发。

       2. 熟练运用HTML+CSS特性完成页面布局。

       4. 熟练应用CSS3技术,动画、弹性盒模型设计。

       5. 熟练完成移动端页面的设计。

       6. 熟练运用所学知识仿制任意Web网站。

       7. 能综合运用所学知识完成网页设计实战。

       知识点:

       1、Web前端开发环境,HTML常用标签,表单元素,Table布局,CSS样式表,DIV+CSS布局。熟练运用HTML和CSS样式属性完成页面的布局和美化,能够仿制任意网站的前端页面实现。

       2、CSS3选择器、伪类、过渡、变换、动画、jdk11源码字体图标、弹性盒模型、响应式布局、移动端。熟练运用CSS3来开发网页、熟练开发移动端,整理网页开发技巧。

       3、预编译css技术:less、sass基础知识、以及插件的运用、BootStrap源码分析。能够熟练使用 less、sass完成项目开发,深入了解BootStrap。

       4、使用HTML、CSS、LESS、SASS等技术完成网页项目实战。通过项目掌握第一阶段html、css的内容、完成PC端页面设计和移动端页面设计。

       第二阶段:Web后台技术

       阶段目标:

       1. 了解JavaScript的发展历史、掌握Node环境搭建及npm使用。

       2. 熟练掌握JavaScript的基本数据类型和变量的概念。

       3. 熟练掌握JavaScript中的运算符使用。

       4. 深入理解分之结构语句和循环语句。

       5. 熟练使用数组来完成各种练习。

       6.熟悉es6的语法、熟练掌握JavaScript面向对象编程。

       7.DOM和BOM实战练习和H5新特性和协议的学习。

       知识点:

       1、软件开发流程、算法、变量、数据类型、分之语句、循环语句、数组和函数。熟练运用JavaScript的知识完成各种练习。

       2、JavaScript面向对象基础、异常处理机制、常见对象api,js的兼容性、ES6新特性。熟练掌握JavaScript面向对象的开发以及掌握es6中的重要内容。

       3、BOM操作和DOM操作。熟练使用BOM的各种对象、熟练操作DOM的对象。

       4、h5相关api、canvas、ajax、数据模拟、touch事件、mockjs。熟练使用所学知识来完成网站项目开发。

       第三阶段:数据库和框架实战

       阶段目标:

       1. 综合运用Web前端技术进行页面布局与美化。

       2. 综合运用Web前端开发框架进行Web系统开发。

       3. 熟练掌握Mysql、Mongodb数据库的发开。

       4. 熟练掌握vue.js、webpack、elementui等前端框技术。

       5. 熟练运用Node.js开发后台应用程序。

       6. 对Restful,Ajax,JSON,开发过程有深入的理解,掌握git的基本技能。

       知识点:

       1、数据库知识,范式,MySQL配置,命令,建库建表,数据的增删改查,mongodb数据库。深入理解数据库管理系统通用知识及MySQL数据库的使用与管理,为Node.js后台开发打下坚实基础。

       2、模块系统,函数,路由,全局对象,文件系统,请求处理,Web模块,Express框架,MySQL数据库处理,RestfulAPI,文件上传等。熟练运用Node.js运行环境和后台开发框架完成Web系统的后台开发。

       3、vue的组件、生命周期、路由、组件、前端工程化、webpack、elementui框架。Vue.js框架的基本使用有清晰的理解,能够运用Vue.js完成基础前端开发、熟练运用Vue.js框架的高级功能完成Web前端开发和组件开发,对MVVM模式有深刻理解。

       4、需求分析,数据库设计,后台开发,使用vue、node完成pc和移动端整站开发。于Node.js+Vue.js+Webpack+Mysql+Mongodb+Git,实现整站项目完整功能并上线发布。

       第四阶段:移动端和微信实战

       阶段目标:

       1.熟练掌握React.js框架,熟练使用React.js完成开发。

       2.掌握移动端开发原理,理解原生开发和混合开发。

       3.熟练使用react-native和Flutter框架完成移动端开发。

       4.掌握微信小程序以及了解支付宝小程序的开发。

       5.完成大型电商项目开发。

       知识点:

       1、React面向组件编程、表单数据、组件通信、监听、声明周期、路由、Redux基本概念。练使用react完成项目开发、掌握Redux中的异步解决方案Saga。

       2、react-native、开发工具、视图与渲染、api操作、Flutter环境搭建、路由、ListView组件、网络请求、打包。练掌握react-native和Flutter框架,并分别使用react-native和Flutter分别能开发移动端项目。

       3、微信小程序基本介绍、开发工具、视图与渲染、api操作、支付宝小程序的入门和api学习。掌握微信小程序开发了解支付宝小程序。

       4、大型购物网站实战,整个项目前后端分离开发;整个项目分为四部分:PC端网页、移动端APP、小程序、后台管理。团队协作开发,使用git进行版本控制。目期间可以扩展Three.js 、TypeScript。

       web前端学习路线思维导图

效率提升利器:一个在线的.NET源码查询网站

       你是否曾面临这样的困境,想要查询.NET中的某个类型、方法、属性或程序集的源代码,但又不想从GitHub下载?今天我要向大家推荐一个在线的.NET源码查询网站,它将帮助你解决这一难题。

       网站名称:source.dot.net

       如果你对.NET感兴趣,还可以访问以下在线学习网站:github.com/YSGStudyHard...

       以下是该网站的一些功能特性:

       查询IsNullOrWhiteSpace源代码

       搜索IsNullOrWhiteSpace源代码

       定位到GitHub中的源代码

       中文文档大纲

       项目资源管理器

       命名空间资源管理器

Selenium基础 — 浏览器弹窗操作

       说明:在webdriver中,处理JavaScript生成的alert、confirm以及prompt弹窗非常简单。具体方法是通过switch_to.alert()方法定位到alert/confirm/prompt弹窗,然后使用text/accept/dismiss/send_keys方法进行操作。常用操作有:

       示例:页面代码片段:

       脚本代码:

       注意:prompt弹窗输入框,Chrome不显示输入文本 Python版本 3.7.7

       由于alert弹窗不够美观,现在大多数网站都会使用自定义弹窗。使用Selenium自带的方法无法处理这种情况,此时就需要使用JS方法进行处理。需求:去掉淘宝首页的自定义弹窗。淘宝首页的自定义弹窗如下:

       提示:网页中弹出的对话框,也属于页面自定义弹窗,都可以用下面方式处理。实现方式:这种弹窗属于自定义弹窗的表现形式,可以通过设置HTML、DOM、Style对象中的一个display属性来处理,可以设置元素如何被显示。具体解释可以参考:/jsref/prop_style_display.asp。将display的值设置成none:此元素不会被显示,就可以去除这个弹窗了。注意:手动页面刷新之后还会出现弹窗。步骤如下:

       提示:document.getElementById()是JS获取元素的方式,在JS获取元素方式中,只有ById()获取的是一个元素。其他获取元素的方式,都获取的是结果集,需要获取具体元素的时候,注意要使用索引。简单举例:

       示例:

       最后我这里给你们分享一下我所积累和真理的文档和学习资料,有需要是领取就可以了。

       这个大纲涵盖了目前市面上企业百分之的技术,这个大纲很详细的写了你该学习什么内容,企业会用到什么内容。总共十个专题足够你学习。

       这里我准备了对应上面的每个知识点的学习资料、可以自学神器,已经项目练手。

       软件测试/自动化测试全家桶装学习中的工具、安装包、插件....

       有了安装包和学习资料,没有项目实战怎么办,我这里都已经准备好了往下看。

       如何领取这些配套资料和学习思路图,以及项目实战源码。这些资料都已经让我准备在一个php网页里面了,可以在里面领取扫码或者进Q群交流都可以暗号和备注是哦。

       最后送上一句话:世界的模样取决于你凝视它的目光,自己的价值取决于你的追求和心态,一切美好的愿望,不在等待中拥有,而是在奋斗中争取。如果我的博客对你有帮助、如果你喜欢我的文章内容,请 “点赞” “评论” “收藏” 一键三连哦。

相关栏目:知识