Node.js02--03

知识点

  • 模块系统
    • 核心模块
    • 第三方模块
    • 自己写的模块
  • npm
  • package.json
  • Express
    • 第三方web开发框架
    • 高度分装了http模块
    • 更加专注于业务,而非底层细节
    • 知其所以然
  • 增删改查
    • 使用文件来保存数据(锻炼异步编码)
  • MongoDB(所有方法都封装好了)

版本号:x(新增功能比较多,甚至可能去除了某些功能).x(加入了新功能).x(修复bug,提升性能)

遍历方法解析

  • each时art-template的模板语法,专属的
    1
    2
    3
    {{each 数组}}开始便利
    < li>{{$value}}</ li>便利项
    {{/each}}结束遍历
  • jQuery
    $.each(数组,function)
    $(‘div’).each(function)一般用于便利jQuery选择器选择到的伪数组实例对象
  • forEach是ES5中的一个数组遍历函数,是js的原生支持对象

伪数组是一个对象,对象的原型链中没有forEach,对象的原型链是object.prototype

  • jQuery的each和forEach方法基本一致,由于forEach方法是ES5才开始有的一个方法,所以在一些低版本浏览器中可能会存在兼容性问题,IE8不支持注意这两个函数参数位置正好相反forEach的function第一个参数:item,第二个参数:index,jQuery的function第一个参数:index,第二个参数:item

jQuery不是专门用来遍历jQuery元素的
1.方便的遍历jQuery元素
2.可以在不兼容forEach的低版本浏览器中公用jQuery的each方法

网页中的所有路径其实都是url路径,不是文件路径

php比较

php+Apache(默认帮你封装好了很多迪岑那个细节来操作)
但是再Node中比较偏底层,很多东西需要亲自写代码来实现

在Node中开启的服务器,是一个完全的和黑盒子,它不像php,php无论是代码还是网页,都可以直接通过web url路径来访问。
在node中开启的服务器,默认是黑盒子,所有资源都不允许用户来访问每用户可以访问哪些资源由据以的开发人员编写设计的代码为准

永久重定向和临时重定向

  • 301 永久重定向,浏览器会记住
    a.com b.com
    请求a的时候,浏览器不会请求a了,直接跳到b
  • 302 临时重定向 浏览器不会记住
    a.com b.com
    请求a的时候,浏览器还会请求a,a告诉浏览器前往b

模块系统

  • 使用node编写应用程序主要就是使用
    • es语言
    • 核心模块
      fs、http、url、path、os
    • 第三方模块
    • 自己写的模块

什么是模块化

  • 文件作用域
  • 通信规则
    • 加载require
    • 导出

CommonJS模块规范

在node中的js还有一个很重要的概念:模块系统。

  • 模块作用域

  • 使用require方法来加载模块

  • 使用exports接口对象来导出模块中的成员

  • exports.add = add 这样做的目的是为了解决变量命名冲突的问题

  • exports是一个对象,我可以通过多次为这个对象添加成员实现导出多个属性或者方法

  • exports.str = ‘hello’ 这种方法只能导出对象组

  • 如果一个模块需要直接导出某个成员,而非挂载的方式,可以直接module.exports = 方法名

  • 尝试:exports = add 我们可以认为在每个模块的最后return了这个exports ,但是实际情况这种方法是行不通的

加载 require

语法:
var 自定义变量名称 = require(‘模块’)
两个作用:执行被加载模块的代码,得到被加载模块中的express导出接口对象

导出 exports

node是模块作用域,默认文件中所有的成员旨在当前文件模块有效
对于希望可以被其他模块访问的成员,我们就需要把这些工改的成员都挂载到exports接口对象就可以了

  • 导出多个成员(必须在对象中)
    1
    2
    3
    exports.a = 123
    exports.b = 'hello'
    exports.c = function(){}
  • 导出单个成员(拿到的就是函数、字符串、数组)
    1
    module.exports = 'hello'
    注意:以下情况会覆盖 :
    1
    2
    module.exports = 'hello'
    module.exports = function(){}
    这种情况下,后者会覆盖前者

也可以导出多个成员

1
2
3
4
5
6
module.exports = {
add:function(x,y){
return x+y
},
str:'hello'
}

在node中每个模块内部都有一个自己的module对象
在该module对象中,有一个成员叫exports
也就是说如果需要对外导出成员,只需要把导出的成员挂载到module.exports上

