2020-11-29

node进阶第一天总结

目标
什么是nodejs的模块化

npm的使用

使用第三方模块

node中的自定义模块

模块查找规则

模块化开发:MVC架构
程序开发中的模块及好处
封装到一个单独的文件中去,这些单独抽离出来的代码文件叫做程序中的模块化。
好处:保证了每个文件的功能(职能)单一;需要什么特定的功能,直接调用某一个特定的模块;对将来程序开发和维护都有好处!
Node 中的模块的分类
node由三部分组成:ECMAScript + 核心模块 + 第三方模块
核心模块
模块,编译成了二进制可执行文件,打包到了Node的安装包(随着node安装到本地)。
使用核心模块使用require(‘核心模块的名称’);
第三方模块
别人做好的我们可以下载这些模块开发中会使用很多第三方模块
npm的使用
(俗称下包)通过npm我们可以下载项目中所需要的第三方模块
nrm(换镜像源提高效率)
1.安装:

npm install -g nrm

2.查看当前及所有可用的源

$ nrm ls
// * 代码当前源
* npm -----  https://registry.npmjs.org/
  yarn ----- https://registry.yarnpkg.com
  cnpm ----  http://r.cnpmjs.org/
  taobao --  https://registry.npm.taobao.org/
  nj ------  https://registry.nodejitsu.com/
  skimdb -- https://skimdb.npmjs.com/registry

3.切换当前的源

$ nrm use cnpm  // 切换到cnpm

    Registry has been set to: http://r.cnpmjs.org/
npm使用流程(开发是查找对应的文档)
  • 初始化:在当前nodejs项目中执行终端命名: npm init -y
    • 作用:生成一个pachage.json文件,帮你记录当前项目安装了哪些第三方模块及对应的版本号
  • 安装:在当前nodejs项目中执行终端命名: npm install 模块名
    • 安装之后,你的项目目录会新增两个文件node_modulespackage-lock.json
      • node_modules:npm会自动将所有的第三方模块放入这个文件夹中。类似于前端的lib文件夹
      • package.json:npm会自动记录第三方模块的下载地址,下一次安装或更新的时候直接从这个地址下载,速度更快(只是影响以后更新速度,不影响开发)

第三方模块的使用

三步走
1先使用npm下载这个模块
2使用require导入这个第三方模块!(安装导入名字应该相同)
3通过官方文档,试着去使用这个第三方模块!

注意:无论是核心模块、还是第三方模块,都是通过 require来引用这个模块的!

5.一个简单的第三方模块使用的案例

// 这个文件演示一下如果使用第三方模块moment实现日期数据的格式化处理
// 1. 引入moment(引入之前确保这个模块已经正确的下载哦)
const moment = require('moment')

// 2.定义一个日期,现在日期值是未格式化的日期数据
let timeNow = new Date()

