node.js
用到node的地方
-
基于node环境安装babel
es6转es5 es6中:变量 let const
模板字符串 `` ----拼接字符串
数组 map,foreach …
使用()=>{} 改变 this指向
class extends
2.工具-------自动化构建工具 gulp , webpack ,grunt
gulp--构建项目 npm init,压缩处理;gulpfile.js task default watch dist pipe
依赖于丰富的插件 sass uglify ......等等
webpack--构建项目,整合模块,把浏览器不识别的语言babel转换成识别的语言 ;
webpack.config.js entry output module - rule plugins devServer(热更新)
依赖于丰富的加载器loader css style babel url file
3.工具 - 包管理器 npm cnpm yarn
npm install xxx -g / npm i xxx -g 串行 一个接一个 安装比较慢,信息全部打印 , npm i xxx --save-dev/-D/-S
yarn add xxx -g 并行 同时安装 速度快;安装信息以emojis展示
版本管理工具 git–分布式 svn–集中式
4.模块化开发规范 AMD CMD Commonjs
AMD 异步加载规范 提前引入 require.js
CMD 标准通用规范 按需引入 sea.js
commonjs 谷歌提供的规范 核心 模块的接收与暴露
node.js是什么
node.js是一个javascript 运行环境,Node.js使用了一个事件驱动、非阻塞式 I/O的模型,使其轻量又高效。Node.js的包管理器npm,成为世界上最大的开放源代码的生态系统。简单说:编写高性能网络服务器的javascipt工具包(用于js开发服务端程序)
事件驱动:用以决策的一种策略;跟随当前时间点上出现的事务,调用一切可调用的资源,来解决该事务,防止事务堆积
测试 测试工具 黑盒 白盒
联调 前后端数据对接
调试 浏览器控制台
黑盒:功能测试
白盒:源码测试,主要测试的是API
node.js的特点
单线程,异步,事件驱动,快、耗内存多
node.js的作用
可以解析js代码(没有浏览器安全级别的限制),提供很多系统级别的api,如:文件的读写、进程的管理、网络通信。。。。
node的优缺点
优点:性能高,开发效率高,应用范围广
缺点:中间件少(函数),IDE不完善
node中比较热门的框架
Express(Sails),koa,Hapi
HapiExpress:完善、稳定、文档全、社区大
koa :超前
Hapi:复杂(一个简单的helloworld都要做很多堆砌),适合复杂的大型项目
node版本说明
LTS :长时间支持版ben
Curent : 最新版本
eg: v6.8.x 表示第几次发布的版本的,第几次重大修改的,第几次小修改
用node搭建服务器
案例--------基本的服务器搭建
首先分析:服务器需要有:协议,域名/主机,端口号 path
//1.引入http模块----搭建服务器的时候使用的是node中的http模块
var http=require('http');
//创建服务
http.createServer((req,res)=>{
//设置头部信息 writeHead 三个参数(状态码,头部,fc)
res.writeHead(200,{'content-type':'text/html;charset=utf-8','Access-Control-Allow-Origin':'*'});
//对请求路径过滤
if (req.url!='/favicon.ico'){
res.write('你好');
res.end();
}
//监听端口号
}).listen(3000,()=>{
console.log('启动成功');
})
//创建完毕后,就可以进行测试
//当引入自定义模块时: ./ 不能少表示当前目录
自定义模块需要暴露内容 eg: module.exports=obj;
eg: var obj=require(’./comm’);
数据可以写死数据,也可以引入文档数据,还就可以写获取的外部接口数据
eg: comm.js模块
var fs=require('fs');
const https=require('https');
//数据可以写死数据,也可以引入文档数据,还就可以写获取的外部接口数据
var obj={
'index':function (req,res) { //死数据
res.write('index');
res.end();
},
'about':function (req,res) {
res.write('about');
res.end();
},
'home':function (req,res) { //文档数据
fs.readFile('./app.html',(err,data)=>{
res.write(data);
res.end();
})
},
'douban':function (req,res) { //外部数据
const options = {
hostname: 'api.douban.com',
port: 443,
path: '/v2/movie/top250',
method: 'GET'
};
var str=''
var str1=''
const reqq = https.request(options, (a) => {
a.on('data', (d) => {
str+=d;
});
a.on('end',()=>{
str1=str
res.write(str1)
res.end()
})
});
reqq.on('error', (e) => {
console.error(e);
});
reqq.end();
}
}
module.exports=obj;
热更新
安装 npm install supervisor -g
启动 supervisor xxxx.js
可以不用执行node,自动更新(supervisor)
node中的模块划分
内置/原生模块,依赖模块 (–save–dev) ,自定义模块
NODEJS–API
使用方法:1.都是先引入 2.再去使用api中的方法
node中的api都可以在node的REPL命令窗口中调试 直接 命令行 运行node 退出环境ctrl+c 按2次就退出了
REPL(交互式解释器):可以执行一下任务
- 读取 - 读取用户输入,解析输入了Javascript 数据结构并存储在内存中。
- 执行 - 执行输入的数据结构
- 打印 - 输出结果
- 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
http-----
url ----网址
先引入, --------var url=require(‘url’);
url.parse(urlString)查询url信息
url.format(urlObject)将信息解析成正常的url地址
url.resolve(from, to)将两个url解析成一个完整的url from通常根url前 to通常跟path路径
querystring ----查询字符串
先引入------var querystring=require(‘querystring’);
querystring.escape(str)解析对象,字符串(汉字)
querystring.parse(str[, sep[, eq[, options]]])转换成对象
querystring.stringify(obj[, sep[, eq[, options]]])转换成字符串
querystring.unescape(str)解析escape转换的编码,解析成汉字
events ----事件
使用方法
var EventEmitter=require('events'); //引入events模块
class Person extends EventEmitter{}; //创建类去继承它
var person=new Person();
person.on('play',(data)=>{
console.log(data); //获得推送的信息
})
person.emit('play','hello'); //使用emit推送
fs(file system)-----文件系统
引入 -----var fs = require(‘fs’);
1)stat()
获取文件的一些信息 isFile()
2)mkdir()
新建目录
3)writeFile(url,con,fc)
写文件
4)appendFile(url,con,fc)
追加文件内容
5)读取文件的内容:readFile(url,fc)
6)读目录:readdir
-------------得到的是数组(存放的设计文件名)
7)重命名目录或文件:rename
8)删除目录与文件:rmdir
(目录–空目录),unlink
(文件),readdirSync(src)
同步读取目录信息
//删除有文件的目录----也可以用readdirSync(src)
fs.readdir('./log',(err,data)=>{ //错误优先
data.map(function (item) {
fs.unlink('./log/'+item,()=>{
fs.rmdir('./log',()=>{
console.log('success');
})
})
})
})
https ------request–get (注意这个是https)
https请求端口为443,options需要配置头部信息
eg:请求豆瓣数据
//https-request get
const https = require('https');
const http=require('http');
//hostname 是http://后面的一个域名或地址
//path 写的是请求的那个路径
const options = {
hostname: 'api.douban.com',
port: 443,
path: '/v2/movie/top250',
method: 'GET'
};
var str='';
var str1='';
const reqq = https.request(options, (r) => {
r.on('data', (d) => {
str+=d;
});
r.on('end',()=>{
str1=str;
})
});
reqq.on('error', (e) => {
console.error(e);
});
reqq.end();
http.createServer((req,res)=>{
res.writeHead(200,{'content-type':'text/html;charset=utf-8'})
if(req.url!='/favicon.ico'){
res.write(str1)
res.end()
}
}).listen(3000)
http---------request—post (这个是http)
http请求端口为80
eg:利用node提交数据到千锋扣丁学堂
const http=require('http');
const querystring=require('querystring');
//数据格式 在network中的form data 中
const postData = querystring.stringify({
'question[title]': null,
'question[content]': '<p>66666赞</p>',
'question[courseId]': 227,
'question[lessonId]': 1741,
'_csrf_token': 'e657806e247023c0b45b79384f22cb05b983f44e'
});
//参数header在request header中
const options = {
hostname: 'www.codingke.com',
port: 80,
path: '/ajax/create/course/question',
method: 'POST',
//设置头部信息(在request Header中)
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,la;q=0.7',
'Connection': 'keep-alive',
'Content-Length': postData.length,
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': '53gid2=10102158761003; 53revisit=1511193123440; Hm_lvt_9f92046de4640f3c08cf26535ffdd93c=1521162177; UM_distinctid=163ca83f8702ce-05bff3563048af-336b7704-fa000-163ca83f8728d7; tgw_l7_route=ba4a4fa767ccc5ac6060ead23a114820; PHPSESSID=pgar8cied6kjv5uf5caaak6ht0; CNZZDATA1256018185=1397412700-1511191153-%7C1539046694; Invite_code=295463; Hm_lvt_7d5fe787f1dd300413ad4b53656dc0b1=1537235704,1539050531; visitor_type=old; 53gid0=10102158761003; 53gid1=10102158761003; 53kf_72165667_from_host=www.codingke.com; 53kf_72165667_land_page=http%253A%252F%252Fwww.codingke.com%252F; kf_72165667_land_page_ok=1; 53uvid=1; onliner_zdfq72165667=0; 53kf_72165667_keyword=http%3A%2F%2Fwww.codingke.com%2F; Hm_lpvt_7d5fe787f1dd300413ad4b53656dc0b1=1539050579',
'Host': 'www.codingke.com',
'Origin': 'http://www.codingke.com',
'Referer': 'http://www.codingke.com/v/1741-lesson',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'X-CSRF-Token': 'e657806e247023c0b45b79384f22cb05b983f44e',
'X-Requested-With': 'XMLHttpRequest'
}
};
const req = http.request(options, (res) => {
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
nodejs路由
什么是路由:端到端路径的网络范围的进程
前端路由:路由是根据不同的 url 地址展示不同的内容或页面
后端路由:根据不同的URL对应不同的数据,主要用来写后台接口
mongoDB
mongoDB的安装
window安装:
1/把mongodb安装到某一个盘符下(D)
2/创建数据目录 D:data/db文件夹
3/找到mongodb文件夹下的bin文件夹打开mongod.exe
4/双击打开mongo.exe
5/浏览器输入127.0.0.1:27017测试安装成功
使用时—先打开mongod.exe-----再打开mongo.exe
Mac 系统安装
一、安装在Mac OS上面安装MongoDB,你可以通过编译源代码来安装 ,也可以在Mac OS上使用Homebrew安装。这里介绍使用Homebrew安装MongoDB。首先更新Homebrew的package数据库:
$ brew update
$ brew install mongodb
二、启动MongoDB
$ mongod --config /usr/local/etc/mongod.conf 或sudo mongod
三、使用MongoDB
$ mongo
mongoDB的介绍
MongoDB是一个基于分布式文件存储的数据库,是世界上目前用的最广泛的nosql (not only sql 不仅仅是sql)数据库,是一个非关系型数据库
**特点:**高性能、易部署、易使用,存储数据非常方便。
优缺点:
具体指令操作看ppt吧
NodeJS连接MongoDB
mongodb是依赖模块需要安装
npm init
npm i mongodb@2 --save--dev
安装完成后
1/引入mongodb依赖在项目中-------var mongodb=require(‘mongodb’);
2/创建数据库连接服务-------mongodb.Server()
3/数据库连接--------Var db=mongodb.Db()
4/测试链接--------db.open()
eg:
//连接mongodb
var mongodb=require('mongodb');
var server=new mongodb.Server('localhost',27017,{auto_reconnect:true});
var db=mongodb.Db('aa',server,{safe:true});
db.open((err,db)=>{
console.log("connect");
db.collection('bb',(err,coll)=>{
// 查询数据 //toArray()的作用去掉冗余数据
coll.find({}).toArray((err,data)=>{
obj.data=data;
db.close(); //关闭数据库
})
db.close(); //关闭数据库
})
})
##express
//npm i xxx -g 全局环境 (只需安装一次) -- 项目依赖需要依靠的环境
//哪个项目用 哪个项目都要安装 依赖 npm i xx --save-dev/-D/-S
express的使用
1/全局安装环境 npm install express –g
2/安装npm install express-generator –gnpm i express -D
3/安装本地依赖:npm i express -D
express 的路由----------应用路由和路由级别路由
应用路由:
var express=require('express');
var app=express()
//应用级别
app.get('/',(req,res)=>{
// res.write('hello')
// res.end()
res.send('hi')
})
app.get('/home',(req,res)=>{
res.send('home')
})
app.listen(3000)
路由级别:
var express=require('express');
var app=express(); //创建服务
//路由级别
//创建路由
var router=new express.Router();
router.get('/',(req,res)=>{
res.send('hello');
})
router.get('/index',(req,res)=>{
res.send('index');
})
app.use('/',router); //将路由挂载到服务上
app.listen(3000); //监听端口号
小贴士:不同内容挂载到不同路径下
app.use(’/’, index);
app.use(’/users’, users);
脚手架(应用生成器)创建项目
在命令行中执行: express -e project_name(项目名)
,会生成一个项目目录
根据提示信息进行操作eg:
可以在package.json的scripts添加"dev": “supervisor ./bin/www”—实现热更新
如果没有提示怎么办?
找到该目录下的package.json文件 ---------> scripts —>start-对应有操作命令
运行:npm run start (scripts下的key名)
执行package.json中的scripts下的命令都是 npm run key名
Package.json依赖解释
body-parser 对http请求体进行解析
cookie-parser 对cookie进行解析的
debug 输出debug信息
ejs javascript模板引擎
morgan 在控制台上显示request url 信息
serve-favicon: 解决默认请求favicon.ico问题
EJS是一个简单高效的模板语言,通过数据和模板,可以生成HTML标记文本。可以说EJS是一个JavaScript库,EJS可以同时运行在客户端和服务器端,客户端安装直接引入文件即可,服务器端用npm包安装
express写项目的具体步骤
-----------eg:注册页面(我的注册页面用的是login.ejs)
1.通过 express -e project_name(项目名)
创建好项目目录之后
2.在 --views --文件夹下创建登录页面 -----login.ejs
样式:
<input type="text" id="uname" placeholder="用户名" />
<input type="text" id="pwd" placeholder="密码" />
<input type="button" id="btn" value="注册"/>
js代码:
$("#btn").click(function(){
$.ajax({
type:"post",
url:"/users/login",
data:{usename:$("#uname").val(),pwd:$("#pwd").val()},
success:function(data){
console.log(data);
if(data==1){
alert("1秒后跳转登录页面");
setTimeout(function(){
location.href="/deng";
},1000)
}else{
alert("用户名已存在");
location.href="/login";
}
}
})
})
3.在–routes–文件夹下index.js 渲染
渲染一般是在index.js文件中添加渲染
router.get('/login', function(req, res, next) {
res.render('login', {});
});
4.在----routes --文件下的users.js 添加路由处理数据
//引入之前先安装mogodb的本地依赖
快速启动服务
var mongodb=require('mongodb').MongoClient;
var db_str='mongodb://localhost:27017/aa';
添加longin的路由,处理login的数据------将数据插入到mongodb数据库中
//处理login的数据
router.post('/login',(req,res)=>{
console.log(req.body); // req.body获取post数据
//req.query获取get数据
mongodb.connect(db_str,(err,db)=>{
db.collection('aa',(err,coll)=>{
//如果用户名已经存在,不能进行注册
coll.find(req.body).toArray((err,data)=>{
if(data.length==0){
coll.insertOne(req.body,()=>{
res.send("1");
})
}else{
res.send("0");
}
db.close();
});
})
})
});
模板引擎
**概念:**EJS是一个简单高效的模板语言,通过数据和模板,可以生成HTML标记文本,EJS可以同时运行在客户端和服务器端,客户端安装直接引入文件即可,服务器端用npm包安装。
特点:
快速编译和渲染
简单的模板标签
自定义标记分隔符
支持文本包含支持浏览器端和服务器端
模板静态缓存支持express视图系统
常用标签:
<% %>流程控制标签
<%= %>输出内容标签(原文输出HTML标签)
<%- %>输出标签(HTML会被浏览器解析)
<%# %>注释标签
% 对标记进行转义
<%- include(path) %> 引入 path 代表你引入其他模板的路径
Eg:<%- include(‘head.ejs’) %>
路由跳转: res.redirect("/")
session
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以
session的使用:
1.安装
npm install express-session -g ----全局安装
npm install express-session -D -----本地安装依赖
2.在app.js 的文件中配置session
var session=require('express-session') //引入
代码加在挂载之前
app.use(session({
secret: 'recommend 128 bytes random string',
cookie: { maxAge: 20 * 60 * 1000 },
resave: true,
saveUnintialized: true
}))
3.存sesstion,添加代码:----- req.session.name=data[0].username
将数据存储在session中 req.session.名=数据;
4.销毁session
1)req.session.username = undefined;
2)
req.session.destroy((err)=>{ //可以在销毁后跳转路由
res.redirect('/') //路由跳转
})
session与cookie
cookie数据存放在客户的浏览器上,session数据放在服务器上。cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session。session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE。单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
express中 id 查询 --------mongodb中的id存储是用ObjectI包着的,使用的使用应该转换一下
引入: var ObjectId = require(‘mongodb’).ObjectId;
id = ObjectId(req.query.id);
async -----异步流程控制
1)安装该模块
1、npm init 2、npm i async -D
2)串行无关联 async. series()
1、做两个串行的异步请求,无关联,无论什么时候返回,都能拿到结果
2、总的事件执行时间和为几个事件执行时间之和
3、series串行方法=>第一个参数传入数组/对象,数组/对象内传入n个异步方法,第二个参数 对一系列方法的结果处理
3)并行无关联 async. parallel ()
两个并行(两个同时执行)的操作,没关联--时间为某个事件执行的最长时间4)
4)串行有关联 async.waterfall()
获取请求数据的方式:
req.query(get方式)
req.body(post方式)
富文本编辑器 ----------笔记待改善
1、把文件放入指定的位置
2、在需要使用的页面引入js
socket
网络上的两个程序通过一个双向的通信链接实现数据的交换,这个链接的一端称为一个socket
基于net 模板实现通信
Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法
案例: server.js ------服务端
//socket的通信
var net=require('net');
var server=new net.createServer();
var obj=new Object();
var i=0;
server.on('connection',(client)=>{
client.name=++i;
obj[client.name]=client;
client.on('data',(data)=>{
// console.log("sever shou dao")
say(data,client)
})
})
function say(message,client){
for(let i in obj){
obj[i].write(client.name+"说"+message)
}
}
server.listen(3000);
client.js -----客户端
nodejs中实现IO交互使用的是readline模块
var net=require('net');
var client=new net.Socket();
var readline=require('readline'); //实现标准输入输出的模块,可以以逐行的方式读取数据流
var port=3000;
var hostname="localhost";
client.connect(port,hostname,()=>{
client.write('hello 上线了');
})
client.on('data',(data)=>{
console.log(data);
say()
})
//创建readline实例
var r1=new readline.createInterface({
input:process.stdin,
output:process.stdout
})
function say(){
r1.question("请输入内容:",(str)=>{
client.write(str);
})
}
websocket ----实现通信
WebSocket是html5新增加的一种双工通信协议,目前流行的浏览器都支持这个协议
使用方式:
使用之前先进行安装------websocket(包名是 ws )
安装npm init 初始化一个package.json
安装本地依赖 npm i ws -D
案例 服务端js
//websocket的通信-------h5通信
var ws=require('ws').Server;
var server=new ws({port:3000})
var obj=new Object();
var i=0;
server.on('connection',(client)=>{
client.name=++i;
obj[client.name]=client;
client.on('message',(data)=>{
// console.log("sever shou dao")
say(data,client)
})
})
function say(message,client){
for(let i in obj){
obj[i].send(client.name+"说"+message)
}
}
客户端 -----写在html页面里面的
<script>
//创建客户端
var client=new WebSocket('ws://10.8.154.71:3000');
//客户端和服务端连接成功,就会触发onopen事件
client.onopen=function(){};
//当客户端接收到WebSocketServer发送过来的数据时,就会触发onmessage消息
client.onmessage=function(data){
console.log(data);
document.getElementsByClassName("box")[0].innerHTML+=data.data;
};
document.getElementById("btn").onclick=function(){
//向服务器发送数据,用的websock中的send方法
client.send(document.getElementById("txt").value);
}
</script>
websocket知识点
new WebSocket(“ws://echo.websocket.org”);
申请一个WebSocket对象,参数是需要连接的服务器端的地址
WebSocket对象一共支持四个消息 onopen, onmessage, onclose和onerror。
当Browser和WebSocketServer连接成功后,会触发onopen消息;
如果连接失败,发送、接收数据失败或者处理数据出现错误,browser会触发onerror消息;
当Browser接收到WebSocketServer发送过来的数据时,就会触发onmessage消息,参数evt中包含server传输过来的数据;
当Browser接收到WebSocketServer端发送的关闭连接请求时,就会触发onclose消息。
我们可以看出所有的操作都是采用消息的方式触发的,这样就不会阻塞UI,使得UI有更快的响应时间,得到更好的用户体验
mocha 测试
使用方法
1、全局安装:npm install --global mocha
2、npm init 生成package.json文件
package.json的基本配置 : { “name”: “mocha-demos”, “version”: “1.0.0”, “description”: “”, “main”: “index.js”, “scripts”: { “test”: “echo “Error: no test specified” && exit 1” }, “keywords”: [ “testing”, “Mocha” ], “author”: “”, “license”: “MIT”, “devDependencies”: { “babel-core”: “~6.2.1”, “babel-preset-es2015”: “~6.1.18”, “chai”: “~3.4.1”, “mocha”: “~2.3.4”, “mochawesome”: “~1.2.1” }, “dependencies”: { “node-fetch”: “~1.3.3”, “superagent”: “~1.4.0” } }
3、npm install (根据package的配置安装依赖)
4、测试脚本的编写 (测试文件的命名:add.test.js -->测试add.js)
案例:
引入断言库------chai
//断言库
var chai=require('chai')
//断言风格 expect should assert
var expect=chai.expect;
var add=require('../add')
//import add from '../add' //es6
//测试套件
describe('加法测试',function(){
// 测试用例
it('1+0=1',function(){
expect(add(1,0)).to.be.equal(1)
})
it.skip('1+2=3',function(){
expect(add(1,2)).to.be.equal(3)
})
it('true 为真',function(){
expect(false).to.not.be.ok;
})
})
//关于mocha的具体使用方法可以参照袁老师的日志
网址:http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html