1.Node是一个运行时环境,他可以解析和执行jS代码,以前只有浏览器可以解析执行JS代码,现在的JS可完全脱离浏览器来运行,即node.js。他构建在Chrome的V8引擎(是目前公认的解析执行JS代码最快的引擎)之上——把该引擎移植出来,开发了一个独立的JS运行时环境。
2.Node.js中的javaScript没有Bom和Dom,有EcmaScript,并在node这个javaScript执行环境中为JS提供了一些服务器级别的操作API:如文件读写,网络服务的构建,网络通信,http服务器等处理。
3.Node.js特性:事件驱动,非阻塞IO模型(异步)
4.npm:Node.js’ package ecosystem,世界上最大的开源库生态系统,存放绝大多数JS相关的包,让开发人员更方便地去下载使用。
5.模块系统:
node中有模块作用域:内部外部均无法相互访问。文件与文件之间是模块作用域,模块是完全封闭的(没有全局作用域),只能通用exports空对象导出 的东西才能被外部访问。
把需要被外部访问使用的成员手动挂载到‘exports’接口对象中,谁‘require’该模块,谁就可以得到模块内部的‘exports’接口对象
6.require是一个方法,用来加载模块,node中模块有三种:
1)具名的核心模块(均有自己特殊的名称标识,eg fs文件操作模块,http网络服务构建模块,os操作系统信息模块,path路径处理模块等),模块使用前必须手动使用‘require方法来加载’
2)用户自己编写的文件模块(相对路径必须加‘./’,但可以省略后缀名)
7.content-type头部属性:text/plain 为普通文本,text/html 表示发送的内容为html格式,希望浏览器自动转为普通格式。中文操作系统默认是gbk编码,所以获取服务端数据时,头文件上content-type属性可以传个charset=utf-8字符编码类型(但是图片不需要)
server.on('request', function(request, response) {
response.setHeader('Content-Type', 'text/plain; charset=utf-8')
response.end('<p>hello世界</p>') })
8.HTTP 的 Content-type对照表(百度搜索oschina) https://tool.oschina.net/commons
9. url 为统一资源定位符,一个url最终对应一个资源
10.模板引擎art-template:最早诞生于服务器领域,后来发展到前端,前端使用时,可以在控制台中输出模板引擎中的内容,也可以将数据render到指定文件并在浏览器展示
body>
<script src="../01/node_modules/art-template/lib/template-web.js"></script>
<script type="text/template" id="tpl">
<p>hello! My name is {{name}}</p>
</script>
</body>
</html>
<script>
let ret = template('tpl', {
name: 'Jack'
})
console.log(ret);
</script>
11.
服务端响应给客户端的结果实际是页面中的字符串,接着浏览器端解析字符串
客户端渲染(页面不会刷新,异步(更快),动态追加):浏览器向服务器端发起请求,将模板引擎的数据进行渲染。先收到服务器端响应的字符串,自上向下解析之后,如果发现有异步ajax请求,则再次发起新请求,拿到ajax响应结果之后进行模板引擎渲染(很早地看到页面,但是数据渲染较慢)
服务端渲染(网页源代码中可以看到数据,可以被搜索引擎搜索到):只请求一次,在发送给客户端之前,服务器端会先处理并渲染好页面中的数据,他最终响应的就是返回的结果。( let 渲染结果 = template.render( 模板字符串,{解析替换对象} ) )
12.
Node中的url模块使用:可以在cmd中将网页链接分割成如下字段属性:
1.1输入的参数若第二个参数为true,则可以拆分出地址栏中?后的信息:
1.2在代码中运用url模块:网页重定向:
301:永久性重定向
302:暂时性重定向
let parseObj = url.parse(request.url, true)
if (pathname === '/pinglun') {//html页面中提交的表单的action属性
console.log('收到表单请求了', parseObj.query)//在终端显示表单中填写并提交的数据
// response.end(JSON.stringify(parseObj.query))
let comment = parseObj.query//获取表单提交的数据
comment.dateTime = '2021.10.04'
comments.push(comment)
//通过服务器让客户端重定向
response.statusCode = 302//状态码设置为临时重定向
response.setHeader('Location','/')//响应头中告诉客户端在哪里重定向
response.end()
最终在控制台中可以看到:
但是用express框架的话就不用那么麻烦: 看21、
13、第三方包的使用:
通过npm install --save之后的包都会被保存到node_modules目录中(npm版本5之后就可以不用save也会保存到package.json中),但是为什么直接通过require就能使用第三方包呢?
只要是第三方包,node默认会先找到当前文件所处目录中的node_modules目录,找到里面对应的第三方包中的package.json文件中的main属性(即入口模块),然后加载该第三方包,实际上加载的还是文件。但是如果package.json文件不存在或者main指定的入口模块没有,则node会自动找到该目录下的index.js,也就是说index.js会作为一个默认备选项。
若以上条件均不成立,则会进入上一级目录中的node_modules目录查找,若上一级还是没有则继续上上一级,直到当前磁盘根目录还找不到则报错。
14、package.json文件(包描述文件,就像产品说明书)
可以直接通过npm init自动初始化出来。该文件中的depandencies选项用来帮助保存第三方包的依赖信息(每次下载第三方包都会自动增加相关信息)。当删除了node_modules,只需要npm install就可自动把package.json中的depandencies中的所有依赖都下载回来。
**建议每个项目的根目录都下一个package.json
**建议执行npm install包名 的时候都加上--save这个选项,目的是用来保存依赖项信息
15、npm 常用命令
npm init -y 跳过向导,快速以默认数据生成
npm install 一次性把dependencies选项中的依赖项全部安装
npm install 包名 仅下载
npm install --save 包名 下载并保存依赖项
npm uninstall 包名
npm uninstall --save 包名
npm install --global 包名 在任意目录执行都可以(表示安装到全局而非当前目录)
npm 命令 --help查看指定命令的使用,eg. npm uninstall --help
16、npm存储包文件的服务器在国外,有时候会被墙,速度过慢
法1 安装淘宝的cnpm
执行npm install --global cnpm 然后安装包时只需要把之前的npm替换成cnpm
法2 不想安装cnpm又想使用淘宝的服务器来下载:
npm install jquery --registry=https://registry.npm.taobao.org
但每次手动这样加参数很麻烦,所以可以把该选项加入配置文件中:
npm config set registry https://registry.npm.taobao.org
再查看npm配置信息
npm config list
只要经过了上面命令配置,以后所有的npm install都会默认通过淘宝服务器下载
17、路径
17.1文件操作路径:
相对路径:./dta/a.txt 或 dta/a.txt
绝对路径:/dta/a.tx 或 C:/cc/cc...
17.2模块操作路径:
绝对路径:require('/dta/a.tx')
相对路径: require('./data/a.txt') 不能省略 './'
18、nodemon基于Node.js的第三方工具
每次修改完代码都需要重新node运行一次,而使用nodemon可以实现修改完代码之后自动重启服务器、
步骤:
npm install --global nodemon
终端运行是用nodemon代替node eg. nodemon app.js
19、使用express框架
(****遇到res.send、res.redirect这些方法Express会自动结束响应)
1.安装并引入第三方包,看官网
2.let app = express()//相当于原来的http.createServer
3.使用express中的use方法:用于公开指定目录,可以直接获取指定目录下的所有路径内容,如:
//use方法可以通过第一个参数以/public/xx的方式访问第二个参数路径中的所有资源(第一个参数是url统一资源定位符,可以随便定义)
①app.use('/public/', express.static('./public/'))
②app.use( express.static('./public/'))//当只有一个参数时,直接以参数路径中/xx为路径,省略/public
③然后就可以直接在
1.地址栏输入127.0.0.1:端口号/public/img/123.jpg 得到图片内容
2.html页面的href中输入/public/xx
4.使用express中的get方法:
//服务器收到get请求/的时候,执行回调处理函数,以前不用express框架时需要拿到路径通过else if一个个判断
app.get('/', function(req,res) {
res.send("hello expressssss!")//express中对wirte方法和end方法的简写
})
app.get('/about', function(req,res) {
res.send(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>hello html!</h1>
</body>
`)
})
5.express中的Router()方法,后面有
20.express中使用art-template模板引擎
1.安装
github中找到art-template,有api文档,导航栏里有express部分
npm install --save art-template npm install --save express-art-template
**express-art-template 依赖于art-template ,用来在express中把art-template整合到express中
2.配置
app.engine('html', require('express-art-template'))
**当渲染以.html结尾的文件时,使用art-template模板引擎
3.使用
express 为Response对象提供了一个方法:render(配置了模板引擎才可以使用)
res.render('html模板名',{模板数据})参数一不能是路径,默认会去项目中的views目录查找该模板文件
app.get('/', function(req, res) {
res.render('404.html')
})
app.get('/admin', function(req, res) {
res.render('admin/index.html', {
title: '管理系统'
})
})
//如果想要修改默认的views目录,可以用
//app.set('views', render函数的默认路径)
21.使用express框架获取表单传输的数据:对比1.2、
21.1.Express内置了一个API:get请求可直接通过req.query直接获取
//使用get获取表单数据
app.get('/pinglun', function(req, res) {
//不需要url.parse就可以直接拿到数据,qurey只能拿get请求数据,post不行
// console.log(req.query);
let comment = req.query
comment.dateTime = '2017-11-05'
comments.unshift(comment)
res.redirect('/')
})
21.2.但没有内置获取表单POST请求体的API,需要使用第三方包来获取请求体:官网导航栏-资源-中间件
21.2.1.安装 npm install --save body-parser(会在req请求对象上多出一个属性:body,即可以直接req.body获取表单POST请求体数据)
21.2.2.配置
//使用post请求
//安装并引包
let bodyParser = require('body-parser')
//配置body-parser中间件(插件,专门用来解析表单POST请求体)
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.post('/pinglun', function(req, res) {
// console.log(req.body);
let comment = req.body
comment.dateTime = '2017-11-05'
comments.unshift(comment)
res.redirect('/')
})
21.2.3. 使用
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
//通过req.body获取表单POST请求体数据
res.end(JSON.stringify(req.body, null, 2))
})
22.将路由模块单独提取出来
法1:通过自己封装函数实现:
法2:Express提供了更好的方式,专门用来包装路由:
23.
24.MongoDB:动态的,可以直接用js代码设计数据库
24.1下载安装---菜鸟教程中有官网链接以及步骤(别忘记在安装的盘下创建数据目录存放数据)
24.2在node中操作MongoDB数据
法1 使用官方mongodb包来操作,在npm官网上搜索mongo可以看到github链接,有教程(少用)
法2 使用第三方mongoose操作MongoDB数据库,基于MongoDB官网的mongodb包再一次做了封装 。 网站:mongoosejs.com 官方API: Mongoose v6.0.11: API docs 安装 :npm i mongoose 使用:
/*js文件中*/
const mongoose = require('mongoose');
//连接mongodb数据库
mongoose.connect('mongodb://localhost:27017/test');
//创建一个模型:设计数据库
const Cat = mongoose.model('Cat', { name: String });
//实例化一个Cat
const kitty = new Cat({ name: 'Zildjian' });
//持久化保存该实例
kitty.save().then(() => console.log('meow'));
25.关系型数据库和非关系型数据库
1.表就是关系(表与表之间存在关系)
*所有关系型数据库都需要通过sql语言操作,操作前要设计表结构,支持约束:唯一,主键,默认值,非空
2.非关系型数据库:灵活,有的非关系型就是key-value对(MongoDB是最像关系型的非关系型数据库 => 集合(数据表),文档对象(表记录),数据库(数据库))
*MongoDB不需要设计表结构(可以任意存数据)
*node可以操作所有类型的数据库
26.path路径操作模块
*path.basename (路径的文件名,默认包含扩展名)
*path.dirname (路径的目录部分)
*path.extname (路径扩展名)
*path.parse (路径转对象,作语法分析)
*path.join (路径拼接)
*path.isAbsolute (是否绝对路径)
27.node中的路径问题
***文件操作中,相对路径不可靠,在node中文件操作的路径是相对于终端所处的路径:
解决上面问题:(使用绝对路径的方式)
***每个模块中,除了require,exports等模块相关API外,还有两个特殊成员:
__dirname 获取当前文件模块所属目录的绝对路径(动态)
__filename 获取当前文件的绝对路径(动态)
它们不受执行终端所属路径的影响
**拼接路径会有低级错误,推荐使用path.join()来辅助拼接
待更新、