一、软件架构
1.1 C/S(Client客户端/Server服务器端)
- 优点:
- 用户体验感较好
- 运行稳定
- 对带宽的要求低
- 缺点:
- 占硬盘空间
- 更新过于麻烦 - 服务器端和客户端都要更新
1.2 B/S(Browser浏览器端/Server服务器端)
- 优点:
- 几乎不占硬盘
- 更新简单 - 只需要更新服务器端
- 对电脑配置要求不高
- 缺点:
- 用户体验感较差
- 对带宽的要求高
二、Node.js
不是JS,但是语法和JavaScript非常相似,做的功能绝对不是特效!做的事和服务器端其他语言是一致(和数据库进行交互,成为了一个前端到数据库的中间桥梁)
2.1 目的:
- 使用代码搭建一个服务器&文件系统(服务器文件可以放在任何位置,但是不在你的电脑里,你可以根据网址来访问到我的东西)
- Node.js如何沟通前端和数据库
2.2 Node.js安装
- node.js官网下载-安装
- 检查你安装成功没:打开cmd输入:node -v - 查看版本号,如果有版本号代表你已经安装成功!
2.3 Node.js如何运行:3种
- 交互模式 - 临时测试:打开cmd输入:node回车,就可以开始敲你的"js"代码
- 脚本/文件模式 - 正式开发中:先创建xx.js,里面书写自己的代码 -> 打开cmd输入:node 文件的绝对路径
- 安装插件:前提是至少前面两个方式能够成功,才可以安装插件。vscode的插件是code runner:对着文件出右键,第一个选项就是code runner,或者 右上角有一个开始按钮
2.4 js和node的区别
- 相同点:都可以使用一切的ECMAScript的东西包括一切的API都可以使用,在服务器端不存在任何浏览器,所以不必担心兼容问题
- 不同点:
- JavaScript:DOM+BOM - 做特效
- Node.js:有很多的模块
2.5 Node.js最大的特点
- 快、非常快
- 因为官方提供的东西少,甚至连数据库的操作API都没有提供的
- 使用了chrome浏览器的v8引擎
三、模块(module)
每一个xx.js文件,都可以称之为是一个模块
3.1 模块化开发
如果以一个网站来说,我们可以按功能分为很多模块:商家模块、商品模块、促销模块、用户模块、产品模块....
3.2 分工合作
将每个模块交给对应的人,完成,最后再由【主模块】进行引入
- 每一个模块都有一个操作,可以用于公开/暴露自己的成员:exports。Node.js自带的一个预定义变量,可以直接使用,是一个对象,放在此对象里面的东西,就是允许公开的东西
语法:
exports.属性名=属性值;
module.exports={
属性名:属性值,
...
}
console.log(exports);//{}
// 方法一
/* exports.size = function (r) {return Math.PI*r*r}//圆的面积
exports.per = function (r) {return Math.PI*r*2}//圆的周长 */
// 方法二
module.exports = {
size : function(r){return Math.PI*r*r},
per : function(r){return Math.PI*r*2}
}
- 每一个模块(主模块)都有一个操作,可以用于导入/引入其他模块require。Node.js自带的一个预定义变量,可以直接使用,是一个函数,函数中需要书写出引入模块的路径
语法:var x=require("./文件名")
- 语法:
var fz1 = require('./06-分支模块1')
console.log(fz1);//{ size: [Function (anonymous)], per: [Function (anonymous)] }
console.log(fz1.size(2));//12.566370614359172
console.log(fz1.per(3));//18.84955592153876
3.3 exports和module.exports有什么区别
- 语法,写法,用法不同
- 都是用于公开暴露自己的成员的
- 但是exports={},写法是错误的
- 其实Node.js底层有一句话:exports=module.exports
- 其实真正做公开功能的是module.exports
- 如果你使用了exports={};其实是你创建了一个新的空对象,把module.exports覆盖了,所以不在具有公开的功能
四、模块的分类:
4.1 官方模块
不需要下载,在你安装node.js环境的时候就已经带上了,但是某的模块可以需要引入,某的模块可能不需要引入:
- Global模块:不需要引入的,可以直接使用
- __filename - 获取当前文件完整的绝对路径
- __dirname - 获取当前文件的文件夹的绝对路径
- exports - 空对象,可以用于公开暴露自己的成员
- require - 函数,可以用于导入其他模块
- module - 指代当前模块本身,甚至包含着以上4个操作
- 定时器(周期性、一次性、瞬间定时器)
// 周期性定时器 setInterval(function(){ console.log(1); },500) // 一次性定时器 setTimeout(function(){ console.log(2); },1200) // 瞬间定时器 setImmediate(function(){ console.log(3); })
- console
- querystring模块:解析查询字符串,使其变成一个对象,可以获取到前端传到后端的消息
- 需要引入:var qs = require('querystring');
- 作用:解析url查询字符串部分的功能
- var obj=qs.parse("查询字符串");
- 想要获得前端传来的每一个部分:obj.键名;
- 如果前端传来的是一个完整的url网址,他就解析不了了!
const qs = require('querystring') console.log(qs); // 解析字符串 var str = 'name=dy&pwd=123123&vip=1&email=610147162@qq.com'; var obj = qs.parse(str); console.log(obj); console.log(obj.name);//dy
- url模块
- 需要引入:var url = require('url');
- 作用:提供了解析url各个部分的功能
- var objUrl=url.parse("网址",true);//支持第二参数,是一个布尔值,默认为false,一旦设置为true,自动使用querystring模块的parse方法去解析查询字符串部分
- 查询字符串:objUrl.query.键名; - 前端form表单提交传到后端的东西
- 路由/文件相对路径/请求地址:objUrl.pathname - 判断路由的不同,去读取不同的HTML发送给我们的用户看
var url = require('url') // console.log(url); //假设,前端向后端传来的完整网址: var str="https://www.paoge.com:443/new/index.html?name=dy&pwd=123123&vip=1&email=610147162@qq.com"; var obj = url.parse(str,true)//trun代表自动解析查询字符串,可传也可以不传,默认值为false console.log(obj.query.name);//name
- Buffer模块:缓冲区,可以将数据变成一个16进制的数字
var buf = Buffer.from([1,2,3,4,5]) var buf1 = Buffer.from('hello你好') console.log(buf);//<Buffer 01 02 03 04 05> console.log(buf1);//<Buffer 68 65 6c 6c 6f e4 bd a0 e5 a5 bd> console.log(buf1.toString());//hello你好
- fs模块:
- 需要引入:var fs = require('fs');
- 读取文档:
var fs = require('fs') // console.log(fs); // 读取文档 异步 fs.readFile(__dirname+'/public/01.txt',function(err,buf){ console.log(err);//null console.log(buf);//<Buffer e4 bb 8a e5 a4 a9 e6 98 9f e6 9c 9f e4 b8 89> }) // 读取文档 同步 /* var buf = fs.readFileSync(__dirname+'/public/01.txt') console.log(buf);////<Buffer e4 bb 8a e5 a4 a9 e6 98 9f e6 9c 9f e4 b8 89> */ console.log('后续代码');
- 写入文档:
var fs = require('fs') // console.log(fs); // 写入文档 异步 fs.writeFile(__dirname+'/public/01.txt','写入的内容',function(){ console.log('写入完毕后要做什么必须放在这里'); }) // 写入文档 同步 /* fs.writeFileSync(__dirname+'/public/01.txt','写入的内容-同步') console.log('写入完毕'); */ console.log('后续代码');
- 追加文档:
var fs = require('fs') // console.log(fs); // 追加文档 异步 fs.appendFile(__dirname+'/public/01.txt','追加的内容',function(){ console.log('追加完毕后要做什么必须放在这里'); }) // 写入文档 同步 /* fs.writeFileSync(__dirname+'/public/01.txt','写入的内容-同步') console.log('写入完毕'); */ console.log('后续代码');
- http模块:搭建服务器
var http = require('http'); var url = require('url'); var fs = require('fs'); // 创建服务器应用 var app = http.createServer(); // 为其绑定监听端口 http端口默认80 app.listen(8008); // 为其绑定请求事件:http:请求-响应模式,必须要有一个请求,才有一个响应 app.on('request',(req,res)=>{ // req:request(请求)对象,它有一个属性叫做req.url,可以获取到前端传到后端的路由和请求消息,但是路由和请求消息是融为一体的,不方便我们获取某个部分,所有我们引入了url,进行进行解析,分开两个部分 // console.log(req.url);//得到的是路由和请求消息/index.html?name=zs var obj = url.parse(req.url,true) // console.log(obj); // 保存路由 var router = obj.pathname console.log(router); // 判断路由的不同读取不同的页面给用户看 if (router == '/' || router == '/index.html') { fs.readFile('./public/index.html',(err,buf)=>{ //res:response(响应)对象,他有一个方法:res.end(响应的内容) - 可以响应给前端想要的东西 res.end(buf) console.log(1); console.log(err); }) // match方法类似indexOf 但是支持正则 找不到返回null } else if (router.match(/html|css|js|json|ttf|woff|woff2|png|jpg/) !== null) { fs.readFile(`./public${router}`,(err,buf)=>{ res.end(buf) console.log(2); }) } })
4.2 第三方模块
- npm工具:Node Package Manager:Node.js的模块/包管理器,专门用于管理第三方模块的。
- 作用:下载、更新、删除、维护包之间的依赖关系
- 打开网址:npm官网www.npmjs.com/
- 搜索你需要用到的模块:尽量用带有完全符合标签的那个包,或者是 第一个包:(mongoose)
1、打开cmd:检查npm是否安装成功:npm -v
2、在你的项目之中,再打开cmd
3、下载:npm i 包名
4、更新:npm up 包名
5、删除:npm un 包名
4.3 自定义模块
自己书写的xx.js:require("./模块名");
- 文件模块:创建xx.js去公开需要公开的内容,主模块要引入,必须写为require("./模块名");
- 目录模块:3种用法
- 比如创建m1的文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("./m1");
- 比如创建m2的文件夹,在其中创建xx.js的文件,,去公开需要公开的内容,主模块要引入,必须写为require("./m2"),必须再创建一个package.json的配置文件,写入:{"main":"xx.js"};
- 创建一个文件夹必须名为:node_modules,再在其中创建出m3文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("m3");