Node.js入门指南(四)

目录

express框架

express介绍

express使用

express路由

express 响应设置

中间件

路由模块化 

EJS 模板引擎

express-generator


hello,大家好!上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识,这篇文章主要给大家分享Node.js中的express框架!

express框架

express介绍

在上几篇文章中我们介绍了如何使用http模块去搭建http请求,而在实际的开发中却很少直接使用它去搭建服务。一般都会借助express框架去进行开发。express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs.com.cn/ express 相当于是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)。

express使用

express 本身是一个 npm 包,所以我们可以通过 npm 来进行安装。先对文件进行初始化:npm i,然后再使用npm i express来进行安装express。它的基本使用如下,通过node(nodemon) index.js执行文件之后,我们在浏览器通过访问:http://127.0.0.1:9000/home来进行访问结果。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建get请求
app.get('/home',(req,res)=>{
    res.end('hello express');
});
//监听端口
app.listen(9000,()=>{
    console.log('服务启动!')
})

express路由

有学习过vue的小伙伴对路由应该不陌生,express中的路由也是同样的道理,通过访问不同的路径来得到不同的模块,在此之前我们是通过判断语句来实现访问不同路径返回对应内容的。而路由能够更加简便地来实现相应的功能。

一个路由包括请求的方法,请求的路径以及回调函数三个部分组成。回调函数接收请求的对象以及相应的对象两个参数。使用all可以适用于所有的请求方式,而路径使用 * 一般用于处理请求路径匹配不到的错误。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建get请求
app.get('/home',(req,res)=>{
    res.end('hello express');
});
//创建post请求
app.post('/login',(req,res)=>{
    res.end('login success');
});
//首页路由
app.get('/',(req,res)=>{
    res.end('home');
})
//匹配所有请求方法
app.all('/search',(req,res)=>{
    res.end('all req');
})
//定义404路由
app.all('*',(req,res)=>{
    res.end('<h1>404 Not Found</h1>')
})
//监听端口
app.listen(9000,()=>{
    console.log('服务启动!')
})

我们仍然可以使用express来获取到请求报文中的数据。express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式。它除了具有原生的method、url、httpVersion以及headers等操作以外,它还可以直接使用req.path来得到请求的路径,以及req.query来得到查询的数据,并且是以对象形式输出。调用get()方法还可以直接传入自己想要的特定响应头进行输出。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建get请求
app.get('/request',(req,res)=>{
    //原生操作
    console.log(req.method);//GET
    console.log(req.url);///request?name=N-A
    console.log(req.httpVersion);//1.1
    console.log(req.headers);
    //express操作
    console.log(req.path);///request
    console.log(req.query);//{ name: 'N-A' }
    //获取ip
    console.log(req.ip);//::ffff:127.0.0.1
    //获取特定的请求头
    console.log(req.get('host'));//127.0.0.1:9000

    res.end('hello express');
});

//监听端口
app.listen(9000,()=>{
    console.log('服务启动!')
})

路由参数的获取对我们很重要,我们需要通过用于输入的不同的路由参数来匹配出不同的数据,但如果我们一个一个去添加路由规则的话是不现实的。这时候我们可以使用路由参数,在传参的位置我们使用一个占位符,:字符串。字符串的位置在发请求时随意写什么都可以进行匹配到。同时我们可以使用req.params.id来获取我们的路由参数,通过判断获取到的路由参数来返回不同的结果。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建路由
app.get('/:id.html',(req,res)=>{
    console.log(req.params.id);
    res.end('goods detail');
})

//监听端口
app.listen(9000,()=>{
    console.log('服务启动!')
})

可能有点难理解,我们来做一个小练习体验一下吧!现在有个需求,通过用于在浏览器输入不同的请求路径,在json文件中会匹配到对应的数据进行展示。先将两个水果的数据放在一个json文件中,然后当用于输入http:127.0.0.1:9000/friut/1.html时在页面上显示id为1的水果的描述以及图片,http:127.0.0.1:9000/friut/2.html时显示id为2的水果。

