node-day3

(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)本节总结

   

.

原文地址:https://www.cnblogs.com/jianxian/p/12150090.html