Node.js |(六)express框架 | 尚硅谷2023版Node.js零基础视频教程

学习视频:尚硅谷2023版Node.js零基础视频教程,nodejs新手到高手

在这里插入图片描述

文章目录

  • 📚express使用
    • 🐇初体验
    • 🐇express路由
      • ⭐️路由的使用
      • ⭐️获取请求参数
      • ⭐️获取路由参数
      • 🔥练习:根据路由参数响应歌手信息
    • 🐇express响应设置
    • 🐇express中间件
      • ⭐️定义全局中间件
      • ⭐️定义路由中间件
      • ⭐️静态资源中间件
      • 🔥静态资源中间件练习:局域网内访问网页❓
    • 🐇 获取请求体数据 body-parser
    • 🐇express防盗链
      • 🔥防盗链实践
  • 📚路由模块化Router
    • 🐇介绍
    • 🐇使用
  • 📚EJS模板引擎
    • 🐇介绍
    • 🐇列表渲染
    • 🐇条件渲染
    • 🐇express中使用ejs
  • 📚应用程序生成器express-generator

📚express使用

🐇初体验

  • express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址
  • 简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)
  • express 本身是一个 npm 包,所以可以通过 npm 安装

    npm init
    npm i express
    
  • 初体验

    //1. 导入 express
    const express = require('express');
    //2. 创建应用对象
    const app = express();
    //3. 创建路由规则
    app.get('/home', (req, res) => {res.end('hello express server');
    });
    //4. 监听端口 启动服务
    app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
    });
    

    在这里插入图片描述

🐇express路由

官方定义: 路由确定了应用程序如何响应客户端对特定端点的请求。

⭐️路由的使用

  • 一个路由的组成由请求方法路径回调函数组成。

  • express中提供了一系列方法,使用路由,使用格式如下:app.<method>(path,callback)

  • res.end和res.send的区别

    //导入 express
    const express = require('express');
    //创建应用对象
    const app = express();
    //创建 get 路由
    app.get('/home', (req, res) => {res.send('网站首页');
    });
    //首页路由
    app.get('/', (req,res) => {res.send('我才是真正的首页');
    });
    //创建 post 路由
    app.post('/login', (req, res) => {res.send('登录成功');
    });
    //匹配所有的请求方法
    app.all('/search', (req, res) => {res.send('1 秒钟为您找到相关结果约 100,000,000 个');
    });
    //自定义 404 路由
    app.all("*", (req, res) => {res.send('<h1>404 Not Found</h1>')
    });
    //监听端口 启动服务
    app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000');
    });
    

  • 以下是上述代码运行后直接输网址得到的返回。
    在这里插入图片描述

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

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

  • 针对login部分,上边那得不到想要的是因为指定了post
    在这里插入图片描述在这里插入图片描述

⭐️获取请求参数

  • express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式。
    //导入 express
    const express = require('express');
    //创建应用对象
    const app = express();
    //获取请求的路由规则
    app.get('/request', (req, res) => {//1. 获取报文的方式与原生 HTTP 获取方式是兼容的console.log(req.method);console.log(req.url);console.log(req.httpVersion);console.log(req.headers);//2. express 独有的获取报文的方式//获取查询字符串console.log(req.query); // 『相对重要』//获取ipconsole.log(req.ip)// 获取指定的请求头console.log(req.get('host'));res.send('请求报文的获取');
    });
    //启动服务
    app.listen(3000, () => {console.log('启动成功....')
    })
    
    在这里插入图片描述

⭐️获取路由参数

  • 路由参数指的是 URL 路径中的参数(数据)
    //导入 express
    const express = require('express');//创建应用对象
    const app = express();//创建路由
    app.get('/:id.html', (req, res) => {//获取 URL 路由参数res.send('商品详情, 商品 id 为' + req.params.id);
    });//监听端口, 启动服务
    app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
    })
    
    在这里插入图片描述

🔥练习:根据路由参数响应歌手信息