//json文件
{
    "friut":[
        {
          "id":1,
          "name": "沃盼(WOPAN)四川眉山脐橙新鲜水果橙子2kg 4斤装",
          "dicPrice": "¥19.9",
          "oriPrice": "¥50",
          "src":"https://ts1.cn.mm.bing.net/th/id/R-C.efa51c1248bc80a2bd2bc9a1c2449fad?rik=f%2f53DOukVylGvg&riu=http%3a%2f%2fn.sinaimg.cn%2fsinakd20210207s%2f296%2fw1030h866%2f20210207%2f09f4-kirmaiu8306791.jpg&ehk=eTr6szTDThqmZdwt5x3V45f%2b%2bRNJFsDuBjDBLFY99fY%3d&risl=&pid=ImgRaw&r=0"
        },
        {
          "id":2,
          "name": "智利原装进口车厘子礼盒装JJ级 约2kg 果径约28-30mm 原箱礼盒装 新鲜水果",
          "dicPrice": "¥219",
          "oriPrice": "¥299",
          "src":"https://img.zcool.cn/community/0165435d9c740da801211d530e7b5e.jpg@1280w_1l_2o_100sh.jpg"
        }
    ]
}
//index.js

//导入express
const express = require('express');

//导入json文件
const { friut } = require('./data.json');

//创建应用对象
const app = express();
//创建路由
app.get('/friut/:id.html', (req, res) => {
    //获取路由参数
    let { id } = req.params;
    //在数组中寻找对应的id的数据
    let result = friut.find(item => {
        if (item.id === Number(id)) {
            return true;
        }
    });
    //判断
    if(!result){
        res.statusCode=404;
        res.end(`<h1>404 Not Found</h1>`)
    }

    res.end(`
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
    <h2>${result.name}</h2>
    <img src="${result.src}"/>
    </body>
    </html>
    `);
})

//监听端口
app.listen(9000, () => {
    console.log('服务启动!')
})

要点就是通过获取到路由的参数来进行相应数据的寻找以及匹配。

express 响应设置

express可以对相应的数据进行相应的设置,框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式。主要有res.status( )用于设置状态码,res.set()用于设置响应头,res.send()用于设置响应体,使用该方法设置响应体会自动将响应体中的内容转为utf-8的格式,直接写入中文不会出现乱码,因此无需再进行响应头的设置。同时几个方法还可以进行连贯操作。

const express=require('express');
const app=express();
app.get('/response',(req,res)=>{
    //原生响应设置
    res.statusCode=404;
    res.statusMessage='Not Find';
    res.setHeader('name','N-A');
    res.write('hello');
    res.end('response');

    //express响应
    res.status(200);
    res.set('name','N-A');
    res.send('你好呀')
    res.status(200).set('name','N-A').send('你好呀');
});

app.listen(9000,()=>{
    console.log('服务已经启动!');
})

同时express还可以进行其他的响应设置,比如跳转响应、下载响应、JSON响应、响应文件的内容等。具体的实现效果自行实践。

const express=require('express');
const app=express();
app.get('/response',(req,res)=>{
   //跳转响应
   res.redirect('https://baidu.com');
   //下载响应
   res.download(__dirname+'./data.json');
   //JSON响应
   res.json({
    name:'N-A',
    study:'Node.js'
   })
   //响应文件内容
   res.sendFile(__dirname+'/index.html')
});

app.listen(9000,()=>{
    console.log('服务已经启动!');
})

中间件

中间件(Middleware)本质是一个回调函数中间件函数可以像路由回调一样访问 请求对象(request) , 响应对象(response)。它的作用就是使用函数封装公共操作,对代码进行简化。它包括:全局中间件以及路由中间件。全局中间件每一个请求到达服务端之后都会执行全局中间件函数,而路由中间件只对某一些路由进行功能的封装。

全局中间件的实例如下,全局中间件函数三个参数,req,res以及next。next用于接续执行。使用中间件需要调用app.use()。

const express=require('express');
const app=express();
const fs=require('fs');
const path=require('path');
//声明中间件函数
function recordMiddleware(req,res,next){
    let {url,ip}=req;
    //将信息保存在文件中
    fs.appendFileSync(path.resolve(__dirname,'./access.log'),`${url} ${ip}\r\n`);
    next();
}

//使用中间件函数
app.use(recordMiddleware);

app.get('/home',(req,res)=>{
    res.send('首页')
});
app.get('/detail',(req,res)=>{
    res.send('详情页')
});
app.listen(9000,()=>{
    console.log('服务已经启动!');
})

路由中间件的实例如下,无需关注具体实现的功能,主要认识路由中间件如何使用,后续要实现什么功能,函数里面替换成对应的操作即可。它的使用方式与全局中间件不一样。它需要到对应的路由中进行添加。

const express=require('express');
const app=express();
const fs=require('fs');
const path=require('path');
//声明中间件函数
function checkCodeMiddleware(req,res,next){
   if(req.query.code==='521'){
    next();
   }else{
    res.send('错误');
   }
}

