-
个人入门学习用笔记、不过多作为参考依据。如有错误欢迎斧正
-
目录
好像不支持锚点、复制搜索(反正也是写给我自己看的)
- 浏览器
- javaScript
- 编程语言的能力
- Node
- 安装(Mac)
- 使用
- Node---REPL环境
- 终端命令
- 异步操作
- I/O
- Node多线程
- NPM包管理工具
- nrm
- querystring字符串查询模块
- URL模块
- 制作一个简单的表单提交
- 文件操作
- 模板字符串
- HTTP
- http传输方式
- NET.socket
- 手动实现一个简单的静态资源管理服务
- exports&&require
- node_modules文件夹
- package.json
- Post请求处理(原生)
- 一些工具框架(库)
-
浏览器
1、请求http地址(报文---传输的数据文档)
浏览器的最大作用就是将一个url地址封装成一个请求报文、并解析相应报文。
2、服务器返回的相应报文。
报文内容:
html/css/image = >渲染
js=>解释(执行)js
-
javaScript
脚本语言
浏览器中运行
客户端页面交互实现运行在浏览器内核中的js引擎(engine)下
作用: 1、操作DOM(对DOM的修改、增删改、注册事件) 2、AJAX/跨域 3、BOM对象(页面跳转、历史记录、console.log()、alert()、window对象下的大部分子对象) 4、ECMAScript 不能进行的操作(由于js运行环境处于客户端。影响安全性): 1、文件操作(文件和文件夹的CRUD增删改查) 2、操作系统信息(版本号等)
-
编程语言的能力
所有编程语言本身只提供定义变量、函数、对象、流程控制、循环等操作
能力高低取决于运行该语言的平台(环境)----浏览器
对于js来讲。DOM/BOM等能力均由浏览器引擎提供。
java
既是语言、又是平台。
java运行与java虚拟机(vm)平台上(虚拟机本身可以跨操作系统运行)。C# 平台:.net framework(Windows) 也可以运行于MONO这样的平台(Linux) PHP 既是语言、又是平台
javaScript并不只能运行于浏览器
能运行在哪取决于环境有没有特定的平台
-
Node
- Node.js并不是一种语言。(使用v8引擎+js语法。V8:高效解析js、大部分为异步。node就是将V8中的一些功能移植到了服务器上)
- 一个js在服务端的运行平台(runtime)
- 实际上就是JavaScript的虚拟机
- 是Node选择了支持JavaScript、而不是JavaScript选择了Node。
- 与PHP、JSP、Python等直接运行在服务器程序(Apache、Naginx、Tomcat、IIS)上的不同,Node.js跳过了HTTP服务器、不需要建立在任何服务器软件之上。
- 不同于许多经典架构(LAMP=Linux(操作系统)+Apache(服务器)+MySQL(数据库)+PHP(语言))、有着很大的不同、演变成LMP形式。并不存在web容器(根目录)。�Node部署成功之后、并没有运行服务器、但是Node线程却担当了服务器的作用。
特点
所谓特点、就是node.js如何解决服务器高性能瓶颈问题。
服务器语言(PHP、Java等)会为每一个客户端建立一个新的线程(大约2MB)、理论上一个8GB内存的服务器可以连接4000个用户。
Node只有一个线程、当用户连接时、触发一个内部事件。通过非阻塞I/O、事件驱动机制、让node在宏观上实现并行。使用node.js、一个8GB的服务器可以处理4万用户的链接。单线程:充分利用CPU.
提高链接上限、但是主线程崩溃会出现大面积崩溃。
非阻塞I/O(non-blocking I/O ):
在执行了I/O操作时、会将I/O操作移交磁盘进行物理并发、并立即执行其后面的代码、I/O结束后以事件的形式返回并执行回调。
事件驱动(event-driven):
新用户请求进入、或老用户I/O异步回调返回时、会以事件形式加入事件环、等待调度(回调拥有更高的优先级)。
善于I/O、长连接、不善于计算:
擅长于业务调度(用户表单收集--百度贴吧投诉、考试系统)、如果业务过渡占用CPU进行计算、实际上过多计算会阻塞线程。长连接也是业务调度。
作用:
1、web网站服务器(直接服务器)---比如淘宝
2、web网站请求包装、服务器返回数据分发、渲染HTML页面。(间接服务器)---Node的并发数、抗压性高于传统服务器平台。比如天猫
https://github.com/NetEase/pomelo 网易开源游戏服务端
-
安装(Mac)
条件:
1、xcode(因为内含GCC、python等)
xcode-select -p(可以检查一下)
2、python(有了xcode基本python也具备了)
python -V(区分大小写)
安装Homebrew
ruby -v(安装依赖ruby) www.brew.sh(Homebrew官网)
安装Node.js
brew install node
版本控制
n 7.7.2(下载7.7.2版本的node.js)
- 安装完成之后
n(上下键选择本地版本。回车确定安装)
-
使用
nodejs.org(官方教程)
你需要一个js文件控制服务器行为(例:)
//加载“http”模块。由JavaScript编写、负责创建web服务器、以及处理http相关任务 const http = require('http'); //加载其他js文件。无返回值、直接加载即可。 require('./vue.js') //获取调用者对象 module.parent //ip、字符串 const hostname = '127.0.0.1'; //端口、数字 const port = 3005; //创建服务器 //http.createServer(function(回调函数));添加一个回调函数 //req含有请求相关的信息(来源url、请求类型) //res含有请求响应的内容 //1.返回文字等信息 const server = http.createServer(function(req, res){ res.statusCode = 200; //文本内容类型 res.setHeader('Content-Type', 'text/plain'); res.end('Hello World\n'); }); //2.返回一个html页面 /*不同于Apache。node.js没有web容器的概念、也就是没有文件夹的概念*/ const server = http.createServer(function(req, res){ //node作为跨平台文件、不支持同文件夹下直接index_01.html这种windows写法、必须使用./index_01.html的linux写法 fs.readFile('./index_01.html',(err,data) =>{ res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); if (!err) { res.end(data); }else { res.end('html not found'); } }); }); //3.返回路由页面 const server = http.createServer(function(req, res){ //http://127.0.0.1:3007/index_01.html req.url =/index_01.html //http://127.0.0.1:3007/index_02.html req.url =/index_02.html var url = req.url; //如果你愿意、也可以手写url以隐藏文件路径 //比如 if (req.url == '/lalala') url = '/index_01.html'; fs.readFile('.'+url,(err,data) =>{ res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); if (!err) { res.end(data); }else { res.end('html not found'); } }); }); //让服务器在端口监听请求然后调用上面的函数 server.listen(port, hostname, function() { //成功启动服务器监听时、在控制台打印 console.log(`Server running at http://${hostname}:${port}/`); });
res.end(data);是回调内必须实现的一个函数。
//ES6中匿名函数 function(a){} === (a) => {}
关于路由文件、有个重点
node.js在每一次读取文件时、都会调取一遍createServer的回调
也就是说、内部的图片也需要手动读取。所以:var url = req.url; fs.readFile('.'+url,(err,data)
这样的构成就非常重要。
否则就连图片都需要手动指定文件路径了。
当然。对于node.js。根目录就是js文件所在目录。启动服务器
1.cd到js文件夹目录下 2.node servers.js(启动服务器文件 ) 3.control+c(关闭服务器)
带参数运行脚本
node servers.js 123 asd 123可以通过process.argv[2]获取 asd可以通过process.argv[3]获取 argv[2]||'lalalalal' === argv[2]?argv[2]:'lalalala'
-
Node---REPL环境
//进入REPL环境(类似web控制台、用来测试代码模块)
(控制台)node
node --use_strict//严格模式--直接a = 10;之类会报错
//退出REPS环境
.exit
上次取值替代符号
_ //代表上次所取的值
stdin&&stdout
stdin:采集用户输入
stdout:控制台输出(不带\n的console.log())一个简单的控制台登录demo
var q = '请输入用户名'; var users = { 'user1':'111', 'user2':'222', 'user3':'333' }; process.stdout.write(q+'\n'); var type = 0; var user; process.stdin.on('data',(input) => { //获取keys的数组、并且查找是否含有input内容 input = input.toString().trim(); if (type === 0 ){ if(Object.keys(users).indexOf(input) === -1) { //用户名不存在 process.stdout.write('用户名不存在、'); process.stdout.write(q+':\n'); type = 0; }else { user = input; type = 1; process.stdout.write('请输入密码:\n'); } }else { var pwd = users[user]; if (input === pwd){ process.stdout.write('用户'+user+'登录成功\n'); type = 0; }else { process.stdout.write('密码错误、请重新输入密码:\n') } } });
-
终端命令
输出控制台输出+创建文件
echo 'aaa' >>1.txt
查看文件内容
cat 1.txt
创建一个目录/文件
mkdir dirname
删除文件/目录
rm -rf dirname
-
异步操作
1、网络请求
2、文件操作
-
I/O
input/output
-
Node多线程
1、Node平台将一个任务联通该任务的回调函数放到一个时间循环系统中。
2、事件循环高效的管理系统线程池、同事高效执行每一个任务。
3、当任务执行完成过后自动执行回调函数。Node将所有的阻塞操作、交付给内部线程池。
Node本身主线程主要就是不断的“往返调度”(文件操作、网络请求全部交由其他线程执行)。
Node可以充分利用单核CPU的优势。
-
NPM包管理工具
npm(Node Pack Manager)
npm会随着node的安装、自动安装
Nodejs本身是轻内核、不包含太多的功能。
在开发过程中可能需要引用大量的依赖包(再小的功能都有成熟的模块)
个人开发者制作的功能扩展
https://www.npmjs.com/
require时、有限查找系统模块。
然后才会查找项目中node_modules目录;
查看所有依赖包npm ls
查看深度为0的根包
npm --depth 0
使用
npm install 包名称
-
nrm
可以自动切换npm服务器指向
//安装npm install -g nrm //查看所有可用指向 nrm ls //修改npm指向 nrm use taobao //检测节点速度 nrm test
-
querystring字符串查询模块
querystring.parse字符串 =>字典
const querystring = require('querystring'); querystring.parse('foo=bar&abc=xyz&abc=123'); //return { foo: 'bar', abc: ['xyz', '123'] };
默认情况下,查询字符串中的百分号编码的字符会被认为使用了 UTF-8 编码。 如果使用的是另一种字符编码,则 decodeURIComponent 选项需要被指定,如以下例子:
querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,{ decodeURIComponent: gbkDecodeURIComponent });
-
URL模块
const url = require('url');
url.parse()可以将一个完整的url地址分为很多部分、例如:
var url = req.url; res.write('
'+'url ---> '+url+'
'); //url ---> /p/index_01.html?id=123 res.write(''+'host ---> '+urls.parse(url).host+'
'); res.write(''+'port ---> '+urls.parse(url).port+'
'); res.write(''+'path ---> '+urls.parse(url).path+'
'); //path ---> /p/index_01.html?id=123 res.write(''+'pathname ---> '+urls.parse(url).pathname+'
'); //pathname ---> /p/index_01.html res.write(''+'query ---> '+urls.parse(url).query+'
'); query ---> id=123 //url.parse(urlstr,true).query 可以将参数转化为json对象 var query = urls.parse(url,true).query; res.write(''+'id ---> '+ query.id +'
'); //id ---> 123
-
制作一个简单的表单提交
HTML
Node.js
const http = require('http'); var url = require('url'); var hostName = '127.0.0.1'; var port = 3010; http.createServer((req,res) => { var queryJson = url.parse(req.url,true).query; var name = queryJson.name; var age = queryJson.age; var sex = queryJson.sex; //支持中文显示 res.writeHead(200, { "Content-Type": "text/html;charset=utf-8" }); res.write(`
服务器收到了表单请求
`); res.write(`姓名:${name} 年龄:${age} 性别:${sex}`); res.end(); }).listen(port,hostName,()=>{ console.log(`成功监听 http://${hostName}:${port}/`); });
-
文件操作
文件操作下、必须使用"绝对路径(物理路径)"
fs:
基础的文件操作
//异步(options为编码格式) fs.readFile(path[, options], (err, data) => { if (err) throw err; console.log(data); }); //同步(options为编码格式) try { var data = fs.readFileSync(path[, options]) } catch(error){ }
如不声明编码格式。解析结果会一buffer(二进制缓冲区)格式输出
流的形式读取文件
const fs = require('fs'); const rr = fs.createReadStream('foo.txt'); var dara = ' '; rr.on('data', (chunk) => { //chunk为每次读取出来的文件块 (buffer---字节数组) //chunk.lenth data+=chunk.toString(); }); rr.on('end', () => { console.log('end'); });
buffer:
数据容器。将大文件整个放入缓冲区再分批写入磁盘
//读取 buffer.toString('utf8') //写入(字符串) buffer.write(string[, offset[, length]][, encoding])
path:
提供和路径相关的操作
//获取文件名 path.basename(temp) //获取路径中目录名称 path.dirname(temp) //获取不同系统中路径分隔符、Windows是“;”Linux/MacOS是“:” path.delimiter //获取环境变量 process.env.PATH.split(path.delimiter) //获取路径中后缀(扩展)名/包含"." path.extname(temp) //获取文件信息对象.(文件目录、文件名、扩展名等) var obj = path.parse(temp); //将对象路径转化成字符串 path.format(obj) //判断是否为绝对路径 path.isAbsolute(temp) //拼接路径 path.join([path1],[path2],..) //根据当前系统常规化一个路径 var a = path.normalize('C://dev\\abc//cba////1.txt'); console.log(a); //获取to路径相对于from的相对路径 path.relative(from,to); //通过文件操作获取目录(允许从绝对路径开始) path.resolve(__dirname,'..','./','./code'); //获取当前操作系统中默认用的路径成员分隔符.Windows“\” Linux、MacOS“/” path.sep //判断操作系统win32:windows&&LinuxMacOS:posix //可以通过path.win32//posix改变node操作方式 console.log(path=== path.win32);
readline:
读取大文本/歌词等文件、一行一行读
const readline = require('readline'); const fs = require('fs'); const rl = readline.createInterface({ input: fs.createReadStream('sample.txt') }); rl.on('line', (line) => { //确保每次返回一整行数据 //与createReadStream用流的形式返回buffer不用。 //readLIne直接返回字符串对象 console.log(`Line from file: ${line}`); });
const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: 'OHAI> ' }); rl.prompt(); //用户输入 rl.on('line', (line) => { switch (line.trim()) { case 'hello': console.log('world!'); break; default: console.log(`Say what? I might have heard${line.trim()}'`); break; } rl.prompt(); //用户结束了输入。 }).on('close', () => { console.log('Have a great day!'); process.exit(0); });
文件写入
//只要是文件操作。fs以及path就是必须模块 const fs = require('fs'); const path = require('path'); const data = {id:10}; //文件写入时传入对象data:结果为[object Object] //JSON.stringify(data)序列化:结果为{id:10} //JSON.parse(data)反序列化 //写入、覆盖 fs.writeFile(file, data[, options], callback); //追加 fs.appendFile(file, data[, options], callback); //文件流 var streamWriter = fs.createWriteStream(path.join(__dirname,'temp.txt')); streamWriter.write('hello1',() => { console.log('+1'); }); //同步书写文件 fs.writeSync(fd, string[, position[, encoding]])
pipe()方式copy文件
readStream.pipe(writeStream); writeStream.on('pipe',(src) => { src===readStream; }
pipe()支持链式编程
判断文件是否存在
fs.stat(path, callback(err, stats))
重命名文件或目录
fs.rename(oldPath, newPath, callback); fs.renameSync(oldPath, newPath, callback);
删除文件
fs.unlink(path, callback); fs.unlinkSync(path, callback)
创建文件夹(要求路径必须存在)
fs.mkdir(path, callback);
监视文件变化
fs.watchFile(path.join(__dirname,'temp.txt'),(curr, prev) => { console.log(`previous:${prev.size}`); console.log(`current:${curr.size}`); });
fs-extra(第三方):
https://www.npmjs.com/package/fs-extra
扩展了文件拷贝、删除等操作
-
模板字符串
通过不同的引号来包裹
' 普通字符串------` 模板字符串console.log(` 鹅,鹅,鹅, 曲项向天歌。 白毛浮绿水, 红掌波清波。`); console.log(` this is ${nameHe}, this is ${nameShe}` , nameHe);
-
HTTP
客户端输入url
封装成特定格式(http/https等)的请求报文
通过socket(连接方式)传递给服务端
服务端根据不同协议类型对报文进行解析
。。。。。
客户端接收到服务端返回的报文并加以解析
客户端渲染内容到页面当中
-
http传输方式
PUT:传输文件(增)
DELETE:删除文件(删)
POST:传输实体主题(改)
Get:获取资源(查)
HEAD:获得报文首部
OPTIONS:询问支持的方法
TRACE:追踪路径
CONNECT:要求用隧道协议链接代理
LINK:建立和资源之间联系(1.1已废弃)
UNLINK:断开连接关系(1.1已废弃)
-
NET.socket
一个简单的socketdemo
服务端
const net = require('net'); //创建socket服务器 var server = net.createServer(socketConnect); // 当有客户端与服务器连接时、触发 function socketConnect (socket) { //自己的ip var myIp = socket.address().address; //其他人的ip var userip = socket.remoteAddress; var clientIp = socket.address().address; console.log(`被链接from:${userip}`); //监听socket数据流 socket.on('data',(chunk) => { process.stdout.write(`客户端输入:${chunk.toString()}`); // console.log(`客户端输入:${chunk.toString()}`); }); socket.on('end',() => { console.log('客户端断开连接'); }); //通过socket对象向另一端通信 socket.write('hello kirito!') } // 让socket服务器监听端口 //post传入0则会由系统分配空闲端口 var post = 2080; server.listen(post,(err) =>{ //监听成功回调 if (err){ //通常是端口被其他对象占用ing throw err; } console.log(`服务端开启,监听:${post}端口`); });
客户端
const net = require('net'); //与服务端socket作为参数可返回多个不同。客户端只返回一个socket对象. const socket = net.createConnection({ port: 2080 }, () => { //'connect' listener console.log('连接成功!'); }); //数据接收监听 socket.on('data', (data) => { console.log(`服务端返回${data.toString()}`); process.stdout.write('client:'); // socket.end(); }); //链接断开监听 socket.on('end', () => { console.log('disconnected from server'); }); //监听控制台输入 process.stdin.on('data',input =>{ process.stdout.write('client:'); if (input.toString().trim() === 'exit') { socket.end(); return; } socket.write(input.toString()); });
-
手动实现一个简单的静态资源管理服务
const http = require('http'); const url = require('url'); const fs = require('fs'); const path = require('path'); const post = 3000; const host = '127.0.0.1'; var mimeJSON; http.createServer((req,res) => { //拿到路径 var pathName = url.parse(req.url).pathname; console.log(pathName); if (pathName.length == 1){ pathName = '/index.html'; } var extname = path.extname(pathName); //读取文件 fs.readFile('./static/'+pathName,(err,files) => { if (err){ res.writeHead(404, { "Content-Type": "text/html;charset=utf-8" }); fs.readFile('./static/'+'404.html',(err,files) => { res.end(files); }); }else { getMine(extname,(mime) => { //MIME类型 //网页:text/html //jpg:image/jpg res.writeHead(200, { "Content-Type":mime }); res.end(files); }); } }); }).listen(post,host,() => { console.log(`成功监听${host}:${post}`); }); function getMine(extname,callback) { var mime; if (!mimeJSON) { fs.readFile('./static/mime.json',(err,data) => { if (err) { mimeJSON = {'aaa': 'dddd'}; }else { mimeJSON = JSON.parse(data); } mime = mimeJSON[extname] || 'text/plain'; console.log('11'+mime); callback(mime) }) }else { mime = mimeJSON[extname] || 'text/plain'; console.log('22'+mime); callback(mime); } }
exports&&require
(在前端中、js与js文件通过html文件相互联系。
而在node.js中、二者则通过exports与require相互联系)
暴露函数、变量
当需要从A.js引用B.js内部的变量、函数时。
必须在B中使用exports对象进行暴露。
A中使用require命令引用B.js文件B
var msg = '你好'; exports.msg = msg;
A
//将foo.exports解固成顶层变量 const foo = require('./foo.js'); console.log(foo.msg);
暴露类、构造函数
B
function People(name,sex,age) { this.name = name; this.sex = sex; this.age = age; } People.prototype.sayHello = function () { console.log(this.name+this.sex+this.age); } //此时People就被视为构造函数、可以用new来实例化 module.exports = People;
A
var People = require('./people.js'); var xiaoming = new People('小明','男','12岁'); xiaoming.sayHello();
exports&&module.exports
module.exports
- 将模块的require变成一个函数、或者任意类型的对象。
module.exports = function(name, age) { this.name = name; this.age = age; this.about = function() { console.log(this.name +' is '+ this.age +' years old'); }; }; var Rocker = require('./rocker.js'); var r = new Rocker('Ozzy', 62); r.about(); // Ozzy is 62 years old
exports
- exports.xxx= xxx本质上等于为module.exports添加新的方法。或者属性
- 如果你已经实现了module.exports、那么之后的 exports.xxx将会失效、不会动态添加.
如果你想你的模块是一个特定的类型就用Module.exports。如果你想的模块是一个典型的“实例化对象”就用exports。
-
node_modules文件夹
假如 /home/ry/projects/foo.js 调用了
require('bar.js')
那么node查找的位置依次为:
/home/ry/projects/node_modules/bar.js /home/ry/node_modules/bar.js /home/node_modules/bar.js
假如 /home/ry/projects/foo.js 调用了
require('bar')
1、那么node将会先查找文件:
/home/ry/projects/node_modules/bar/package.json
关于package.json、每一个模块文件夹的根文件中推荐都写一个package.json文件(文件名固定)。node将自动读取内部配置。
{ "name": "kiritoVar", "version": "0.0.1", "main":"ffff.js" }
2、然后node将会查找文件:
/home/ry/projects/node_modules/bar.js
3、若没有找到在继续查找文件
/home/ry/projects/node_modules/bar/index.js
package.json
- 在你的项目完成之后、可以用npm为自己的项目创建一个package.json
控制台$ npm init 会出现如下引导(均可不填) package name: (beginning) beginning //项目名称 version: (1.0.0) //版本 description: my node demo//项目说明 entry point: (demo_01.js) url_demo.js//入口 test command: //测试 git repository: //git仓库 keywords: suibian//标签、关键词 author: kritio_song//作者 license: (ISC) ISC//版权
然后将会生成一个package.json文件
其中最重要的一点、他将会含有一个dependencies字段"dependencies": { "date": "^1.0.2" 其中'^',表示固定这个数字 "^1.^0.2"就表示固定为1.0.x这样 },
dependencies下、记录着此项目所有引用的第三方模块、以及node_modules文件夹下你自己创建的模块
作用
在项目目录下 $ npm install
将会检测所有dependencies下的依赖、并且自动安装
Post请求处理
原生
if (req.url == '/dopost' && req.method.toLowerCase() == 'post'){ var allData = ''; //为了防止参数过多影响线程利用、node读取参数的方式是分块读取。参数过多时、可能会多次回调 req.addListener('data',(chunk) =>{ allData += chunk; }); //读取完毕 req.addListener('end',(chunk) =>{ console.log(allData.toString()); //输出foo=bar&abc=xyz&abc=123 //可以使用querystring模块转义 querystring.parse(str)字符串 =>字典 res.end(allData); }); }
原生处理post请求、需要两个监听。并且文件上传需要特殊处理
formidable
const http = require('http'); const path = require('path'); const fs = require('fs'); const formidable = require('formidable'); const post = 8080; const host = '127.0.0.1'; http.createServer((req,res) => { if (req.url == '/dopost' && req.method.toLowerCase() == 'post'){ var form = new formidable.IncomingForm(); //设置文件上传存放地址 form.uploadDir = __dirname+"/fileDir"; //执行里面的回调函数时、表单已经接收完毕 form.parse(req, function(err, fields, files) { //所有的文本域、单选框,都在fields存放 //所有的文件域、都在files存放 console.log(err); console.log(fields); console.log(files); if (files){ var extname = path.extname(files.file.name); var random = parseInt(Math.random() * 999999 + 100000); var dir = form.uploadDir; var timestamp=new Date().getTime(); var oldName = files.file.path; var newName = dir+'/'+timestamp+random+extname; //修改文件名以及后缀 fs.rename(oldName,newName,()=>{ console.log(`renameed to ${newName}`); }) } res.end('succes'); }); } }).listen(post,host,() =>{ console.log(`成功监听${host}:${post}`) });
formidable只能接收表单形式提交上来的post参数。
-
模板引擎
EJS(通过字符串进行逻辑替换)
- Embedded JavaScript templates
- 后台的一个模板引擎
- 现在很少用、基本都是前端采用模板拼接(比如vue.js)
const ejs = require('ejs'); var string = '我买了一个iphone<%= a%>s'; var data = { a : 6 }; var html = ejs.render(string,data); console.log(html);
也可以直接替换html文件中的模板标记
node文件中:
const fs = require('fs'); const ejs = require('ejs'); const http = require('http'); http.createServer((req,res) => { fs.readFile('./view/index.ejs',(err ,data ) => { var template = data.toString(); var dictionary = { a:6, news:['第一个','第二个','第三个'] }; var html = ejs.render(template,dictionary); res.writeHead(200, { "Content-Type":'text/html' }); res.end(html); }); }).listen(3000,'127.0.0.1',() =>{ console.log('监听成功'); });
html文件中:
Title 好高兴啊、我今天买了一个iphone<%= a%>s
<% for (var i = 0 ; i< news.length ; i ++){ if(news){ %>
- <%= news[i]%>
<% } } %><% %>之中支持所有js语法(for if等)
include引用
<% include nav.ejs %>
-
图片处理
http://www.graphicsmagick.org/
-
webSocket
使用SocketIO模块
- app.js
/** * Created by kiritoSong on 17/9/29. */ var http = require('http'); var fs = require('fs'); var server = http.createServer(function (req, res) { if (req.url == '/'){ fs.readFile('./index.html',function (err,data) { res.end(data); }) } }); //将server变成socket //http://127.0.0.1:3000/socket.io/socket.io.js 会是一个文件地址 var io = require('socket.io')(server); //监听链接事件 io.on('connection',function (socket) { socket.on('提问',function (msg) { console.log('客户端提问:'+msg); socket.emit('回答',['吃了','还是没吃']); }) socket.on('广播',function (msg) { //broadcast 广播 socket.broadcast.emit('有人问我'+msg); console.log('客户端提问:'+msg); //io.emit可以向所有连接广播 io.emit('回答',['吃了','还是没吃']); }) }); server.listen(3000);
- index.html
Socket index页面
socket.emit('k',msg)负责发送
socket.on('k',msg)负责监听
服务器&&客户端均是
express搭配socket.io
-
一些工具框架(库)
nodemon
一个可以监听node文件改变、并且重新开启node文件的工具
SocketIO
webSocket(浏览器不支持socket则自动模拟长轮询)