//导入 express
const express = require('express');
//导入 json 文件(中括号解构,返回数组)
const {singers} = require('./singers.json');
//创建应用对象
const app = express();//创建路由
app.get('/singer/:id.html', (req, res) => {//获取路由参数let {id} = req.params;//在数组中寻找对应 id 的数据let result = singers.find(item => {if(item.id === Number(id)){return true;}});//判断if(!result){res.statusCode = 404;res.send(`<h1>404 Not Found</h1>`)return;}res.send(`<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><h2>${result.singer_name}</h2><img src='${result.singer_pic}' /></body></html>`);
});//监听端口, 启动服务
app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
})

在这里插入图片描述

🐇express响应设置

  • express 框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式

    //获取请求的路由规则
    app.get("/response", (req, res) => {
    //1. express 中设置响应的方式兼容 HTTP 模块的方式
    res.statusCode = 404;
    res.statusMessage = 'xxx';
    res.setHeader('abc','xyz');
    res.write('响应体');
    res.end('xxx');
    //2. express 的响应方法
    res.status(500); //设置响应状态码
    res.set('xxx','yyy');//设置响应头
    res.send('中文响应不乱码');//设置响应体
    //连贯操作
    res.status(404).set('xxx','yyy').send('你好朋友')
    //3. 其他响应
    res.redirect('http://atguigu.com')//重定向
    res.download('./package.json');//下载响应
    res.json();//响应 JSON
    res.sendFile(__dirname + '/home.html') //响应文件内容
    });
    

🐇express中间件

  • 中间件(Middleware)本质是一个回调函数。中间件函数可以像路由回调一样访问请求对象(request)和响应对象(response)。
  • 中间件的作用 就是 使用函数封装公共操作,简化代码。
  • 类型:全局中间件和路由中间件。

⭐️定义全局中间件

  • 声明中间件函数

    let recordMiddleware = function(request,response,next){//实现功能代码//.....//执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用next)next();
    }
    

    在这里插入图片描述

  • 应用中间件:app.use(recordMiddleware);

  • 声明时直接传递

    app.use(function (request, response, next) {console.log('定义第一个中间件');next();
    })
    
  • express 允许使用 app.use() 定义多个全局中间件

    app.use(function (request, response, next) {console.log('定义第一个中间件');next();
    })
    app.use(function (request, response, next) {console.log('定义第二个中间件');next();
    })
    

/*** 记录每个请求的 url 与 IP 地址*/
//导入 express
const express = require('express');
const fs = require('fs');
const path = require('path');//创建应用对象
const app = express();//声明中间件函数(在这里就是起一个函数声明形成模板,不用在每个app里写记录语句)
//把公共代码放这里(这样每次请求都能被记录)
function recordMiddleware(req, res, next){//获取 url 和 iplet {url, ip} = req;//将信息保存在文件中 access.logfs.appendFileSync(path.resolve(__dirname, './access.log'), `${url}  ${ip}\r\n`);//调用 next,让它去调用后续的路由函数next();
}//使用中间件函数
app.use(recordMiddleware);//创建路由
app.get('/home', (req, res) => {res.send('前台首页');
});app.get('/admin', (req, res) => {res.send('后台首页');
});app.all('*',(req, res) => {res.send('<h1>404 Not Found</h1>')
})//监听端口, 启动服务
app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
})

在这里插入图片描述

⭐️定义路由中间件

  • 如果只需要对某一些路由进行功能封装 ,则就需要路由中间件。

  • 调用格式如下:

    app.get('/路径',`中间件函数`,(request,response)=>{
    });
    app.get('/路径',`中间件函数1`,`中间件函数2`,(request,response)=>{
    });
    