app.get('/home',checkCodeMiddleware,(req,res)=>{
    res.send('首页')
});
app.get('/detail',checkCodeMiddleware,(req,res)=>{
    res.send('详情页')
});
app.all("*",(req,res)=>{
    res.send('<h1>404</h1>')
})
app.listen(9000,()=>{
    console.log('服务已经启动!');
})

静态资源来前几篇文章我们已经有介绍到了,对于静态资源的处理也是比较麻烦,需要获取对应文件的后缀名来判断该文件属于哪一种资源,再做相应的处理。而静态资源中间件可以大大地提高我们处理静态资源的效率。使用方式如下:

//引入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 端口启动....');
});

静态资源中间件index.html为默认打开的资源,如果静态资源与路由规则同时匹配,谁先匹配谁就响应。路由响应动态资源,静态资源中间件响应静态资源

最后我们再介绍一个中间件:body-parser。express可以使用这个中间件来进行处理请求体。首先需要使用:npm i body-parser 进行安装。然后需要导入body-parser包,再获取中间件函数,最后是使用 request.body 来获取请求体数据。

我们以一个实例来展示吧,假设我们通过get请求来向本地的/login路径发请求,显示表单网页,通过post请求访问/login来获取表单中的用户名以及密码。

//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login" method="post">
        用户名:<input type="text" name="username"><br/>
        密码  :<input type="password" name="password"><br/>
        <button>登录</button>

    </form>
    
</body>
</html>
//导入express
const express=require('express');
//导入body-parser包
const bodyParser = require('body-parser');
//创建应用对象
const app=express();

//处理 JSON 格式的请求体
//let jsonParser = bodyParser.json();

//处理 querystring 格式的请求体
let urlParser = bodyParser.urlencoded({extended:false});
//创建路由规则
app.get('/login',(req,res)=>{
    res.sendFile(__dirname+'/index.html');
});
//post规则
app.post('/login',urlParser,(req,res)=>{
    console.log(req.body);
    res.send(req.body)
})
//监听端口
app.listen(9000,()=>{
    console.log('服务启动!')
})

路由模块化 

当什么需要对多个路由进行设置时,都在主文件中进行设置就会非常乱,维护起来也不是很好,因此express引入了Router,它可以实现路由的模块化,更好地进行管理路由。express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。

//创建单独的管理文件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(9000,()=>{
console.log('服务已经启动');
})

EJS 模板引擎

EJS 是一个高效的 Javascript 的模板引擎,模板引擎是分离 用户界面和业务数据 的一种技术。简单地将就是它能够实现我们的html文件以及js文件分离。上面那个路由跳转不同水果的案例我们就把html中的文件写到了js里面。因此使用EJS模板引擎可以让两者进分开。

首先我们需要使用:npm i ejs --save来进行安装。它是将变量名使用<%= 变量名 %>的形式包裹起来的。那具体怎么样体现它的分离效率呢?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   <h2><%= name %>今天学习<%= study %></h2>
    
</body>
</html>
//导入EJS
const ejs=require('ejs');
const fs=require('fs');
//字符串
let name='N-A';
let study='Node.js'
//声明变量
let str=fs.readFileSync('./index.html').toString();
//使用ejs渲染
let result=ejs.render(str,{name,study});
console.log(result);

这样就可以完全将两者进行拆分,后续想要修改或者增加都是可以实现的。

下面再来演示EJS模块列表的渲染以及条件的渲染。都是使用<% %>将内容或者操作包裹在里面,然后变量仍然使用<%= %>来进行包裹。

//进行列表的渲染
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   <ul>
    <% study.forEach(item=>{ %>
        <li><%= item %></li>
    <% })%>
   </ul>
    
</body>
</html>
//导入EJS
const ejs=require('ejs');
const fs=require('fs');

const study=['Node.js','Vue.js','ES6','Webpack']
//声明变量
let str=fs.readFileSync('./index.html').toString();
//使用ejs渲染
let result=ejs.render(str,{study});
console.log(result);


//输出
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   <ul>
    
        <li>Node.js</li>
    
        <li>Vue.js</li>
    
        <li>ES6</li>
    
        <li>Webpack</li>

   </ul>

</body>
</html>

下面展示条件渲染:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   <% if(isLogin) { %>
   <span>欢迎回来</span>
   <% }else{ %>
    <span>请登录</span>
    <% } %>
    
</body>
</html>
//导入EJS
const ejs=require('ejs');
const fs=require('fs');

let isLogin=true;
//声明变量
let str=fs.readFileSync('./index.html').toString();
//使用ejs渲染
let result=ejs.render(str,{isLogin});
console.log(result);


//当isLogin为true是会输出欢迎回来,当为false时会显示请登录