// 3.调用moment实现对日期数据的格式化处理
console.log(moment(timeNow).format('YYYY-MM-DD HH:mm:ss')

node中的自定义模块(重点)

定义用户模块(自己添加所需要的)

导出用户模块中的成员(exports)

它是一个对象,我们可以在这个对象上挂载你想暴露的成员。
使用.语法在exports上挂载成员

1定义用户模块

// 我们所创建的js文件就可以认为是一个自定义模块
let obj = {
    name:'jack',
    age:20
}

function sayHi(){
    console.log('我的名字叫:'+obj.name+",我的年龄是:"+obj.age)
}

// 在模块中有一个默认的对象exports,这个对象在在这个模块被引入的时候会自动的返回
// 我们暴露成员的方式就是在这个对象上挂载你想暴露的成员
exports.sayHi = sayHi
exports.aa = obj

2.使用用户模块

// 如何使用用户自定义模块:
// 所有模块想使用都要先引入
// 如果引入一个模块,那么这个模块默认会返回一个对象
let umodule = require('你想引入的模块路径')
umodule.sayHi()

module.exports
这是个对象,可以在对象上挂载你想暴露的成员。
语法:module.exports上挂载成员。
module.exports重置为一个新的对象,对象中就包含你想暴露的成员。

1.定义用户模块

// 我们所创建的js文件就可以认为是一个自定义模块
let obj = {
    name:'jack',
    age:20
}

function sayHi(){
    console.log('我的名字叫:'+obj.name+",我的年龄是:"+obj.age)
}

// 在模块中有一个默认的对象module.exports,这个对象在在这个模块被引入的时候会自动的返回
// 我们暴露成员的方式就是在这个对象上挂载你想暴露的成员

// module.exports.sayHi = sayHi
// module.exports.aa = obj
// 也可以直接使用你想暴露的成员覆盖module.exports
module.exports = sayHi

2.使用用户模块

// 如何使用用户自定义模块:
// 所有模块想使用都要先引入
// 如果引入一个模块,那么这个模块默认会返回一个对象
let umodule = require('你想引入的模块路径')
umodule.sayHi()

global(了解)
相当于浏览器中的window,global是一个全局对象

  • 全局变量污染
  • 暴露的成员不明确:不知道成员是从哪个模块中暴露出去的
  • 成员可能被覆盖
  • 不建议使用

- exports 和 module.exports 的区别(建议使用module.exports)

  1. 通过 module.exports 可以使用 . 的形式追加属性,也可以使用 等号 直接赋值的形式导出成员;
  2. exports 只能通过 . 的形式追加属性;不能使用 等号 直接赋值的形式!
  3. 注意: 在一个 module 中,最终向外暴露的成员,以 module.exports 指向的对象为准!
  4. 在一个模块中,不要混合使用 module.exportsexports

模块查找(加载)规则(了解)

  1. 优先从缓存中加载

  2. 加载核心模块:优先从缓存中加载;如果缓存中没有的话,再去执行加载核心模块!

  3. 用户自定义模块:优先从缓存中加载;如果缓存中没有的话,再去执行加载用户模块!

    用户模块的查找规则:
    如果不写后缀名,则先严格按照给定的文件名去查找模块并加载执行;
    
    
   index   ->  index.js  ->   index.json    ->  index.node(主要看这几步即可)

第三方模块查找规则:

4. 首先,查看项目根目录中有没有 `node_modules` 文件夹
5. 查找 `node_modules` 文件夹中,有没有和第三方模块名称一致的文件夹
6. 在模块对应的文件夹中,查找有没有 `package.json` 这个文件
7.`package.json` 文件中,查找有没有 `main` 属性
8. 如果有 `main` 属性,并且 `main` 属性指向的路径存在,那么就尝试加载这个路径指定的文件!
9. 如果 `package.json` 文件中,没有 `main` 属性,或者 `main` 属性指向的路径不存在,或者没有`package.json` 文件, 那么,Node尝试加载 模块根目录中 `index` 相关文件:`index.js` -> `index.json` -> `index.node`
10. 如果在`node_modules`文件夹中,找不到对应的模块文件夹,或者在项目根目录中根本没有`node_modules`文件夹,则向上一层文件夹中去查找,查找规则同上!
11. 如果上一层目录中也没有查找到,则再向上翻一层去查找,直到找到当前项目所在的盘符根目录为止!
12. 如果找到当前盘符根目录还找不到,则报错:***cannot find module***

案例

搭建案例目录结构

在这里插入图片描述
**#### 在app.js中完成所有的功能

创建服务器**
// 1.引入协议 
const http = require('http')

// 2.创建服务器
const server = http.createServer()

// 3.添加对端口的监听
server.listen(3004, function () {
    console.log('http://127.0.0.1:3004')
})

目中需要使用到的核心模块和第三方模块

const fs = require('fs')
const mime = require('mime')
const querystring = require('querystring')

##### 添加用户请求的监听

完成注册页面的读取并返回
完成静态资源的处理
完成注册功能

html页面

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<title>用户注册</title>
	<link rel="stylesheet" href="/css/index.css">
	<script src="/js/jquery.js"></script>
</head>

<body>
	<div class="register">
		<form id="ajaxForm">
			<ul>
				<li>
					<label for="">用户名</label>
					<input type="text" name="username" class="name">
				</li>
				<li>
					<label for="">密码</label>
					<input type="password" name="password" class="pass">
				</li>
				<li>
					<label for="">手机号</label>
					<input type="text" name="phone" class="mobile">
				</li>
				<li>
					<label for=""></label>
					<input type="button" class="submit " value="立即注册">
				</li>
			</ul>
		</form>
		<img src="/images/timg.gif" alt="">
	</div>
	<script>
		$('.submit').on('click', function () {
			$.ajax({
				type: 'post',
				url: 'http://127.0.0.1:3004/register',
				data: $('#ajaxForm').serialize(),
				dataType: 'json',
				success: function (res) {
					console.log(res)
					if (res.code == 200) {
						alert(res.msg)
						// 跳转到列表页
					} else {
						alert(res.msg)
					}
				}
			})
		})
	</script>
</body>

</html>

app.js页面

// 一般没有特别的需要,服务器的入口文件都是叫app.js

// 引入核心模块
const http = require('http')
const fs = require('fs')
const path = require('path')
// 引入第三方模块
const mime = require('mime')
// 引入自定义模块
const usermodule = require('./js/common')

const server = http.createServer()

server.listen('3004', function () {
  console.log('http://127.0.0.1:3004')
})

server.on('request', function (req, res) {
  // 约定请求形式和请求url
  // 1.响应注册页面 get /register
  // 2.实现注册功能 post /register
  // 获取用户请求方式
  let method = req.method
  // 获取用户请求url
  let myurl = req.url
  console.log(method, myurl)
  // 进行用户请求方式和请求url的判断,从而实现相应的响应
  if (method.toLowerCase() == 'get' && myurl == '/register') {
    // 读取注册页面并响应
    fs.readFile(path.join(__dirname, '/views/register.html'), (err, data) => {
      if (err) {
        res.end('404')
      } else {
        res.end(data)
      }
    })
  }
  // 处理静态资源  /css/reset.css
  // indexOf:查找指定字符串在源字符串第一次出现的索引位置,如果找不到就返回-1
  // myurl.indexOf('/css/') != -1:说明当前的url有/css/,意味着它是一个css请求
  else if (method.toLowerCase() == 'get' && (myurl.indexOf('/css/') != -1 || myurl.indexOf('/js/') != -1 || myurl.indexOf('/images/') != -1)) {
    console.log(path.join(__dirname, myurl))
    // 读取静态资源文件
    fs.readFile(path.join(__dirname, myurl), (err, data) => {
      if (err) {
        res.end('404')
      } else {
        // 响应之前,进行资源的mime类型的设置,明确的告诉客户端文件的类型是什么,方便客户端的处理
        // getType:根据文件的扩展名获取文件的mime类型
        res.setHeader('Content-Type', mime.getType(myurl))
        res.end(data)
      }
    })
  }
  else if (method.toLowerCase() == 'post' && myurl == '/register') {
    // 1.接收参数:node支持传递大容量的参数,为了节省服务器的内存开销,node实行分批接收参数,接收的参数是字符串类型
    let str = '' // 定义一个参数用于存储接收到的参数字符串
    // 1.1 添加data事件,用于分批接收参数--拼接,每次接收到参数就会自动的触发data事件,所以我们可以在data事件拼接接收到的参数.它有一个回调函数,每次接收到参数就会调用这个函数,同时将接收到的参数赋值给chunk
    req.on('data', (chunk) => {
      str += chunk
    })
    // 1.2 添加end事件,当所有参数接收完毕的时候,就会触发end事件,在参数接收完毕之后进行下一步的处理
    req.on('end', () => {
      console.log(str)  // username=saaa&password=sdsafds&phone=fasdfasdfas
      // 2.将参数转换为对象
      let obj = usermodule.getParameter(str) // {}
      console.log(obj)
      // 3.将数据添加到json文件
      // 3.1 读取json文件
      fs.readFile(path.join(__dirname, '/data/users.json'), 'utf-8', (err, data) => {
        if (err) {
          // 这里返回了json格式的字符串
          let ret = {
            code: 404,
            msg: '注册失败'
          }
          res.end(JSON.stringify(ret))
        } else {
          // 3.2 将内容转换为数组
          let arr = JSON.parse(data)
          // 3.3 将新新增数据添加到数组中
          arr.push(obj)
          console.log(arr)
          // 3.4 将添加了新数据的数组重新转换为字符串
          // 3.5 将字符串写入到json文件中
          fs.writeFile(path.join(__dirname, '/data/users.json'), JSON.stringify(arr, null, ' '), (err) => {
            if (err) {
              // 这里返回了json格式的字符串
              let ret = {
                code: 404,
                msg: '注册失败'
              }
              res.end(JSON.stringify(ret))
            } else {
              let ret = {
                code: 200,
                msg: '注册成功'
              }
              res.end(JSON.stringify(ret))
            }
          })
        }
      })
    })
  }
})

common.js(用来去除一些符号直接拿到对象)

module.exports = {
  getParameter: function (str) { // ?id=7&name=jack
    // 删除?
    str = str.replace('?', '')  // id=7&name=jack
    // 分割字符串
    var arr = str.split('&')  // ["id=7","name=jack"]
    // 循环遍历再次分割
    var obj = {}
    for (var i = 0; i < arr.length; i++) { // 1.id=7
      var temp = arr[i].split('=') // ["id",7]
      // 将数据添加到对象
      obj[temp[0]] = temp[1] // {id:7}
    }
    return obj
  }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值