- node
- ECMAscript
- node-API
- node.js回调函数是错误优先的回调函数
- 系统模块
- fs(File system)
- fs.readFile('文件路径/文件名称'[,'文件编码'],callback) 读文件
- callback
- (err,doc)=>{}
- callback
- fs.writeFile('文件路径/文件名称',数据,callback) 向文件中写入内容 (覆盖)
- callback
- (err)=>{}
- callback
- fs.appendFile() 向文件中追加内容 (追加)
- fs.mkdir() 创建目录
- fs.readFile('文件路径/文件名称'[,'文件编码'],callback) 读文件
- path
- path.parse() 解析路径 获取路径信息
- path.join() 路径拼接
- 不同系统路径分隔符不统一
- 防止路径拼接少写斜杠问题
- 使用绝对路径进行路径拼接 __dirname
- 相对路径
- 不是相对于当前的js文件
- 而是相对于命令行的当前目录
- require是相对于当前js文件
- __dirname当前文件所在目录的绝对路径
- 绝对路径
- 常用path.join(__dirname,'执行文件')
- http
- 创建web服务器
- const server = http.createServer();
- server.on('request',(request,response)=>{})
- // 引用系统模块
- const http = require('http');
- // 创建web服务器
- const server = http.createServer();
- // 当客户端发送请求的时候
- server.on('request', (req, res) => {
- // 设置响应头
- res.writeHead(200, {
- 'Content-Type': 'text/html;charset=utf8'
- });
- // 设置响应体
- res.write('<h1>哈哈哈</h1>');
- // 结束请求
- res.end();
- });
- // 监听3000端口
- server.listen(3000, error => {
- if (!error) {
- console.log('服务器已启动,监听3000端口,请访问 localhost:3000')
- }
- });
- http协议
- 超文本传输协议,用于从web服务器传输超文本到本地浏览器的传送协议,基于客户端服务器架构工作
- 创建web服务器
- url
- url,parse(url,true)
- 返回对象
- 第二个参】、0数默认false,标识是否转换成对象
- fs(File system)
- 第三方模块(包)
- 以js文件的形式存在,提供实现项目具体功能的API接口
- 以命令行工具形式存在,辅助项目开发
- 本地安装(库文件)
- npm默认下载到当前工作目录
- 全局安装(命令行工具)
- 安装npm install -g
- 卸载npm uninstall
- nrm
- nrm -ls
- nrm use
- glup
- 基于node平台开发的前端构建工具
- package.json
- npm init -y生成
- 放置在项目的项目的根目录下
- 项目描述文件,记录当前项目信息,例如项目名称、版本、作者、github地址、当前项目依赖了哪些第三方模块,目的是方便他人了解项目信息,下载项目依赖文件
- scripts
- 对执行的命令起别名
- 开发依赖
- npm install 包 --save dev
- 声明是开发依赖
- 在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖。
- package.json记录在devDependence中
- 项目依赖
- npm install 包
- 在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖
- package.json记录在Dependence中
- 为什么记录依赖项
- Node.js中下载的第三方包文件拥有非常多的细碎文件,将项目通过移动硬盘传递给别人时传输速度非常慢.
- 使用git工具管理项目时,不希望git管理node_modules文件夹,也不会将其上传到github中.
- package.lock.json
- 锁定包的版本,确保再次下载不会因为包的不同版本来产生问题
- npm install会下载所有依赖
- npm install --production只下载项目依赖
- 模块查找规则
- 当引入模块拥有路径但没有后缀
- require方法接收相对路径,相对于当前文件
- 先找同名文件再找同名js文件夹
- 如果找到同名文件夹(包)
- package.json中找main入口中保存的js文件
- 没有执行默认Index.js
- 在没有报错
- 无路径无后缀
- 先当做系统模块
- 找不到去node_modules文件夹下去加载
- package.json中找main入口中保存的js文件
- 没有执行默认Index.js
- 当引入模块拥有路径但没有后缀
- 全局对象
- global
- console.log()
- setTimeout()
- clearTimeout()
- setInterval()
- clearInterval()
- 在全局作用域声明的变量不能在global下找到
- global
- 模块化
- js弊端
- 命名冲突和项目依赖
- 模块化开发需要依赖第三方库文件
- 模块之间相互独立
- 解决命名冲突和项目依赖
- 将具有独立·功能的代码分离到单独的文件中
- 项目代码易于维护
- 一个js文件也就是一个模块,在模块内部定义的变量和函数默认情况下在外部无法访问·
- js弊端
- 模块化的使用
- 导入
- required
- required(使用模块)
- 导入模块
- 导出(对外暴露)
- exports是module.exports的别名
- exports.属性="值"
- module.exports.属性="值"
- 当module.exports以{}的方式整体导出时会覆盖exports的属性和方法
- 当exports与module.exports指向不同的对象时最终导出以module.exports为准
- 只能用module.exports指向一个新对象
- 导入
- 服务器端
- C/S体系结构
- 客户端/服务端,例如QQ、网盘
- 优点:交互性好,对服务器压力小,安全
- 缺点:服务器更新时需要同步更新客户端
- B/S体系结构
- 浏览器/服务端,例如网站
- 优点:不需要更新客户端
- 缺点:交互性差,安全性低
- web服务器
- 能够提供web访问服务的机器就是网站服务器,能接收浏览器端的请求,能对请求做出响应
- server
- ip地址
- 电脑在互联网中的唯一的地址
- 域名
- P地址与域名是对应的关系,在浏览器的地址栏中输入域名,会有专门的服务器 (DNS) 将域名解析为对应的IP地址,从而找到对应的服务器
- 如果将本机作为服务器,本机有一个特定的域名是 localhost
- 端口
- 当前电脑给软件分配的编号
- URL
- 同一资源定位符
- 专为标识网上资源位置而设的一种编码方式
- 协议+域名+端口号+路径
- 自己的IP地址127.0.0.1(域名localhost)
- 报文
- 请求报文
- 获取请求方式
- request.method
- 表单提交
- method
- action表单提交的地址
- 表单默认 提交行为是GET
- 获取请求地址(标识)
- request.url()
- 获取请求报文
- request.headers()
- 请求参数
- GET请求数据
- 参数被放在地址栏中
- POST发送数据
- 参数被放置在请求体中
- 格式和GET参数相同
- // 处理post参数
- // 由于post传递的参数数据量比较大,在网络中并不是一次性传递完成的,而是分成了多次传递
- // 所以在接收的时候也需要分为多次接收
- // 在NodeJs中接收post参数需要使用事件完成
- const querystring = require('querystring');
- let formData = '';
- req.on('data', chunk => formData += chunk);
- req.on('end', () => console.log(querystring.parse(formData)));
- GET请求数据
- 获取请求方式
- 响应报文
- http状态码(标识)
- 200请求成功
- 404请求的资源没有找到
- 500服务器端错误
- 400客户端请求有语法错误
- 301重定向
- 1** 信息,服务器收到请求,需要请求者继续执行操作
- 2** 成功,操作被成功接收并处理
- 3** 重定向,需要进一步的操作以完成请求
- 4** 客户端错误,请求包含语法错误或无法完成请求
- 5** 服务器错误,服务器在处理请求的过程中发生了错误
- 内容类型
- res.writeHead(“状态码”,{'content-type":"内容类型;charset=utf8"})
- http状态码(标识)
- 客户端请求方式
- 浏览器地址栏
- Form表单提交
- link标签的href属性
- script标签的src属性
- image标签的src属性
- 请求报文
- 路由
- 路由是指URL地址与程序的映射关系,更改URL地址可以改变程序的执行结果
- 静态资源处理
- 服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件。
- 使用Node.js的第三方模块serve-static处理静态资源的响应。
- 实现静态资源访问
- 第三方模块serve-static
- 引入serve-static模块获取创建静态资源服务功能的方法
- 调用方法创建静态资源服务并指定静态资源服务目录
- 启用静态资源服务功能
- const serveStatic = require('serve-static')
- const serve = serveStatic('public')
- server.on('request', () => {
- serve(req, res, ()=>{})
- })
- server.listen(3000)
- 第三方模块 router
- 功能:实现路由
- 使用步骤:
- 获取路由对象
- 调用路由对象提供的方法创建路由
- 启用路由,使路由生效
- router.get/post('地址',(req,res)=>{})
- ip地址
- C/S体系结构
- 工作原理
- 同步异步
- 同步或者异步指的是服务器端处理请求的方式
- 同步
- 代码一行一行执行,下一行的代码必须等待上一行代码执行完成以后才能执行
- 异步
- 代码在执行过程中某行代码需要耗时,代码的执行不会等待耗时操作完成以后再去执行下一行代码,而是不等待直接向后执行.异步代码的执行结果需要通过回调函数的方式处理
- promise语法
- Promise出现的目的是解决Node.js异步编程中回调地狱的问题
- Promise本身是一个构造函数,需要使用new运算符创建Promise构造函数的实例对象
- 在创建对象的时候需要传入一个匿名函数,匿名函数中有两个参数 resolve,reject
- 链式then+catch
- 异步函数
- 将异步代码写成同步的形式,让代码不再有回调函数嵌套
- async
- 普通函数定义前加async关键字 普通函数变成异步函数
- 异步函数默认返回promise对象
- 在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法
- 在异步函数内部使用throw关键字抛出程序异常
- 调用异步函数再链式调用then方法获取异步函数执行结果
- 调用异步函数再链式调用catch方法获取异步函数执行的错误信息
- await
- await关键字只能出现在异步函数中
- await promise await后面只能写promise对象 写其他类型的API是不不可以的
- await关键字可是暂停异步函数向下执行直到promise返回结果
- promisify
- // 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法
- const promisify = require('util').promisify;
- // 调用promisify方法改造现有异步API 让其返回promise对象
- const readFile = promisify(fs.readFile);
- 同步异步
- 模板引擎
- 模板引擎可以让将数据和HTML模板更加友好的结合,省去繁琐的字符串拼接,使代码更加易于维护
- ART-TEMPLATE
- .art不是用<!--注释>
- 高性能 JavaScript 模板引擎,使用npm install art-template命令下载
- // 模板引擎导入
- const template = require('art-template');//返回方法
- // 模板编译
- // 1.模板位置
- // 2.向模板中传递要拼接的数据,对象类型,对象属性可以直接在模板中使用。
- // result 拼接结果
- const result = template('绝对路径/index.html',插值表达式 );
- 模板语法
- 插值表达式
- {{}}
- 显式数据,将数组放在双大括号内即可
- 原始语法
- <% %>
- 标准语法
- {{数据}}
- 原始语法
- <%=数据 %>
- 标准语法
- <% %>
- 原文输出
- 如果数据中携带HTML标签,默认不会解析标签,会将其转义后输出
- {{@ value }}
- 条件判断
- <!-- 标准语法 -->
- {{if 条件}} ... {{/if}}
- {{if v1}} ... {{else if v2}} ... {{/if}}
- <!-- 原始语法 -->
- <% if (value) { %> ... <% } %>
- <% if (v1) { %> ... <% } else if (v2) { %> ... <% } %>
- <!-- 标准语法 -->
- 数组循环
- {{each target}}
- {{$index}} {{$value}}
- {{/each}}
- <!-- 原始语法 -->
- <% for(var i = 0; i < target.length; i++){ %>
- <%= i %> <%= target[i] %>
- <% } %>
- {{each target}}
- 子模板
- <!-- 标准语法 -->
- {{include './header.art'}}
- <!-- 原始语法 -->
- <% include('./header.art') %>
- <!-- 标准语法 -->
- 模板继承
- {{extend './layout.html'}}
- {{block '名字'}} ... {{/block}}
- 模板中预留位置和填充内容
- 模板配置
- 向模板中导入变量 template.defaults.imports.变量名 = 变量值
- 模板中调用导入的方法
- {{方法名(要处理的变量)}}
- 模板中调用导入的方法
- 设置模板根目录template.defaults.root=模板目录
- 设置模板默认后缀 template.defaults.extname = '.art'
- 向模板中导入变量 template.defaults.imports.变量名 = 变量值
- 插值表达式
- mongoDB
- Node.js通常使用MongoDB作为其数据库,具有高性能,易使用,存储数据方便等特点,完全使用JavaScript语法即可操作
- 使用Node.js操作MongoDB数据库需要依赖Node.js第三方包mongoose,使用npm install mongoose命令下载
- 概念
- database 数据库 mongoDB数据库软件中可以建立多个数据库
- collection 集合 一组数据的集合,可以理解为JavaScript中的数组
- document 文档 一条具体的数据,可以理解为JavaScript中的对象
- field 字段 文档中的属性名称,可以理解为JavaScript中的对象属性
- 开启mongoDB服务
- 在命令行工具中运行net start mongodb即可开启MongoDB服务。
- 创建数据库
- 不需要显式创建数据库
- 数据库连接
- // 引用mongoose包
- const mongoose = require('mongoose');
- // 数据库链接
- mongoose.connect('mongodb://localhost/playground')
- .then(() => console.log('数据库连接成功'))
- .catch(err => console.log('数据库连接失败', err));
- 创建集合
- 创建集合实际上就是对集合设定规则
- // 设置集合规则
- const courseSchema = new mongoose.Schema({
- name: String,
- author: String,
- tags: [ String ],
- data: { type: Date, default: Date.now },
- isPublished: Boolean
- });
- // 使用规则创建集合 返回集合类(集合构造函数)
- const Course = mongoose.model('Course', courseSchema);
- 创建集合实际上就是对集合设定规则
- 创建文档
- 创建文档实际上就是向集合中插入具体的数据
- save方式
- // 创建集合类的实例
- const course = new Course({
- name: 'Node.js course',
- author: 'wangjian',
- tags: ['node', 'backend'],
- isPublished: true
- });
- // 保存实例
- course.save();
- create方式
- Course.create({name: 'JavaScript基础', author: '黑马讲师', isPublish: true}, (err, doc) => {
- // 错误对象
- console.log(err)
- // 当前插入的文档
- console.log(doc)
- });
- // create还支持promise 可以写成下面的形式
- Course.create({name: 'JavaScript基础', author: '黑马讲师', isPublish: true})
- .then(doc => console.log(doc))
- .catch(err => console.log(err))
- save方式
- 创建文档实际上就是向集合中插入具体的数据
- 查询文档
- .find()
- .limit()
- .sort()
- .select()
- .exec((err, data) => {})
- 删除文档
- 删除单个
- Course.findOneAndDelete({}).then(result => console.log(result))
- // findOneAndDelete只会删除一个如果有多条数据 就删除第一个
- 删除多个
- User.deleteMany({}).then(result => console.log(result))
- Course.findByIdAndRemove(id, err => {});
- 删除单个
- 更新文档
- 更新单个
- User.updateOne({查询条件}, {要修改的值}).then(result => console.log(result))
- 更新多个
- User.updateMany({查询条件}, {要更改的值}).then(result => console.log(result))
- 根据id更新
- Course.findByIdAndUpdate(id, {
- $set: {
- author: 'mosh',
- isPublished: false
- }
- }, err => {})
- 更新单个
- 多集合联合查询(集合关联)
- // 用户集合
- const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));
- // 文章集合
- const Post = mongoose.model('Post', new mongoose.Schema({
- title: { type: String },
- // 使用ID将文章集合和作者集合进行关联
- author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
- }));
- //联合查询
- Post.find()
- .populate('author')
- .then((err, result) => console.log(result));
- Mongoose验证
- required: true 必传字段
- minlength:3 字符串最小长度
- maxlength: 20 字符串最大长度
- min: 2 数值最小为2
- max: 100 数值最大为100
- enum: ['html', 'css', 'javascript', 'node.js']
- trim: true 去除字符串两边的空格
- validate: 自定义验证器
- default: 默认值
- catch获取错误信息
- error => {
- // 获取错误信息对象
- const err = error.errors;
- // 循环错误信息对象
- for (var attr in err) {
- // 将错误信息打印到控制台中
- console.log(err[attr]['message']);
- Express(第三方插件)
- 框架特性
- .提供了方便简洁的路由定义方式
- 对获取HTTP请求参数进行了简化处理
- 对模板引擎支持程度高,方便渲染动态HTML页面
- 提供了中间件机制有效控制HTTP请求
- 拥有大量第三方中间件对功能进行扩展
- send()
- 内部会检测响应内容的类型
- 会自动设置http状态码
- 会帮我们自动设置响应的内容类型及编码
- 中间件
- 中间件本质上就是函数,可访问请求对象和响应对象,可对请求进行拦截处理,处理后再将控制权向下传递,也可终止请求,向客户端做出响应
- get和post中间件方法
- server.get/post('请求',(req,res,next)=>{
- next()
- })
- next方法表示进行下一个匹配
- 但位置无关
- use中间件
- use中包含一个函数
- 匹配所有请求
- server.use((req,res,next)=>{
- next();
- })
- 匹配单一请求
- server.use('请求'(req,res,next)=>{
- next();
- })
- 路由保护
- 采用多级中间件进行请求拦截和过滤
- 网站维护
- 对所有请求拦截并进行响应
- 自定义404页面
- 在所有路由都未匹配成功,进行响应
- res.status('状态码')
- 链式
- 错误处理中间件
- 定义在所有中间件后边
- 集中处理错误
- server.use((err,req,res,next)=>{
res.status('500').send('err.message');} - 同步
- server.use('请求',(req,res)=> {
thorw new Error('错误信息')//只能捕捉同步错误})
- server.use('请求',(req,res)=> {
- 异步的人为的将错误对象交给错误处理中间件
- 异步代码
- 异步函数
- try{}catch{}
- server.use((err,req,res,next)=>{
- 框架的基本架构
- 通常一个网站项目分2部分路由:
- 前台展示页面的路由
- /home/list 列表页
- /home/index 首页
- 后台管理的路由
- /admin/login 登录页
- /admin/list 列表页
- /admin/add 添加页
- /admin/login 登录页
- 前台展示页面的路由
- 构建模块化路由
const express = require('express') // 第1步,创建路由对象 const home = express.Router(); // 第2步,在home路由下继续创建路由 home.get('/index', () => { // /home/index res.send('欢迎来到博客展示页面'); }); // 第3步,将路由和请求路径进行匹配 app.use('/home', home); - 获取get请求参数
- req.query
- 返回一个对象
- 获取post请求参数
- 借助第三方包body-parser
// 引入body-parser模块 const bodyParser = require('body-parser'); // 配置body-parser模块 app.use(bodyParser.urlencoded({ extended: false }));extended为true时使用QS模块(同queryString)进行解析extended为false时使用queryString 进行解析 // 接收请求 app.post('/add', (req, res) => { // 接收请求参数 console.log(req.body); }) ;
- 借助第三方包body-parser
- 路由参数
// 以get方式访问/list路由时携带id参数app.get('/index/id/:pp', (req, res) => {想要多携带/:参数1/:参数2 console.log(req.params) // {"pp":"123"}});// 客户端请求时地址栏应该写成这样// http://localhost:3000/index/id/123- 一种请求地址:把请求参数放在了请求地址中,看上去好像是请求地址
- 静态资源的处理
- 通过 Express 内置的 express.static 可以方便地托管静态文件,例如图片、CSS、JavaScript 文件等
// 拦截所有的请求,如果是静态资源访问请求,就自动到 静态资源目录去找到这个文件并响应回去app.use(express.static('静态资源绝对位置'));app.use('/static',express.static('静态资源绝对位置'));
- 通过 Express 内置的 express.static 可以方便地托管静态文件,例如图片、CSS、JavaScript 文件等
- express-art-template模板引擎
- 在art-template基础封装
- 使用
var express = require('express');var app = express();// 告诉Express框架 使用art-template模板引擎渲染HTML模板app.engine('html', require('express-art-template'));// 当render方法渲染模板时, 如果模板所在路径被省略, 则在内部会自动将以下路径进行拼接// 设置模板所在目录app.set('views', path.join(__dirname, 'myvv'));// 当render方法渲染模板时, 如果模板后缀被省略, 则将html作为默认的文件后缀app.set('view engine', 'html');app.get('/', function (req, res) { // 将拼接好的结果直接响应给客户端 res.render('index.art', { user: { name: 'aui', tags: ['art', 'template', 'nodejs'] } });}); - locals对象
- 变量设置到.locals对象下面,这个数据在所有的模板中都可以获取到
- 通常一个网站项目分2部分路由:
- 框架特性
一名前端小白的学习笔记(1/N)--node
最新推荐文章于 2020-06-04 10:07:18 发布