那express如何使用EJS模板引擎呢?首先需要设置模板引擎,其次要设置模板文件的存放位置,然后通过render()方法来做响应,该方法接受两个参数:模板的文件名以及数据。最后再去设置的相应位置下去创建模板文件,后缀应该是.ejs。

//index.js

//导入express
const express=require('express');
const app=express();
const path=require('path');
//设置模板引擎
app.set('view engine','ejs');
//设置模板文件的存放位置
app.set('views',path.resolve(__dirname,'./views'));

app.get('/home',(req,res)=>{
    //render响应
    let name='N-A';
    res.render('home',{name});

    res.end('hello express');
})
//监听端口
app.listen(9000,()=>{
    console.log('服务启动!')
})
<!-- home.ejs -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1><%= name  %></h1>
    
</body>
</html>

express-generator

在我们练习的过程中express框架的代码都是我们一点一点写的,但是在实际的开发中会非常地低效,而express官方提供了一个工具express-generator,可以帮助我们快速搭建应用的骨架。

首先我们使用npm install -g express-generator命令来进行安装。然后可以通过express -h来查看它的相关命令。我们选择ejs模板引擎来进行创建。输入expres -e 文件名。创建之后先对文件进行初始化,npm init 以及npm i。之后运行npm start 打开3000端口,看到如下图片则表示成功!

创建之后的文件内容可以自己研究研究,这里就不做过多的解释!

好了,本文就好这里结束啦!感谢阅读~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c语言中指针详解

内存与地址 1.地址的概念 众所周知数据需要在内存中读取&#xff0c;那么我们当我们需要找这个内存时该怎么办&#xff1f;其实在计算机中每个内存单元都有一个编号&#xff0c;有了这个编号CPU可以快速找到内存空间&#xff0c;在这里我们将这个编号叫做地址&#xff0c;在c…

企业计算机服务器中了360勒索病毒怎么办,360勒索病毒解密文件恢复

计算机技术的不断发展&#xff0c;为企业的生产运营提供了极大便利&#xff0c;不仅提升了办公效率&#xff0c;还促进了企业的发展。企业计算机在日常工作中一定加以防护&#xff0c;减少网络威胁事件的产生&#xff0c;确保企业的生产生产运营。最近&#xff0c;网络上的360后…

nodejs+vue+python+PHP+微信小程序-健身俱乐部在线管理平台的设计与实现-安卓-计算机毕业设计

随着经济的发展、财富的累积&#xff0c;人们生活水平、生活质量大幅度提高&#xff0c;生活环境得到明显改善&#xff0c;但是竞争激烈、人们生活压力大、生活节奏快加上饮食习惯和生活方式不合理导致国内 亚健康人群逐年增多。统计数据表明当前我国亚健康人群比例已经超过了7…

vscode导入STM32CubeIDE工程文件夹未定义警告清除方法

0 前言 在我们使用vscode去编辑STM32CubeIDE的工程文件时&#xff0c;经常会出现一些类型未定义、头文件路径无效的问题&#xff0c;无法正常使用且非常影响观感。本文介绍如何设置vscode导入的STM32CubeIDE配置文件&#xff0c;解决这一问题。 1 vscode导入STM32CubeIDE工程…

JVM——几种常见的对象引用

目录 1. 软引用软引用的使用场景-缓存 2.弱引用3.虚引用和终结器引用 可达性算法中描述的对象引用&#xff0c;一般指的是强引用&#xff0c;即是GCRoot对象对普通对象有引用关系&#xff0c;只要这层关系存在&#xff0c; 普通对象就不会被回收。除了强引用之外&#xff0c;Ja…

Python武器库开发-前端篇之CSS盒模型(三十一)

前端篇之CSS盒模型(三十一) CSS盒模型是指网页中的每个元素可以看做是一个矩形盒子&#xff0c;该盒子有四个主要部分组成&#xff1a;content、padding、border和margin。其中&#xff1a; content&#xff1a;指盒子中的内容区域&#xff0c;可以包含文本、图像、视频、其他…

illuminate/database 使用 四

文档&#xff1a;Hyperf Database: Getting Started - Laravel 10.x - The PHP Framework For Web Artisans 因为hyperf使用illuminate/database&#xff0c;所以按照文章&#xff0c;看illuminate/database代码实现。 一、读写分离 根据文档读写的host可以分开。设置读写分…

辅助驾驶功能开发-系统方案篇-地平线超级驾驶解决方案介绍

