(1)反馈
1、本节知识
2、SEO
网站运营专业,负责SEO搜索引擎优化,职位SEO运营专员
3、软件开发版本---设计软件工程学
4、each与forEach
5、node重要性
6、模块加载规则
7、node网站开发模型
8、重定向
永久重定向案例:
访问新浪时,会永久重定向
(2)模块系统
前言:
1、什么是模块化?
如果一套平台具有以下特点,那么就是模块化
2、模块作用域
3、多次添加
4、局部导出模块
需求升级:现在希望直接导出的exports对象中的方法和属性,无需再加点执行符去解析
方式:module.exports
如果模块只需要导出某个成员,而非挂载的方式,可以使用module.exports = 导出成员
(3)CommonJS模块规范&&加载导出规范
1、前言
2、require导入
3、exports导出
4、覆盖性
(单个导出语法注意)使用module.exports导出模块时,如果重复导出则会覆盖之前的导出模块
结果为函数,覆盖了之前的字符串
(4)exports和module.exports区别
1、分析
我们可以从底层实现去理解:在node里每个模块内部都有一个自己的对象module,而该module对象里,有一个子对象exports
在node里,谁require该文件,谁就得到module.exports接口对象
我们发现,每次导出接口成员时通过module.exports.xxx = xxx的方式很麻烦,都得通过点.方式
因此node为了简化操作,专门提供了一个变量:exports = module.exports
也就是说在模块底层实现里,还有这么一句代码
var exports = module.exports
测试如下
2、原理解析
exports是module.exports的一个引用
3、导出单个模块
当导出单个模块时,需要module.exports即可
4、思考进阶(面向对象--引用类型)
为什么导出单个对象不可以使用exports = xxx;直接赋值定义导出???
原理图:引用数据类型
接下来再看个思考题
结果为hello,为什么呢?
当给obj1重新赋值后,它便指向了新对象,开辟了新的内存空间,如下所示,此时两者已经没有关系
综上分析不能使用exports = xxx来直接导出单个成员
var exports = module.exports
类似于
var obj1 = obj
这里exports只是module.exports的一个引用,所以这里直接给exports直接赋值,并不会影响module.exports,只是指向了新对象而已。
始终要记住:底层实现里最后返回的是module.exports对象
5、重新赋值,解除引用
此外,这里要注意:一旦给exports重新赋值,便会失去和module.exports的关联,指向新对象,且后期无法使用。
如下所示
6、思考2
对上述代码再次修改如下
结果如下
7、思考3
再使用module.exports添加如下
8、思考4
接下来再做下调整
原理如下:
换为exports与module.exports
这里注意:此时两者已经没有引用关系,最终return的是module.exports所以只需要看module.exports即可
9、思考5
接着修改代码
10、思考6
11、小结
1、exports为modules.exports的一个引用 2、最后node底层模块导出的是module.exports 3、底层代码 var module = { exports:{...} } 4、exports.name等价于module.exports.name,但node为了方便书写,使用module.exports导出单个成员,本质为将该子对象重新赋值
5、所以只要给exports赋值,便丢失了module.exports的引用关系,后期便不可用
(5)复习
1、each和forEach
2、伪数组对象转数组
Array.prototype.slice.call(jQuery实例对象)
slice截取拷贝测试:
底层实现:
接下来写个伪数组对象
接下来,伪数组对象转数组,如下所示
此时,内部this指向fakeArr伪数组对象
3、模块导出成员(单个与多个)
4、301与302的区别
301为永久重定向,浏览器会保留缓存,下次访问url时会直接从缓存里访问跳转(使用较少)
302为临时重定向
5、exports与module.exports
(6)require加载规则---优先从缓存加载
1、首先新建测试文件a.js、b.js、c.js
执行顺序为
a.js→b.js→c.js→b.js→a.js
c.js执行完毕后返回b.js执行,因为b.js后续没有代码了,所以返回a.js
接着a.js里又调用了c.js,这里注意不会重复调用,而是为了提高性能,优先从缓存加载
验证如下
分析:
如果之前已经加载过该模块,则直接从缓存里拿取结果,不会重复执行加载
可以拿到接口对象的代码,但不会重复执行里面的代码。
目的:避免重复加载,提高模块加载效率
(7)require标识符分析---即require方法加载规则
1、模块标识符/模块标识
2、判断模块标识符
3、路径形式模块标识
4、非路径形式模块
5、核心模块位置
可以在GitHub查看node源码
const用于定义常量,定义后不可再次更改
var用于定义变量
但安装完成后便被编译到node程序二进制文件中,所以无法直接查看
6、第三方模块
①下载使用
②区分第三方模块与核心模块
不可能有任何一个第三方包和核心模块名字重复
③读取第三方模块步骤
7、读取第三方模块步骤--jquery举例
这里jQuery.js和jquery.min.js并不是源码,源码是src目录下文件,这里也是应用了模块化思想,但和node模块化不太一样
8、验证第三方包如下
在第三方包art-template入口模块index.js做下修改,如果运行时输出标识,则代表猜想正确
9、手动编写模拟第三方包读取加载步骤
①node_modules下创建文件目录a
②a目录下新建package.json说明文件,里面写入main选项标明入口文件(node相关规定)
③入口文件编写代码进行验证
加载导入第三方模块---a
验证如下:
10、其他情况---默认备选项index.js
node默认规则:如果第三方模块不存在package.json或者main选项指定为空,则node会自动寻找目录下的index.js
11、模块查找机制---完整模块加载规则---链式查询加载
所以下面情况可以正常查找到
12、小结
(8)require模块加载查找机制
注意:这里不会进行兄弟查找,和原型链类似,只会进行嵌套查询
因此blog项目下,在b目录中main.js查找第三方模块,无法查找到a目录下的node_modules目录中的模块
不会在兄弟间查找
(9)npm
node package manager包管理工具
npm一般有两层含义:npm网站、命令行工具
1、npm网站
npm网站服务器里的包名不可能重复,通过npm下载的必须存在于该服务器
也可以通过该网站发包
2、npm命令行工具
3、npm常用命令
安装+初始化
卸载依赖注意事项:
查看帮助
4、cnpm
5、解决npm被墙问题
6、测试如下
cnpm init -y
跳过向导步骤,采用默认项,一步到位
7、线上淘宝镜像使用规范
如果不想安装cnpm,且仍旧想使用淘宝镜像下载模块,如下所示
npm i 包名 --registry-https://registry.npm.taobao.org
但是上面这种下载方式过于繁琐,每次还需加上后面的链接,所以可以将这个选项加入配置文件里
验证:
配置项加入淘宝镜像后,再次通过npm下载包时,便会使用配置项链接下载,提高下载效率
8、小结
关于淘宝镜像cnpm用法有两种 1、可以直接下载cnpm到本地,后期使用时只需将指令里的npm换位cnpm即可 2、如果不想下载包,也可以将淘宝镜像链接加入配置项镜像注册,此后再次通过npm下载模块时,便会自动使用淘宝镜像链接下载,提高效率
(10)包说明文件package.json
场景如下:项目目录下,误删了node_modules依赖目录,此时便无从获取项目依赖模块
即便node_modules目录还在,也很难知道依赖了哪些模块,因为里面的文件太多
主要因为:下载安装第三方包时--按照依赖下载
1、手动创建package.json进行测试
手动创建package.json文件,在里面写个{}空对象,然后在同级目录下开始下载模块
与之前不同的是npm i bootstrap && npm i bootstrap --save,这里多了--save参数,下载后会发现除了多出来node_modules目录,在package文件下也会多出下载依赖项
下载后
dependencies描述当前依赖项
此时node_modules目录下,除了使用的模块,还有其依赖文件
由此可以看出,文件太多,无法快速查看项目依赖模块,所以这里就体现出了package.json项目说明文件作用
2、不加--save
下载第三方模块时如果不加--save则不会保存信息到package.json项目说明文件里
3、小结
在实际开发里,一般package.json说明文件都是通过指令创建,进入向导界面
如下所示
package-name | 说明文件名 |
version | 版本号,一般从0.0.1低版本开始即可 |
description | 描述 |
entry point | 入口文件,默认index.js,也可以自定义项目目录下的其他js文件 |
test command | 测试命令 |
git repository | 如果项目放置到git,可以将仓库地址填到这里 |
keywords | 关键字,如果要编写发布第三方包到npm网站,以供他人使用,可以写入关键词 |
author | 作者 |
license | 开源许可证 |
接下来创建完毕后即可生成package.json文件
注意:此时没有dependencies依赖项,在安装第三方包后才会自动生成
4、测试
此时如果再次误删了node_modules依赖模块目录,也没有关系,因为这里的packsge.json中保存了依赖项信息,再次执行npm i指令即可
(11)Express框架介绍+安装
1、简介
express翻译为“特快”、“表达”,简单理解就是封装原生http模块后的一个框架
2、安装
进入Express官网,首页有Getting started入门导航和Guide指南
查看Getting started入门导航,里面有安装导向
3、目录如下
(12)Express框架基本感知
1、安装完毕后,开启第一个案例,感受Express框架
首页→指南→hello world案例
2、这里开始手写案例
①项目根目录下新建入口文件index.js,引包
②接下来分析第三方包解析读取步骤
1、读取第三方包说明文件package.json,查找main选项,获取该包的入口文件 2、如果没有或指定错误,则查找备选项express/index.js
3、 在使用express框架创建服务之前,先来回顾下服务构建模块http创建服务
①版本1
var http = require('http') var server = http.createServer(); server.on('request',function(req,res){ console.log(req.url) res.end('hello world') }) server.listen(3000,function(){ console.log('server start running... ...') })
②版本2---简写版
var http = require('http') var server = http.createServer(function(req,res){ console.log(req.url) res.end('hello world') }).listen(3000,function(){ console.log('server start running... ...') })
4、接下来使用express框架构建服务
/* 引入第三方包 */ var express = require('express') /*创建server服务器,也就是原来的http.createServer*/ var app = express() /*添加响应,类似之前的server.on('request',callback),但这注意是服务器收到get请求/的时候,执行的回调处理函数*/ app.get('/',function(req,res){ res.send('hello world') }) /*启动服务器,监听端口*/ app.listen(3000,function(){ console.log('app is running at port 3000') })
同理,当请求/about时,返回“关于我们”
写好后重启服务器,再次测试即可
验证发现,这里没有乱码,不用再处理请求头信息,设置响应内容编码类型
Express根据语言响应特定编码内容,有时也会将请求头Content-Type添加进来,验证如下所示
5、优势
相对于之前的路径处理(if...else if...else),这里简化了很多,支持并行编写,代码更加简洁
6、内置处理404
express框架内置处理了其他情况,如果路径不存在,则返回对应内容
7、处理开放资源---express.static内置中间件功能
例如public目录下的静态资源,默认不可访问
如果原生处理,则需要做一大堆判断和读取,这里Express框架只需要一个API即可搞定
接下来使用Express框架API开放该资源目录
/*公开指定目录,即开放资源目录*/ app.use('/public/',express.static('./public'))
此后便可以通过localhost:3000/public/js/main.js来访问该静态资源文件,完整如下
/*公开指定目录,即开放资源目录,此后便可以通过/public/xxx访问public下所有开放资源*/ /* 为express.static函数提供服务的文件创建虚拟路径前缀(该路径在文件系统中实际上不存在),请为静态目录指定安装路径 现在可以从/ static路径前缀加载公共目录中的文件 注意:名字随意,最好和开放目录名相同 */ app.use('/static',express.static('./public/'))/*express.static内置中间件功能*/
这里我的虚拟路径前缀为/static,所以可以通过localhost:3000/static/js/main.js来访问
图片也可以,测试如下
8、多资源开放,即同时开放多个目录
同理,如果想和Apache服务器一样,根据url直接读取文件,也可以将node_modules开放
9、小结
开放静态资源、模板引擎等应用,在Express框架里都是一个API的事,这样便提高了开发效率,更多去关注业务逻辑
(13)本节总结
.