1
2
3
4
5
6
7
8
9
var module ={
exports:{
foo:'bar'
}
}


//上述代码等同于下面这一句
exports.foo = 'bar'//等同于module.exports.foo = 'bar'

谁来require我,谁就得到module.exports
默认在代码的最后有一句:

1
return module.exports

由于每次导出接口成员的时候都通过module.exports.xxx = xxx的方式来导出比较麻烦,所以专门提供了一个变量exports等于module.exports,也就是在模块中还有这样一句代码:

1
2
3
var exports = module.exports

console.log(exports === module.exports)//true

由于最后返回的是module.exports,所以直接给‘exports = add’类似这样赋值是不管用的,因为对象是引用类型,赋值是直接类型,因为最后return的是module.exports,不是exports,所以给exports重新赋值不管用,一旦改变exports的值(或者是引用地址的改变的话),此刻exports就不再指向module.exports了,也就是后续再给exports赋值的都不能返回给require引用接口看

给exports赋值会断开和module.exports的引用,给module.exprts也会断开跟exports的引用,这两个都是一个对象,我们一开始是让这两个对象相等,即这两个对象的地址指向同一个堆内存,当给其中任意一个对象重新赋值的时候,都会断开和彼此的联系,从而这个时候只要记得最终return的是module.exports,只看该对象指向的堆内存所存的内容就可以了。

真正使用的时候:
导出多个成员:exports.xxx = xxx
module.exports = {

}

导出单个成员:module.exports

小总结:

  • 每个模块中都有一个module对象
  • 每个module对象都有一个exports对象
  • 我们可以把需要导出的成员都挂载到module.exports接口对象中
  • 也就是module.exports.xxx=xxx的方式
  • 但是每次都module.exports.xxx=xxx比较麻烦
  • 所以node为了方便,同时在每一个模块中提供了一个成员 叫exports
  • module.exports === exports的结果为true
  • 当一个模块需要导出单个成员的时候,必须要module.exports = xxx
  • 不要使用exports = xxx
  • 因为每个模块最终向外return的是module.exports
  • exports只是module.exports的一个引用
  • 所以即便给exports = xxx重新赋值,,也不会影响module.exports
  • 但是有一种赋值方式比较特殊:exports = module.exports这个用来重新建立引用关系的连接

require加载规则

优先从缓存中加载,不管什么时候、谁加载过需要require的代码,只要加载过了该模块,则都会从缓存中加载,不会重新加载代码。

  • require(‘模块标识’) ==>模块标识由核心模块、第三方模块、自己写的模块三部分
  • 如果是非路径形式的模块表示 (foo.js、)
  • 路径模式的模块: ./(当前目录)、../、/xxx (很少用),首位的/表示当前文件模块所属磁盘根路径,.js后缀名可省略
  • 核心模块的本质也是文件,不过已经编译到二进制文件中了,我们只需要使用名字来加载就可以了
  • 第三方模块,凡是第三方模块都必须通过npm来下载,使用的时候就可以通过require(‘包名’)的方式来进行加载才可以使用
  • 不可能有任何一个第三方包和核心模块的名字是一样的
  • 既不是核心模块也不是路径形式的模块,先找到当前文件所处目录中的node_modules目录,然后再去该目录中查找该包名对应的文件夹名,然后再在该文件夹中查找package.json文件并进入查看main属性,main属性中就记录了该模块的入口模块,然后加载使用这个第三方包,实际上最终加载的还是文件
  • 如果package.json文件不存在或者main指定的入口模块也没有,则node会自动找该目录下的index.js
  • 也就是说index.js会作为一个默认备选项,当前面的入口和文件不存在的时候,就会从该文件进入
  • 如果以上任何一个条件都不成立,则会进入上一级目录中的node_modules目录查找,查找方式和顺序同上
  • 如果上一级也没有,则继续往上上一级查找。。。。以此类推
  • 如果知道当前磁盘根目录还找不到,最后报错:can not find module xxx
  • 注意:一个项目只有一个node_modules文件夹,放在项目的根目录,这样的话项目中的所有子目录都能引用··
    不会出现多个node_modules