01.产品方案 Horizon Matrix SuperDrive超级驾驶解决方案,助力汽车智能化步入人机共驾时代 SuperDrive超级驾驶解决方案,全面整合了自动驾驶、智能交互、云端大脑三大模块,形成完整的泛车载AI人工智能系统,帮助整车智能化提升到一个新的高度。该方案的核心硬件-车载中央计…

从0到0.01入门 Webpack| 006.精选 Webpack面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

基于Loki + Promtail + Grafana 搭建 Nginx 日志监控

文章目录 引言第一部分&#xff1a;Loki 简介与安装1.1 Loki 简介1.2 Loki 安装1.2.1 下载 Loki1.2.2 安装 Loki 1.3 启动 Loki 第二部分&#xff1a;Promtail 简介与安装2.1 Promtail 简介2.2 Promtail 安装2.2.1 下载 Promtail2.2.2 安装 Promtail 2.3 启动 Promtail 第三部分…

MySQL 库操作 | 表操作

文章目录 一.MySQL库的操作1.创建数据库2.字符集和校验规则3.操纵数据库 二.MySQL表的操作1.创建表2.操作表3.删除表 一.MySQL库的操作 1.创建数据库 创建数据库 创建数据库的SQL如下&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [[DEFAULT] CHARSETcharset_name…

Java基于协同过滤算法开发的springboot+vue服装商城

演示视频 https://www.bilibili.com/video/BV1oH4y127fq/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 主要功能&#xff1a;用户可以浏览商品和特价商品&#xff0c;加入购物车&#xff0c;直接下单支付&#xff0c;在我的个人中心里可以管理自己的…

【数据结构实验】树(一)构建二叉查找树(BST)

文章目录 1. 引言2. 二叉查找树3. 实验内容3.1 实验题目&#xff08;一&#xff09;输入要求&#xff08;二&#xff09;输出要求 3.2 算法实现1. 数据结构2. 全局变量3. 中序遍历函数InOrder4. 二叉查找树的构建函数T5. 主函数 3.3 代码整合 4. 实验结果 1. 引言 二叉查找树&a…

python多线程为什么没有跑满CPU?

1、实验环境 Vmvare虚拟机&#xff1a;单处理器2核。 2、Python获取CPU使用率 import psutildef get_cpu_percent():cpu_percent psutil.cpu_percent(interval1)return cpu_percentwhile(1):cpu_percent get_cpu_percent()print("当前CPU占用率&#xff1a;{}%"…

第81篇:JSONP劫持漏洞获取敏感信息原理、复现与坑点总结

Part1 前言 大家好&#xff0c;我是ABC_123。今天我们研究一下JSONP劫持漏洞&#xff0c;早些年这个漏洞主要被攻击者用来窃取个人信息&#xff0c;如姓名、身份证号、家庭住址等&#xff0c;现在更多的用于蜜罐之中&#xff0c;间接溯源红队攻击者的个人身份。好多朋友至今对…

34970A 数据采集 / 数据记录仪开关单元

34970A 数据采集 / 数据记录仪开关单元 产品综述&#xff1a; Keysight 34970A 数据采集/数据记录仪开关单元由一个 3 插槽主机和一个内置的 6 1/2 位数字万用表组成。每个通道可以单独配置&#xff0c;以测量 11 种不同功能之一&#xff0c;这样既不会增加成本&#xff0c;也…

mybatis的使用,mybatis的实现原理,mybatis的优缺点,MyBatis缓存,MyBatis运行的原理,MyBatis的编写方式

文章目录 MyBatis简介结构图Mybatis缓存&#xff08;一级缓存、二级缓存&#xff09;MyBatis是什么&#xff1f;mybatis的实现原理JDBC编程有哪些不足之处&#xff0c;MyBatis是如何解决这些问题的&#xff1f;Mybatis优缺点优点缺点映射关系 MyBatis的解析和运行原理MyBatis的…

Element-Plus 图标自动导入

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

吉他初学者学习网站搭建系列(3)——如何实现吉他在线调音

文章目录 背景知识teoriapitchytone效果 背景知识 学过初中物理就会知道&#xff0c;声音是由空气振动产生的。振动产生波&#xff0c;所以声音就是不同振幅和频率的波构成的。振幅决定了声音的响度&#xff0c;频率决定了声音的音高。想更进一步了解的可以访问这个网页wavefo…

Harmony开发 eTs公共样式抽取

Harmony系统开发使用eTs开发过程中对于样式相同且重复使用的样式可以抽取成公共样式循环利用&#xff0c;类似于android的style样式。 import router from ohos.router import cryptoFramework from ohos.security.cryptoFramework; import prompt from system.prompt class L…