/*** 针对 /admin  /setting 的请求, 要求 URL 携带 code=521 参数, 如未携带提示『暗号错误』  *///导入 express
const express = require('express');//创建应用对象
const app = express();//创建路由
app.get('/home', (req, res) => {res.send('前台首页');
});//声明中间件
let checkCodeMiddleware = (req, res, next) => {//判断 URL 中是否 code 参数等于 521if(req.query.code === '521'){// 满足条件就调用next();}else{res.send('暗号错误');}
}//后台
app.get('/admin', checkCodeMiddleware, (req, res) => {res.send('后台首页');
});//后台设置
app.get('/setting', checkCodeMiddleware, (req, res) => {res.send('设置页面');
});app.all('*',(req, res) => {res.send('<h1>404 Not Found</h1>')
})//监听端口, 启动服务
app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
})

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

⭐️静态资源中间件

  • express 内置处理静态资源(css,图片等)的中间件

    //引入express框架
    const express = require('express');
    //创建服务对象
    const app = express();
    //静态资源中间件的设置,将当前文件夹下的public目录作为网站的根目录
    app.use(express.static('./public')); //当然这个目录中都是一些静态资源
    //如果访问的内容经常变化,还是需要设置路由
    //但是,在这里有一个问题,如果public目录下有index.html文件,单独也有index.html的路由,
    //则谁书写在前,优先执行谁
    app.get('/index.html',(request,response)=>{respsonse.send('首页');
    });
    //监听端口
    app.listen(3000,()=>{console.log('3000 端口启动....');
    });
    

    在这里插入图片描述


//导入 express
const express = require('express');//创建应用对象
const app = express();//创建路由
app.get('/', (req, res) => {res.send('我才是首页~~~');
});//静态资源中间件设置
app.use(express.static(__dirname + '/public'));//监听端口, 启动服务
app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
})

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

🔥静态资源中间件练习:局域网内访问网页❓

喵喵大王立大功

  • 首先npm init
  • 其次npm i express
  • 创建server.js
    const express = require('express');
    const app = express();// 设置静态资源中间件
    app.use(express.static(__dirname + '/todolist'));app.listen(3000,() =>{console.log('服务已经启动,端口3000正在监听中......')
    })
    
  • node .\server.js
    在这里插入图片描述
  • 查看ip地址:cmd ——>ipconfig
  • 可实现局域网内访问喵喵大王立大功的网页(呜三个舍友只有一个可以呜呜)

在这里插入图片描述

  • 解决办法:ISS管理界面修改
    在这里插入图片描述

🐇 获取请求体数据 body-parser

  • 第一步:安装

    npm i body-parser
    
  • 第二步:导入 body-parser 包

    const bodyParser = require('body-parser');
    
  • 第三步:获取中间件函数

    //处理 querystring 格式的请求体
    let urlParser = bodyParser.urlencoded({extended:false}));
    //处理 JSON 格式的请求体
    let jsonParser = bodyParser.json();
    
  • 第四步:设置路由中间件,然后使用 request.body 来获取请求体数据

    app.post('/login', urlParser, (request,response)=>{//获取请求体数据//console.log(request.body);//用户名console.log(request.body.username);//密码console.log(request.body.userpass);response.send('获取请求体数据');
    });
    

  • 应用:记得先装包
/*** 按照要求搭建 HTTP 服务* * GET   /login  显示表单网页* POST  /login  获取表单中的『用户名』和『密码』*/
//导入 express
const express = require('express');
const bodyParser = require('body-parser')//创建应用对象
const app = express();//解析 JSON 格式的请求体的中间件
// const jsonParser = bodyParser.json()//解析 querystring 格式请求体的中间件
const urlencodedParser = bodyParser.urlencoded({ extended: false })//创建路由规则
app.get('/login', (req, res) => {// res.send('表单页面')//响应 HTML 文件内容res.sendFile(__dirname + '/11_form.html');
});//post 规则
app.post('/login', urlencodedParser, (req, res) => {//获取 用户名 和 密码console.log(req.body);res.send('获取用户的数据')
});//启动服务
app.listen(3000, () => {console.log('server is running...');
})

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

🐇express防盗链

在这里插入图片描述

  • 不允许外部网页调用图片。