小总结

  • 模块查找机制:优先从缓存中加载>>核心模块>>路径形式的文件模块>>第三方模块
    • node_modules/art-template/
    • node_modules/art-template/package.json
    • node_modules/art-template/package.json main
    • index.js 备选项
    • 进入上一级目录查找node_modules
    • 按照这个规则依次往上查找,直到根目录找不到在报错。
    • 一个项目只有一个node_modules文件夹,放在根目录,方便所有子目录的引用,兄弟之间不能引用node_modules中的第三方模块,但是可以通过路径方法引用自己手写的的模块

package.json包说明文件

  • 用来描述这个项目依赖的模块和安装包或者一些信息和相关信息
  • 建议每一个项目都要有一个package.json文件,包描述文件,就像产品的说明书一样。
  • 这个文件可以通过npm init的方式来进行初始化
  • npm install –save xxx,会生成一个package安装包
  • 目前来说,dependences选项,可以用来帮我们保存第三包的依赖信息
  • 建议每个目录的根目录小都有一个package文件
  • 安装的时候–save就是为了安装package,目的是用来保存依赖选项信息
  • 如果node_modules删除了也不用担心,我们只需要:npm install就会自动把package.json中的dependencies中的所有依赖项都下载回来(作用)

npm

  • node package manager
  • 两个含义:npm网站和npm命令行工具

网站

npmjs.com,npm的官方网站

npm命令行工具

  • npm –version 查看npm版本号
  • npm install –global npm 升级npm

常用命令

  • npm init(初始化),npm init -y可以跳过向导,快速生成
  • npm install 安装,只下载
  • npm install –save 下载并且保存依赖项(package.json文件)
  • npm uninstall,只删除,如果有依赖会依然保存
  • npm uninstall –save,删除的同时也会把以来信息去除(npm un-S)
  • npm help 查看帮助
  • npm命令 –help 查看指定命令的帮助

常用几个参数

  • -g 将模块安装到全局环境,安装以后就可以在终端命令直接使用,作为命令使用,如果不是安装到全局则是安装到本地(局部),这种时候,就不能作为命令来使用,要引用的时候只能通过模块来引用require
  • –save将魔魁啊安装到项目node_modules目录下,并在package.json的dependencies节点写入依赖
  • –save-dev:将模块安装到项目node_modules目录下,并在package.json的devdependencies节点写入依赖
  • –production值下载dependencies节点下的依赖

dependencies节点的依赖为运行时依赖,时i项目运行时必不可少的部分,例如引入jquery、express
devdependencies节点的依赖为开发时依赖,在项目正式上线后,可以不需要。例如webpack,只有在开发编译时用到,正式环境使用的都是打包后的代码了。less加载器因为正式环境使用的是编译后的css。

换句话说,–save安装的都是底层必须的依赖,没有这些依赖项目就无法进行。二–save-dev安装的就只是开发依赖,正式环境中没有并不影响功能。

解决npm被墙问题

npm存储包文件的服务器默认在国外,有时候会被墙,速度很慢。
http://npm.taobao.org,cnpm,即淘宝的团队把npm在国内做了一个备份
安装的时候,直接把npm替换为cnpm就可以了。
在任意目录下执行都可以。

  • npm config set registry https://registry.npm.taobao.org,只要经过可该命令的配置,则以后的所有npm install都会默认通过淘宝服务器来下载
  • 通过npm config list来查看是否配置成功

Express

·原生的http在某些方面表现不足以应对我们的开发需求,所以我们就需要使用框架来加快我们的开发效率,框架的目的就是提高效率,是我们的代码更加高度统一
·官方网站首页:expressjs.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//0 安装
//1 引包
var express = require('express')
//2.创建服务器的应用程序,也就是原来的http.ANGLE_instanced_arrays
var app = express()

//当服务器收到get请求/的时候,执行回调函数,和原来的server.on()方法相同
app.get('/',function(req,res){
res.send('hello express!')
})

//req.query,直接用该方法就可以来获取查询字符串参数,返回的是一个对象

app.get('/about',function(req,res){
res.send('你好,我是express')
})

//类似于server.listen()
app.listen(3000,function(req,res){
console.log('app is running at port 3000')
})


//在express中开放引擎就是一个API的事
//公开指定目录
//只要这样做了,就可以直接通过/public/xx的方式访问public目录中的所有资源了
app.use('/public/',express.static('./public'))
app.use('/static/',express.static('./static'))
//以上的两个文件夹由于公开了,所以以上两个文件夹都能被访问了,但是其他文件夹就不可以被访问
-------------本文结束感谢您的阅读-------------