nodejs终端使用
运行node命令
运行本地js文件
文件操作案例
初始化目录
初始化数据
创建项目根路径
引入模块
const path=require('path')
const fs=require('fs')
调用模块
//创建项目根路径
fs.mkdir(path.join(root,initData.projectName),(err)=>{
if(err) return;
//创建子目录和文件
initData.data.forEach((item)=>{
if(item.type=='dir'){
//创建子目录
fs.mkdirSync(path.join(root,initData.projectName,item.name));
}else if(item.type=='file'){
//创建文件并写入内容
fs.writeFileSync(path.join(root,initData.projectName,item.name),fileContent(外部引入的模块html文件))
}
)}
});
buffer本质上就是字节数组
API
通过实例化来调用buffer(new)
let buf=new buffer(5);
//
let buf=Buffer.alloc(5);
通过静态方法
let buf Buffer.from('hello')
//buf产生此此字符的16进制编码const buf=Buffer.from(arr)
//传入一个16进制数字的数组
路径操作
路径基本操作API
引入核心模块
const path =require('path')
获取路径的最后一部分
path.basename('/foo/bar/baz/asdf/quux.html(文件路径)','html'可不加)
获取路径
path.dirname('路径')
获取文件的扩展名
path.extname('xxx.html')
路径的格式化处理
path.format()
path.parse()
拼接路径
path.join();
判断是否为绝对路径
path.isAbsolute(c:/foo/..)
规范化路径
path.normalize()
计算两个路径的相对路径
path.relative()
解析路径
path.resolve()
两个特殊的属性
path.delimiter
path.sep
引入const fs=require('fs')
文件信息(元数据?)读取
fs.stat('./abc',(err,stat)=>{
if(err) return ;
if(stat.isFile()){
console.log('文件');
}else if(stat.isDirectory){
console.log('目录');
}
console.log(stat);
})
stat的属性
同步操作
console.log(1);
let ret =fs.statSync('./data.txt');
console.log(ret)
console.log(2)
读文件操作
fs.readFile(file[,options],callback);
const path=require('path');
let strpath=path.join(__dirname,'data.txt');
fs.readFile(strpath,'utf8',(err,data)=>{//不加utf8的话文件会被解析为ASCII编码
if(err) return;
console.log(data);
})
同步操作
let ret =fs.readFileSync(strpath,'utf8');
console.log(ret);
写文件操作
fs.writeFile('./message.txt', '这是第一行',(err)=>{
if(!err){
console.log('文件写入成功')
}
});
//第一个参数为写入文件的路径,第二个参数可以是字符串,也可以是buffer对象,第三个参数默认为utf8
//同步方法
fs.writeFileSync('./message.txt','这是第一行');
//都是覆盖操作
文件的流式操作(大文件操作)
fs.createReadStream(path[,options])
fs.createWriteStream(path[,options])
const path =require('path');
const fs=require('fs');
let spath=path.join(__dirname,'../..','file.zip');
let dpath=path.join('c:/user/Desktop','file.zip');
let readStream =fs.createReadStream(apth);
let writeStream=fs.createWriteStream(dpath);
//基于事件的处理方式
let num=1;
readStream.on('data',(chunk)=>{//data事件,读取文件时触发事件
num++;
writeStream.write(chunk);
});
readSteam.on('end',()=>{//事件处理完成之后触发的函数
console.log('文件处理完成'+num)
});
readStream.pipe(writeStream);
fs.createReadStream(spath).pipe(fs.createWriteStream(dpath));
创建目录
语法
fs.mkdir(path[,mode],callback)
fs.mkdirSync(path[,mode])
实例
const path =require('path');
const fs=require('fs');
//创建目录
fs.mkdir(path.join(__dirname,'abc'),(err)=>{
if(){
console('创建成功')
}else{
console.log('创建失败')
}
});
//在本目录下创建一个abc目录
//同步处理
fs.mkdirSync(path.join(__dirname.'hello'))
读取目录
语法
fs.readdir(path[.options],callback)
fs.readdirSync(path[,options])
实例
const path =require('path');
const fs=require('fs');
//读取目录
fs.mkdir(__dirname,(err,files)=>{
files.forEach((item,index)=>{
fs.stat(path.join(__dirname,item),(err,stat)=>{
if(stat.isFile()){
console.log(item,'文件');
}else if(stat.isDirectory()){
console.log(item,'目录');
}
})
})
})
//同步处理
let files=fs.readdirSync(__dirname);
files.forEach((item,index)=>{
fs.stat(path.join(__dirname,item),(err,stat)=>{
if(stat.isFile()){
console.log(item,'文件');
}else if(stat.isDirectory()){
console.log(item,'目录');
}
})
})
//读取当前目录
删除目录
fs.rmdir(path.join(__dirname,'目录名'),(err)=>{
console.log(err);
})
//同步操作
fs.rmdirSync(path.join(__dirname,'目录名'))
本地安装
全局安装
指定版本安装
卸载
更新(更新到最新版本)
包的规范
package.json字段分析
自定义包案例
把md文件转换为html页面
安装markdown-it包
//初始化
const path =require('path');
const fs =require('fs');
const md=require('markdown-it')();//require('markdown-it')返回一个函数
//指定路径
let tplPath = path.join(__dirname,'tpl.html');
let mdPath = path.join(__dirname,'demo.md');
let targetPath=path.join(__dirname,'demo.html')
//获取markdown文件
fs.readFile(mdpath,'utf8',(err,data)=>{
if(err)return;
//对markdown内容进行转换操作
let result = md.render(data);
//读取模板内容
let tpl =fs.readFile(tplPath,'utf8',(err,tplData)=>{
if(err) return;
tplData=tplData.replace('<%xxx%>',result);
//生成的最终界面写入
fs.writeFile(targetPath,tplData,(err)=>{
console.log('转换完成')
});
})
})
使用http模块初步实现服务器功能
const http=require('http');
引入模块
demo
const http=require('http');
//创建服务器实例对象
let server = http.createServer();
//绑定一个请求事件request
server.on('request',(req,res)=>{//req表示请求信息,res表示响应信息
res.end('hello');
});
//绑定一个端口,监听端口
server.listen(端口号);
//通过locahost:端口号访问
———————————————————华丽的分割线————————————————————————
//通过httpAPI创建
http.createServer((req,res)=>{
res.end('hello');
}).listen(端口号,'本机ip地址',()=>{
console.log('running..')
});
//通过本机ip地址:端口号,访问
处理请求路径的分发
req对象是Class:http.IncomingMessage的实例对象
res对象是Class:http.ServerResponse的实例对象
demo
const http =require('http');
http.createServer((req,res)=>{
res.end(req.url);//请求路径
if(req.url.startsWith('/xxxx')){
res.write('xxxxx');//向客户端响应内容
res.write('xxxx');//可响应多次
res.end('xxxx')//只能执行一次
}else if(req.url.startsWith('/xxxx'){
res.end('xxxx');
}else{
res.end('not found');
}
}).listen(端口号,'本机ip地址',()=>{
console.log('running..')
});
req.url可以获取URL路径获取(端口号之后的部分)
res.write()方法来向客户响应内容
req.url.startWith()
响应完整的页面信息
demo
const http =require('http');
const path =require('path')
const fs =require('fs');
//根据路径读取文件的内容,并且响应到浏览器
let readFile=(url res)=>{
fs.readFile(path.join(__dirname,'文件所在目录',url)'utf8',(err,fileContent)=>{
if(err){
res.end('server error');
}else{
res.end(fileContent);
}
}
http.createServer((req,res)=>{
//处理路径的分发
if(req.url.startsWith('/xxx')){
readFile('xxx.html',res);
}else if(req.url.st、artsWith('/yyy'){
readFile('yyy.html')
}else{
//添加html页面表头防止乱码
res.writeHead(200,{
'Content-Type':'text/plain;charset=utf8'
});
res.end('页面不存在');
}
}).listen(端口号,'本机ip地址',()=>{
console.log('running..')
});
const http =require('http');
const path =require('path')
const fs =require('fs');
//引入映射表文件
const mime = require('mime.json');
http.createServer((req,res)=>{
fs.readFile(path.join(__dirname,req.url),(err,fileContent)=>{
if(err){
res.writeHead(404,{
'Comtent-Type':'text/plain; charset=utf8'
});
res.end('未找到页面');
}else{
//设置默认文件类型
let dtype='text/html'
//获取请求文件的后缀
let ext =path.extname(req.url);
//如果请求文件后缀合理,就能获取到标准的响应格式
if(mime[ext]){
dtype=mime[ext];
}
//如果响应内容是文本,就设置utf8编码
if(dtype[ext]){
dtype+=';charset=utf8'
}
//响应头信息
res.writeHead(200,{
'Content-Type':dtype;
});
res.end(fileContent);
}
});
}).listen(端口号,()=>{
console.log('running..')
});
//localhost访问
实现静态服务器功能
const http =require('http');
const path =require('path')
const fs =require('fs');
//引入映射表文件
const mime = require('mime.json');
http.createServer((req,res)=>{
fs.readFile(path.join(__dirname,req.url),(err,fileContent)=>{
if(err){
res.writeHead(404,{
'Comtent-Type':'text/plain; charset=utf8'
});
res.end('未找到页面');
}else{
//设置默认文件类型
let dtype='text/html'
//获取请求文件的后缀
let ext =path.extname(req.url);
//如果请求文件后缀合理,就能获取到标准的响应格式
if(mime[ext]){
dtype=mime[ext];
}
//如果响应内容是文本,就设置utf8编码
if(dtype[ext]){
dtype+=';charset=utf8'
}
//响应头信息
res.writeHead(200,{
'Content-Type':dtype;
});
res.end(fileContent);
}
});
}).listen(端口号,()=>{
console.log('running..')
});
//localhost访问
const http = require(http);
const ss=require('要引入模块的路径');
const path =require('path');
http.createServer((req,res)=>{
ss.staticServer(req,res,path.join(创建文件路径));
}).listen(3000,()=>{
console.log('running');
})
get参数处理
const url = require(‘url’);
parse方法
const url =require('url');
let str ='http://www.baidu.com/abc?flag=123&keyworld=java';
let ret =url.parse(str,true);//第二参数为true把query属性设置为一个对象
console.log(ret);
//parse把URL转换为一个对象
//url格式:'http://user:[email protected]:8080/p/a/t/h?query=string#hash';
format方法
const url =require('url')
let obj={
protocol:
slashes:
auth:
host:
port:
hostname:
hash:
search:
query:
pathname:
path:
href:
}
let ret1=url.format(obj);
console.log(ret1);
返回一个完整的URL
url实现完整的服务器功能
const http =require('http');
const path=require('path');
const url=require('url');
http.createServer((req,res)=>{
let obj=url.parse(req.url,true);
res.end(obj.query.username+'========'+obj.query.password);
}).listen(3000,()=>{
console.log('running..')
})
ret的属性
post参数获取
const querystring=require('querystring');
引入
实例
const querystring=require('querystring');
//parse方法的作用就是把字符串转化为对象
let param='username=luomingyang&password=123456';
let obj =querystring.parse(param);
console.log(obj.username);
//如果有重复属性则会放到一个数组中
//把对象转化为字符串
let obj1={
flag:'123';
abc:['hello','hi']
}
let str1=querystring.stringify(obj1);
console.log(str1);
参数从浏览器端传输到后台
const querystring=('querystring');
const http=require('http');
http.creatServer((req,res)=>{
if(req.url.startsWith('/login')){//判断URL是不是以login为开头
let pdata='';
req.on('data',(chunk)=>{//有数据传输就会触发的事件
pdata+=chunk;
});
req.on('end',()=>{//结束时触发事件在控制台打印pdata
console.log(pdata);
let obj=querystring.parse(pdata);//把pdata转换为对象,用来获取属性
res.end(obj.username+'_________'obj.password);
});
}
}).listen(3000,()=>{
console.log('running...')
})
登录验证案例
login.html
```
```
login.js
const http =require('http')
const ss =require('要引入模块的路径');//这里封装了一个staticServer方法
const querystring =require('querystring')
const url =require('url')
http.createServer((req,res)=>{
//启动静态资源服务
if(req.url.startWith('查看是否在本目录')){
ss.staticServer(req,res,__dirname);
}
//动态资源服务
if(req.url.startsWith('/login')){//判断请求地址
//get请求
if(req.method=='GET'){
let param=url.parse(req.url,true).query();
if(param.username=='admin'&¶m.password=='123'){
res.end(get successful);
}else{
res.end('get faild')
}
}
//post请求
if(req.method=='POST'){
let pdata='';
req.on('data',(chunk)=>{
pdata+=chunk;
})
req.on('end',()=>{
let obj =querystring.parse(pdata);
if(obj.username=='admin'&&obj.password=='123'){
res.end('psot true');
}else{
res.end('post false')
}
})
}
}
}).listen(3000,()=>{
console.log(ing...);
})
//请求方式也能用来分发路径
模板引擎的使用
优点:使代码更加通用
安装:npm install art-tmppate --save
const template=require('art-template')
引入
核心方法
//基于模板名的渲染模板
template(filename,data);
//将模板源代码编译成函数
template.compile(source,options);
//将模板源代码编译成函数并立即执行
template.render(source,data,options);
实例:template(filename,data);
let html=template();
let html=template(__dirname+'/xxx.art',{
user:{
name:'xxx';
}
})
console.log(html);
实例:template.compile(source,options);
let tpl ='{{each list as value}}- {{value}}
{{/each}}
'
let render=template.compile(tpl);
let ret=render({
list:['apple','orange','banana']
});
console.log(ret);
实例template.render(source,data,options);
//let tpl ='{{each list as value}}- {{value}}
{{/each}}
//用另外一种方法遍历
let tpl ='{{each list}}- {{$index}}:{{$value}}
{{/each}}
let ret=template.render(tpl,{
list:['apple','orange','banana']
})
console.log(ret);
template语法
官网art-template: https://aui.github.io/art-template/zh-cn/docs/syntax.html
条件
{{if value}} ... {{/if}}{{if v1}} ... {{else if v2}} ... {{/if}}
循环
{{each target}} {{$index}} {{$value}}{{/each}}
基本使用
index.art
```
- 语文:{{chinese}}
-
- 数学:{{math}}
- 外语:{english}
- 综合:{{summary}}
```
index.js
const template=require('art-template')
let html=template();
let html=template(__dirname+'/xxx.art',{
user:{
chinese:'120',
math:'130',
english:'146',
summary:'268'
}
})
console.log(html);
nodejs的web开发相关的内容
安装
基本使用
var express = require('express');//返回一个函数
var app = express();
const app=require('express')();//与上面两行是相同效果
//绑定一个根路径的请求
app.get('/',(req,res)=>{
res.send('Hello World');
}).listen(3000,()=>{
console.log('running');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
//实现helloworld
express实现静态服务器
const express=require('express');
const app=express();
//托管静态资源文件
//use方法的第一个参数可以指定一个虚拟路径
app.use('abc',express.static('public'));
app.use('/Hi',express.static('xxx'))
//可以指定多个目录作为静态资源目录
app.listen(3000,()=>{
console.log('running...')
})
express路由处理
路由(根据请求路径和请求方式进行路径分发处理)
http的常用请求方式
restful api(一种URL格式)
实现增删改查操作
const express=require('express');
const app=express();
//基本的路由处理
app.get('/'(req,res)=>{
res.send('get data')
});
app.post('/'(req,res)=>{
res.send('post data')
});
app.put('/'(req,res)=>{
res.send('put data')
});
app.delete('/'(req,res)=>{
res.send('delete data')
});
//通过use方法处理,可以直接处理所有的请求,内置中间件
app.use((req,res)=>{
res.send('ok');
});
app.listen(3000,()=>{
console.log('running..')
});
express中间件
中间件:就是处理过程中的一个环节(本质上就是一个函数)
应用级中间件
中间件的挂载方式和执行流程
应用级中间件绑定到app对象使用app.use()和app.MRTHOD(),其中METHOD是需要处理的http请求的方法,
const express=require('express');
const app=express();
let total=0;
app.use((req,res,next)=>{
console.log('有人访问');
next();
})
app.use('user',(erq,res,next)=>{
//记录访问时间
console.log(Date.now());
next();
})
app.use('user',(erq,res,next)=>{
//记录访问日志
console.log('访问了/user');
next(); //next方法的作用就是把请求传递到下一个中间件
})
app.use('user',(erq,res,next)=>{
total++;
console.log(total);
res.end('reault');
});
app.listen(3000,()=>{
console.log('running');
})
//三个中间件
路由级中间件
路由级使用router.use()或router.VERB()加载,get post put delete
const express=require('express');
const app=express();
app.get('/abc',(req,res,next)={
console.log(1);
next('router');//用来跳转到下一个路由
}(req,res)=>{
console.log(2);
res.send('abc')
});//本质上是一个路由
app.get('/abc',(req,res)=>{
console.log(3);
res.send('hello');
})
app.listen(3000,()={
console.log('running');
})
错误处理中间件
错误处理中间件函数的定义方式与其他中间件函数基本相同,差别在于错误处理函数有四个自变量而不是三个,专门具有特征符 (err, req, res, next)
:
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
应用层中间件参数处理和body -parser的使用
const express =require('express');
const app=express();
//挂载参数处理中间件(post)
app.use(bodyParser.urlencoded({extended:false}));
//处理json格式的参数
app.use(bodyParser.json())
//处理get提交参数
app.get('/login',(req,res)=>{
let data=req.query;
console.log(data);
res.send('get');
})
//处理post提交参数
app.post('/login',(req,res)=>{
let data=req.body;
//console.log(data);
if(data.username=='admin'&&data.password=='123'){
res.send('登录成功');
}else{
res.send('登录失败')
}
})
//处理put提交参数
app.put('/login',(req,res)=>{
res.end('put data');
});
//处理delete提交参数
app.delete('/login',(req,res)={
res.end('delete data');
})
app.listen(3000,()=>{
console.log('running');
})
ajax参数传递
$(function(){
$('#btn').click(function(){
var obj={
username:$('#username').val(),
password:$('#password').val()
}
$.ajax({
type:'post/put/get/detele',
url:'http://localhost:3000/login',
contenType:'application/json',
dataType:'text',
data:JSON.stringify(obj),
sucess:function(data){
console.log(data);
}
})
})
})