第一部分node.js基础
一、模块系统
1.具名模块
就是node封装好的现成模块,例如fs,os模块,path模块
//operation system模块,获取机器信息
var os=require('os');
console.log(os.cpus());//当前机器cup信息
console.log(os.totalmem());//当前机器内存信息
//path模块,处理路径
var path=require('path');
console.log(path.extname('D:/a/index/img/666.png'))//获取路径下文件的扩展名
2.自定义模块
①简单的模块化
用户自定义使用的模块
例:
//aaa.js
//node中没有全局作用域,只有模块作用域(文件作用域),不同文件不能使用其他文件的变量和方法
console.log('a start');
require('./bbb.js');//执行bbb.js,后缀名可以省略,相对路径需要写./,此处require执行的是具体的文件模块,虽然加载了bbb,但两个文件互不影响
console.log('a end');
function add(x,y){
return x+y;
};
//bbb.js
console.log('b start');
require('./ccc.js');//执行ccc.js,相对路径需要写./,此处require执行的是具体的文件模块
console.log('b end');
add(3,5);
//ccc.js
console.log('ccc执行完毕');
②模块间互相调用成员
例:
// require是一个方法
//它的作用是用来加载模块的
//require有两个作用:
// 1.加载文件模块并执行里面的代码
// 2.拿到被加载文件模块导出的接口对象
//first.js
let res=require('./second');//res默认是一个空的exports对象
console.log(res.code);//打印second中的code成员
console.log(res.add(33,22));//打印second中add方法的结果
//second.js
var code=111;
exports.code=code;//将code挂在到exports对象上,以便其他文件访问当前文件成员
exports.add=function(x,y){
return x+y
}//将add方法挂在到exports对象上
③使用module.exports(非挂载)调用成员
一、调用单个成员
//a.js
let import=require('./b.js')
console.log(import)//结果为字符串hello
//b.js
module.exports ='hello'
//a.js
let import=require('./b.js')
console.log(import)//结果为方法add
//b.js
function add(x,y){
return x+y
}
module.exports =a
//a.js
let import=require('./b.js')
console.log(import)//结果为字符串hello
//b.js
function add(x,y){
return x+y
}
module.exports =a
module.exports ='hello'//字符串hello会覆盖掉上面的add,后者会覆盖前者
二、调用多个成员
//a.js
let import=require('./b.js')
console.log(import)//结果为对象
//b.js
module.exports ={
a:function (x,y){
return x+y
},
str:'hello'
}//导出对象
3.模块中通过接口对象互访成员原理
接口对象exports:
①node中每个js文件都会有默认的接口对象module
var module={
exports:{
a1:'bar',
a2:function
}
}
//
//
//如果分不清
②默认module.exports引用地址和exports引用地址一样
console.log(exports===module.exports)//结果为true
③module最终会return module.exports
所以在用exports和module.exports导出成员时要注意引用地址的变化
④在exports===module.exports的前提下可以混合使用两者导出成员
exports=‘hello’//改变引用地址,和module.exports断开连接,所以不能导出字符串成员hello
总结:
因为module最终return的是module.exports,所以如果分不清exports和module.exports的引用地址,
则统一用module.exports来导出单个成员,module.exports={}来导出多个成员
4.模块查找机制(重点理解)
1优先从缓存加载
2其次核心模块
3路径形式的文件模块
4第三方模块
①node_modules/art-Eemplate/
②node_modules / art-template/package.json
③node_modules/art-template/ package.json main
④index.js备选项(package.json中没有设置main则默认找index.js)
⑤进入上一级目录找node_modules
⑥按照这个规则依次往上找,直到磁盘根目录还找不到,最后报错:Can not find moudle xx
注意:一个项目有且仅有一个node_modules而且是存放到项目的根目录
5.第三方模块
例如express,npm,webpack涉及到会另外总结列出
二、ip地址和端口号
服务器和软件的通信原理:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MMUBLLRE-1622020784562)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\image-20210412195819550.png)]
ip地址和端口号小结:
①ip地址用来定位计算机
②端口号用来定位具体的应用程序
③一切需要联网通信的软件都会占用一个端口号
④端口号的范围在0-65536之间
⑤在计算机中有一些默认的端口号(例如http服务的80),最好不用去使用
⑥可以同时开启多个服务,但要确保不同服务占用的端口号不同(同一端口号同一时间只能被一个程序占用)
三、Content-type指定浏览器解析的文件类型
概述:
通过server的response.end()把服务器的数据发送到浏览器时,需要告诉浏览器解析的是什么类型的文件,
例:根据不同url请求不同类型文件,fs,http模块结合使用
//使用fs模块读取文件,并且使用http服务器发发送文件
let fs = require('fs');
let http = require('http');
let server = http.createServer();
server.on('request', function(req, res) {
let url = req.url;
//默认发送index.html
if (url === '/') {
// 读取文件操作
fs.readFile('./resource/index.html', function(err, data) {
// data默认是二进制数据,可以通过tostring转为咱们能识别的字符串
//设置读取失败的提示信息
if (err) {
res.setHeader('Content-Type', 'text/plain;charset=utf-8');
res.end('文件读取失败,请稍后再试!');
} else {
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end(data); //发送data,因为res.end()支持二进制和字符串,所以可以直接输出data
}
})
}
//读取图片
if (url === '/pic') {
// 读取文件操作
fs.readFile('./resource/wallpaper.jpg', function(err, data) {
// data默认是二进制数据,可以通过tostring转为咱们能识别的字符串
//设置读取失败的提示信息
if (err) {
res.setHeader('Content-Type', 'text/plain;charset=utf-8');
res.end('文件读取失败,请稍后再试!');
} else {
res.setHeader('Content-Type', 'image/jpeg'); //因为是jpg图片文件,所以无需设置字符编码
res.end(data); //发送data,因为res.end()支持二进制和字符串,所以可以直接输出data
}
})
}
});
server.listen(5000, function() {
console.log('server is running~~')
})
查看不同文件对应的contenttype工具网址:
https://www.oschina.net/
四、客户端渲染和服务端渲染的区别
①客户端渲染不利于SE搜索引擎优化
②服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的
③在实际开发中的网站中都是客户端渲染和服务端渲染两者结合开发的
例如京东的商品列表采用的是服务端渲染,目的是为了SEO搜索引擎优化(方便搜索引擎查询),而商品评论列表为了用户体验,而且不需要SEO优化,所以采用的是客户端渲染
五、处理服务器中的静态资源
概述:
当浏览器收到HTML响应内容后,就要从上到下依次解析,带发现有src或者href(link)属性标签(具有外链接的资源)的时候,浏览器会自动对这些资源发起新的请求
例如:link,script,img,iframe,video,audio标签
处理服务器静态资源实例:
注意index.html中的标签地址要写成绝对路径:
<script type="text/javascript" src="/lib/js/jquery.js"></script>
<img src="/lib/img/pic1.jpg">
<img src="/lib/img/pic2.png">
//main.js
//处理服务器静态资源
let http = require('http')
let server = http.createServer()
let fs = require('fs')
server.on('request', function(req, res) {
let url = req.url
//默认请求index
if (url === '/') {
fs.readFile('./lib/views/index.html', function(err, data) {
if (err) {
res.setHeader('Content-Type', 'text/plain;charset=utf-8')
return res.end('文件读取失败,请稍后再试!')
}
res.end(data)
})
} else if (url.indexOf('/lib/') === 0) {
//处理index中的静态资源
fs.readFile('.' + url, function(err, data) {
if (err) {
res.setHeader('Content-Type', 'text/plain;charset=utf-8')
return res.end('文件读取失败,请稍后再试!')
}
res.end(data)
})
}
})
.listen('4000', function() {
console.log('server is running~~~~~')
})
六、node中url模块相关操作
1.解析url中的查询字符串(参数)
let baseurl = req.url
let urlObj = url.parse(baseurl, true) //使用urlparse将url解析成对象,第二个参数设置为true直接将?后参数转换成对象形式
let path = urlObj.pathname //获取url的pathname
let recData = urlObj.query //获取url地址中的参数(对象形式)
2.后台授予跨域访问权限
res.setHeader("Access-Control-Allow-Origin", "*") //解决跨域问题
3.实现服务器重定向
res.statusCode=301//301为永久重定向,浏览器会记住
res.statusCode=302//302为临时重定向
res.setHeader('Location','/')//设置请求头重新定向,'/'为根路径
第二部分Express框架
一、使用express快速构建服务器
let express = require('express') //引用express
let app = express() //构建web服务
//根据请求地址设置不同响应
app.get('/', function(req, res) {
res.send('现在访问的是根目录')
})
app.get('/login', function(req, res) {
res.send('现在访问的是登录页')
})
app.get('/index', function(req, res) {
res.send('现在访问的是首页')
})
app.use('/public/', express.static('./public/'))
//公开public下的所有资源,可以在地址后面使用/public/xx直接访问xx资源
//设置端口号
app.listen(4000, function() {
console.log('server is running~~')
})
二、处理静态资源
app.use( express.static( " public'))//直接/XXX访问public中的XXX资源
app.use( express.static( "files ' ))//直接/XXX访问files中的XXX资源
app.use( ' / static ' , express.static( 'public ' ) )//使用/static/XXX访问public中的XXX资源
app.use( ' /static ' , express.static(path.join( __dirname,'public ' )))
三、获取请求参数
1.get请求
express已经封装好get请求的参数,直接res.query即可获取get请求参数
2.使用body-parser组件获取post请求参数
express中无法直接获取post请求参数,需要借助第三方body-parser插件获取post请求参数
①安装:
npm install body-parser --save
②引用模块:
let bodyParser=require('body-parser')//引用处理post请求参数的组件
③配置参数:
app.use(bodyParser.json(),bodyParser.urlencoded({extended:false})) //配置body-parser插件参数
④获取参数
let params=req.body//使用req.body获取post请求参数
四、express路由模块(router)
1.使用实例:
/**
\* router模块
\* 处理路由
\* 根据不同的请求地址和请求方法设置不同的处理
*/
var express = require('express') //1.引入expres
var router = express.Router() //2.实例化express中的router对象
let personList = require('./public/list.js')//导入数据列表
//3.根据请求地址和方式设置不同的处理
//根目录请求
router.get('/', function(req, res) {
res.send('啊啊啊啊啊页面崩溃了')
})
//查询列表接口
router.get('/list/query', function(req, res) {
res.send(personList)
})
module.exports = router//4.导出router对象
//入口函数模块
let express = require('express') //引用express
let app = express() //构建web服务
let router = require('./router') //5.导入router模块
app.use(router) //6.将路由挂载到app上,注意最后的挂载router必须放在其他app.use后面
//设置端口号
app.listen(2000, function() {
console.log('server is running~~')
})
2.在mian.js中绑定多个路由
//7挂载路由
//7.1home页路由
app.use('/home/channel',require('./src/routers/home/channels.js'))//7.1.1挂载频道路由
app.use('/home/goodslist',require('./src/routers/home/goodslist.js'))//7.1.2挂载商品列表路由
//7.2search页路由
app.use('/search',require('./src/routers/search/giftslist.js'))//7.2.1挂载礼物列表路由
第三部分MongoDB
一、关系型数据库和非关系型数据库
1.关系型数据库:
表就是关系,或者说表和表之间就存在关系。
①所有的关系型数据库都需要sql
语句来操作;
②所有的关系型数据库在操作之前都需要设计表结构;
③关系型数据库有约束性
- 唯一的
- 主键
- 默认的
- 非空
2.非关系型数据库
- 非关系型数据库非常的灵活
- 有的非关系型数据库就是键值对
- MongoDB是最像关系型数据库的非关系型数据库
- 在MongoDB中:
- 数据库=》数据库
- 数据表=》集合(数组)
- 表记录=》(文档对象)
- MongoDB不需要设计表结构
- 可以任意往MongoDB里面存数据,没有结构性这么一说
二、MongoDB下载安装后环境变量配置
1.找到MongoDB安装目录下的bin目录(D:\MongoDB\bin)
2.点开我的电脑→属性→高级系统设置→环境变量→点开path→新建→把bin目录地址粘进去→保存退出
3.cmd中输入mongod --version即可查看版本信息,配置成功
三、MongoDB基本命令行操作
mongo
启动数据库,会自动默认在bin目录下创建并储存在data=》dbexit
、ctrl+c
关闭数据库,命令行会提示byeshow dbs
查看所有数据库,默认有admin、config和localdb
当前数据库- use ‘数据库名’,切换到指定数据库,如果没有则会创建,并且db变为新创建的
- db.xxx.insertOne({‘name’:‘yuankun’})给当前数据库插入一条数据
- show collections查看所有集合
- db.xxx.find()查看数据库某一集合数据
四、使用mongoose连接mongoDB数据库
一、快速上手
1.安装mongoose
npm install mongoose -y
2.连接 mongoDB模块
// 1.导入mongoose模块
const mongoose = require('mongoose')
const Schema = mongoose.Schema // 2.创建mongoose的结构对象schema
// 3.连接MongoDB数据库
mongoose.connect('mongodb://localhost:27017/itcast')
// 4.设计文档结构(表结构)
// 字段名称就是表结构中的属性名称
const userSchema = new Schema({
username: {
type: String,
required: true // 是否必须
},
password: {
type: String,
required: true
},
email: {
type: String
}
})
// 5.将文档结构发布为模型
// mongoose.model方法将一个结构发布为model
// 第一个参数:传入一个大写名词单数字符串表示你的表名,
// mongoose会自动将大写名词的字符串生成小写复数的集合名称
// 这里的User最终会变成集合users
// 第二个参数:架构 schema,对user进行curd
const User = mongoose.model('User', userSchema)
3.mongoose操作数据API
-
1.添加数据
-
// 1.新建数据 let admin = new User({ username:'张三', password:'666666', email:'jojojoo@66.com' }) // 2.储存到数据库 admin.save(function(err,ret){ if(err){ console.log('保存失败') console.log(err) }else{ console.log('保存成功') console.log(ret) } })
-
2.查询数据
-
// 1.查询集合所有元素 User.find(function(err,ret){ if(err){ console.log(err) }else{ console.log(ret) } }) // 2.按条件查询数据 User.find({ username:'张三' },function(err,ret){ if(err){ console.log(err) }else{ console.log(ret) } })
-
3.删除数据
-
//按条件删除数据 User.remove({ username:'张三666' },function(err,ret){ if (err) { console.log('删除失败') }else{ console.log('删除成功') console.log(ret) } })
-
4.修改数据
-
//根据条件更新数据 User.findByIdAndUpdate('608a16567c6b6942e8207d52',{ username:'yaoyuan', password:'999999', email:'1293516898@qq.com' },function(err,ret){ if (err) { console.log('更新失败') }else{ console.log('更新成功') } })
二、封装MongoDB操作模块(典中典)
-
安装插件npm i mongoose -y
-
封装mongoose操作模块
-
/**封装数据库模块 * 封装数据管理api */ //mongoose初始化数据库 const mongoose = require('mongoose') // 1.引入mongoose mongoose.connect('mongodb://localhost:27017/itcast') // 2.连接数据库 const Schema = mongoose.Schema // 3.声明操控表结构的对象Schema const commentSchema = new Schema({ id: { type: Number, required: true }, info: { type: String, required: true }, done: { type: Boolean, default: false, require: true } }) // 4.设计表结构 module.exports = mongoose.model('Comment', commentSchema) // 5.直接导出模型构造函数
-
执行数据操作
//1.查询评论列表接口 router.get('/list/query', function(req, res) { comments.find(function(err,ret) { try { res.send({ state: 0, msg: '查询成功', data: ret }) } catch (err) { res.send({ state: 1, msg: '查询失败' + err }) } }) })
第四部分连接MySql
一、快速上手
1.安装插件:npm install mysql -s
2.连接mysql模块
var mysql = require('mysql');// 1.引入mysql
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});// 2.输入信息,创建连接
connection.connect();// 3.连接数据库
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});// 4.数据操作
connection.end();//5.结束连接
二、封装mysql操作模块(经典)
1.配置连接数据库参数
// /utils/mysqlconfig.js
//配置链接数据库参数
module.exports = {
host: 'ip',
user: '用户名',
password: '密码',
database: '数据库名称'
}
2.封装mysql操作模块
-
安装插件:npm install mysql -s
-
/** *mysql操作模块 */ const mysql = require('mysql') // 1.引入mysql模块 var databaseConfig = require('../utils/mysqlconfig') //2.引入数据库配置模块中的数据 //3.向外暴露方法 module.exports = { query: function(sql, params, callback) { //每次使用的时候需要创建链接,数据操作完成之后要关闭连接 var connection = mysql.createConnection(databaseConfig) //3.1连接数据库 connection.connect(function(err) { if (err) { console.log('数据库链接失败') throw err } //3.2开始数据操作 //传入三个参数,第一个参数sql语句,第二个参数sql语句中需要的数据,第三个参数回调函数 connection.query(sql, params, function(err, results, fields) { if (err) { console.log('数据操作失败') throw err } //将查询出来的数据返回给回调函数 callback && callback(results, fields) //results作为数据操作后的结果,fields作为数据库连接的一些字段 //停止链接数据库,必须再查询语句后,要不然一调用这个方法,就直接停止链接,数据操作就会失败 //3.3关闭数据库连接 connection.end(function(err) { if (err) { console.log('关闭数据库连接失败!') throw err } }) }) }) } }
3.在路由模块调用mysql操作数据
const express = require('express') // 引入express const router = express.Router() // 实例化路由router const db =require('../../api/mysql.js')// 引入mysql操作api // 2.查询配饰列表 router.get('/accessorylist', (req, res) => { let sql='SELECT * FROM `accessorylist`' db.query(sql, [],function(result,fields){ console.log('查询配饰商品列表成功') res.send(result)//向页面返回查询结果 }) }) module.exports = router//导出此路由
console.log('数据操作失败') throw err } //将查询出来的数据返回给回调函数 callback && callback(results, fields) //results作为数据操作后的结果,fields作为数据库连接的一些字段 //停止链接数据库,必须再查询语句后,要不然一调用这个方法,就直接停止链接,数据操作就会失败 //3.3关闭数据库连接 connection.end(function(err) { if (err) { console.log('关闭数据库连接失败!') throw err } }) }) })
}
}### 3.在路由模块调用mysql操作数据
const express = require(‘express’) // 引入express
const router = express.Router() // 实例化路由router
const db =require(’…/…/api/mysql.js’)// 引入mysql操作api// 2.查询配饰列表
router.get(’/accessorylist’, (req, res) => {
let sql='SELECT * FROMaccessorylist
’
db.query(sql, [],function(result,fields){
console.log(‘查询配饰商品列表成功’)
res.send(result)//向页面返回查询结果
})
})module.exports = router//导出此路由