🔥防盗链实践

  • 关键:关注referer请求头。
  • 功能:只允许127.0.0.1访问
    //导入 express
    const express = require('express');//创建应用对象
    const app = express();//声明中间件
    app.use((req, res, next) => {//检测请求头中的 referer 是否为 127.0.0.1//获取 refererlet referer = req.get('referer');if(referer){//实例化let url = new URL(referer);//获取 hostnamelet hostname = url.hostname;//判断if(hostname !== '127.0.0.1'){//响应 404 res.status(404).send('<h1>404 Not Found</h1>');return;}}next();
    });//静态资源中间件设置
    app.use(express.static(__dirname + '/public'));//监听端口, 启动服务
    app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
    })
    

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

📚路由模块化Router

🐇介绍

  • express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。
  • Router 作用:对路由进行模块化,更好的管理路由。
  • 主文件代码量减少,管理更方便,就类似css,js外部分离。

🐇使用

  • 创建独立的js文件(homeRouter.js)
    //1. 导入 express
    const express = require('express');
    //2. 创建路由器对象
    const router = express.Router();
    //3. 在 router 对象身上添加路由
    router.get('/', (req, res) => {
    res.send('首页');
    })
    router.get('/cart', (req, res) => {
    res.send('购物车');
    });
    //4. 暴露
    module.exports = router;
    
  • 主文件
    const express = require('express');
    const app = express();
    //5.引入子路由文件
    const homeRouter = require('./routes/homeRouter');
    //6.设置和使用中间件
    app.use(homeRouter);
    app.listen(3000,()=>{console.log('3000 端口启动....');
    })
    

在这里插入图片描述

📚EJS模板引擎

🐇介绍

  • 模板引擎是分离用户界面和业务数据的一种通用型技术(但现在用的没那么多了)。
  • EJS 是一个高效的 Javascript 的模板引擎,官网,中文站
  • 下载安装:npm i ejs --save
  • 示例
    //1.引入ejs
    const ejs = require('ejs');
    //2.定义数据
    let person = ['张三','李四','王二麻子'];
    //3.ejs解析模板返回结构
    //<%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构
    let html = ejs.render(<%= person.join(",") %>, {person:person});
    //4.输出结果
    console.log(html);
    

在这里插入图片描述

  • 执行js代码:<% code %>
  • 输出转义的数据到模板上:<%= code %>
  • 输出非转义的数据到模板上:<%- code %>

🐇列表渲染

//原生 JS
let str = '<ul>';
xiyou.forEach(item => {str += `<li>${item}</li>`;
})
//闭合 ul
str += '</ul>';
console.log(str);

<ul><% xiyou.forEach(item => { %><li><%= item %></li><% }) %>
</ul>

在这里插入图片描述

🐇条件渲染

// 原生 JS
if(isLogin){console.log('<span>欢迎回来</span>')
}else{console.log('<button>登录</button>  <button>注册</button>');
}

<% if(isLogin){ %>
<span>欢迎回来</span>
<% }else{ %>
<button>登录</button>  <button>注册</button>
<% } %>

在这里插入图片描述

🐇express中使用ejs

//导入 express
const express = require('express');
//导入 path
const path = require('path');
//创建应用对象
const app = express();
//1. 设置模板引擎
app.set('view engine', 'ejs');// pug  twing
//2. 设置模板文件存放位置   模板文件: 具有模板语法内容的文件
app.set('views', path.resolve(__dirname, './views'));//创建路由
app.get('/home', (req, res) => {//3. render 响应// res.render('模板的文件名', '数据');//声明变量let title = '尚硅谷 - 让天下没有难学的技术';res.render('home', {title});//4. 创建模板文件
});//监听端口, 启动服务
app.listen(3000, () => {console.log('服务已经启动, 端口 3000 正在监听中....')
})

在这里插入图片描述

📚应用程序生成器express-generator

  • 可以快速创建一个应用的骨架
  • 首先全局安装npm install -g express-generator
  • 创建骨架:express -e <文件夹>
    在这里插入图片描述
  • 然后需要安装依赖npm i
  • 运行npm start
    在这里插入图片描述

  • 该有都有,补充什么,在对应内容添加即可。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/136921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AJAX 入门笔记

课程地址 AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09; AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部分网页内容 XML…

C++初阶(九)内存管理

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、C/C内存分布1、选择题2、填空题3、sizeof 和 strlen 区别&#xff1f;4、总结 二、 C语言…

LED热仿真笔记

LED的输入电能主要转换为热能和光能两个部分。对于车灯散热、建筑热舒适性等计算域尺寸远大于单个LED尺寸的问题&#xff0c;通常不考虑LED的细节结构&#xff0c;LED简化为一个实体即可。 LED热源加载处理&#xff1a; 热能简化为LED实体的体热源光能简化为LED实体的发光面的…

适用于 iOS 的 10 个最佳数据恢复工具分享

在当今的数字时代&#xff0c;我们的移动设备占据了我们生活的很大一部分。从令人难忘的照片和视频到重要的文档和消息&#xff0c;我们的 iOS 设备存储了大量我们无法承受丢失的数据。然而&#xff0c;事故时有发生&#xff0c;无论是由于软件故障、无意删除&#xff0c;甚至是…

rabbitMq虚拟主机概念

虚拟主机是RabbitMQ中的一种逻辑隔离机制&#xff0c;用于将消息队列、交换机以及其他相关资源进行隔离。 在RabbitMQ中&#xff0c;交换机&#xff08;Exchange&#xff09;用于接收生产者发送的消息&#xff0c;并根据特定的路由规则将消息分发到相应的队列中。而虚拟主机则…

Unity地面交互效果——5、角色足迹的制作

大家好&#xff0c;我是阿赵。   之前几篇文章&#xff0c;已经介绍了地面交互的轨迹做法。包括了法线、曲面细分还有顶点偏移。Shader方面的内容已经说完了&#xff0c;不过之前都是用一个球来模拟轨迹&#xff0c;这次来介绍一下&#xff0c;怎样和角色动作结合&#xff0c…

大语言模型(LLM)综述(七):大语言模型设计应用与未来方向

A Survey of Large Language Models 前言8 A PRACTICAL GUIDEBOOK OF PROMPT DESIGN8.1 提示创建8.2 结果与分析 9 APPLICATIONS10 CONCLUSION AND FUTURE DIRECTIONS 前言 随着人工智能和机器学习领域的迅速发展&#xff0c;语言模型已经从简单的词袋模型&#xff08;Bag-of-…

期中考试班主任反馈家长

超实用&#xff01;期中考试后班主任给家长们的反馈话术 尊敬的家长们&#xff1a; 经过一段时间的紧张备考和答题&#xff0c;孩子们终于完成了本学期的期中考试。在此&#xff0c;我反馈一下孩子们这次考试的情况。 首先&#xff0c;感谢每一位孩子在这次考试中所做出的努力和…

洛谷 Equalize the Remainders

洛谷没提供中文题面&#xff0c;这里大致翻译一下&#xff1a; 可以进行的操作&#xff1a;任选一个数加一。 一共有n个整数&#xff0c;还有一个约数m&#xff0c;n个数都对m进行求余&#xff0c;累计余数的数量&#xff0c;要求每个余数都有n/m个。 对于样例1的输入&#xff…

Go入门简介

Go 语言从发布 1.0 版本以来备受众多开发者关注并得到广泛使用&#xff0c;Go 语言的简单、高效、并发特性吸引了众多传统语言开发者的加入&#xff0c;而且人数越来越多。 就目前来看&#xff0c;Go语言已经⼴泛应用于人工智能、云计算开发、容器虚拟化、⼤数据开发、数据分析…

机器学习复习(待更新)

01绪论 &#xff08;1&#xff09;机器学习基本分类&#xff1a; 监督学习&#xff08;有标签&#xff09;半监督学习&#xff08;部分标签&#xff0c;找数据结构&#xff09;无监督学习&#xff08;无标签&#xff0c;找数据结构&#xff09;强化学习&#xff08;不断交互&…

【Axure视频教程】item和targetitem函数

今天教大家在Axure里如何使用item和targetitem函数&#xff0c;会先学历两个函数的基础与区别&#xff0c;然后通过在表格指定位置插入行和两个中继器联动筛选的案例更加深入的讲解这两个函数的应用。注&#xff1a;该教程主要讲解item和targetitem函数&#xff0c;不包含中继器…

【微软技术栈】C#.NET 正则表达式源生成器

本文内容 已编译的正则表达式源生成在源生成的文件中何时使用 正则表达式 (regex) 是一个字符串&#xff0c;它使开发人员能够表达要搜索的模式&#xff0c;使其成为搜索文本和提取结果作为已搜索字符串子集的一种很常见的方法。 在 .NET 中&#xff0c;System.Text.RegularE…

linux常用软件安装

#【gcc&make】 ##分开安装 yum install gcc //c的编译器需要单独安装 yum install gcc-c yum install -y make ##一步到位 yum -y install gcc automake autoconf libtool make #【rzsz】 # 源码编译安装 wget http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.g…

支持C#的开源免费、新手友好的数据结构与算法入门教程 - Hello算法

前言 前段时间完成了C#经典十大排序算法&#xff08;完结&#xff09;然后有很多小伙伴问想要系统化的学习数据结构和算法&#xff0c;不知道该怎么入门&#xff0c;有无好的教程推荐的。今天给大家推荐一个支持C#的开源免费、新手友好的数据结构与算法入门教程&#xff1a;He…

C# wpf 实现任意控件(包括窗口)更多拖动功能

系列文章目录 第一章 Grid内控件拖动 第二章 Canvas内控件拖动 第三章 任意控件拖动 第四章 窗口拖动 第五章 附加属性实现任意拖动 第六章 拓展更多拖动功能&#xff08;本章&#xff09; 文章目录 系列文章目录前言一、添加的功能1、任意控件MoveTo2、任意控件DragMove3、边…

Java面试题(每天10题)-------连载(28)

目录 多线程篇 1、线程和进程有什么区别&#xff1f; 2、线程实现的方式有几种&#xff1f; 3、高并发、任务执行时间短的业务怎么使用线程池&#xff1f;并发布高、任务执行时间长的业务怎么使用线程池&#xff1f;并发高业务执行时间长的业务怎么使用线程池&#xff1f; …

大厂面试题-MySQL的binlog有几种格式?分别有什么区别

Binlog有三种格式&#xff1a;statement&#xff0c;row和mixed。 1、statement&#xff1a;记录的是SQL的原文。好处是&#xff0c;不需要记录每一行的变化&#xff0c;减少了binlog日志量&#xff0c;节约了IO&#xff0c;提高性能。由于sql的执行是有上下文的&#xff0c;因…

【STM32】STM32的Cube和HAL生态

1.单片机软件开发的时代变化 1.单片机的演进过程 (1)第1代&#xff1a;4004、8008、Zilog那个年代&#xff08;大约1980年代之前&#xff09; (2)第2代&#xff1a;51、PIC8/16、AVR那个年代&#xff08;大约2005年前&#xff09; (3)第3代&#xff1a;51、PIC32、Cortex-M0、…

selenium等待元素加载、元素操作、执行js、切换选项卡、登录cnblogs(chrome)、抽屉半自动点赞

selenium等待元素加载 代码操作非常快 ⇢ \dashrightarrow ⇢ 有的标签还没加载 ⇢ \dashrightarrow ⇢ 找就找不到 ⇢ \dashrightarrow ⇢ 就会报错 设置等待&#xff1a;显示等待&#xff0c;隐士等待 # 找某个标签&#xff0c;如果找不到&#xff0c;最多等待10s bro.…