基于v8(webkit内核)引擎渲染和解析js (所以它非后台语言是一个工具或环境,用来解析js的工具或环境 )(类似:webview/谷歌浏览器等)
1.基于命令$ node xxx.js 把js代码在node环境里执行。
2.基于REPL模式(Read-Evaluate-Print-Loop,输入-求值-输出-循环)$ node
I/O :一般指对文件的读写操作
I :input 输入
O:output 输出
在客户端浏览器中运行:
1,不能对客户端本地文件进行读写操作,因为要保证客户端安全。
2,input:type='file’文件上传这种除外,但是也要用户手动选择后才可以。
在服务端运行(基于NODE运行):
1,可以对服务端文件进行读写操作
2,NODE赋予了JS进行I/O操作的能力(内置模块:fs)
在客户端浏览器中运行JS:
JS的全局对象是:window(提供了很多内置的属性和方法)
在NODE中运行JS:
JS的全局对象是:global
安装在全局环境下和安装在当前项目中
安装在全局:$ npm install xxx --global ( $ npm I -g xxx)**
安装在本地项目中: $ npm install xxx
{
把模块设置为开发依赖(开发中):$ npm install xxx --save-dev
把模块设置为生产依赖(部署到服务器):$ npm install xxx – save
}
安装在全局和本地的区别
{
在全局:安装在全局对任何项目都有作用(也有可能导致版本冲突),但是只能基于命令的方式管理,不能基于CommonJS中的require导入使用。($ npm root -g 查看全局安装到目录,原因是在全局目录下生成了一个 xxx.cmd的文件)
在本地:默认不能基于命令管理,但是可以导入到文件中基于代码操作只对当前项目有用
}
在本地安装模块之前,这样最好先 $ npm init -y,生成package.json模块配置文件
把安装的模块生成配置请单,存放在package.json中,后期别人需要部署文件的时候,只需执行 $ npm i 就可以把所以的依赖项重新安装一遍 。(“跑环境”)
$ npm i :是把开发和生产依赖的模块都安装一遍
$ npm I --production :只安装生产依赖的模块
在package.json 中,可以基于scripts选项配置本地可执行的脚本命令 $ npm run xxx :
"scripts":{
// AAA是命令,值是要做的事
"AAA": "node xxx.js",
}
在配置可执行脚本命令的时候,基于process的环境变量区分开发还是生产环境
"scripts":{
// set NODE_EVN=dev 设置全局环境变量 ( mac下用 export NODE_EVN=dev )
"serve":"set NODE_EVN=dev&&node text1.js",
"built":"set NODE_EVN=pro&& node text1.js"
}
AMD:require.js
CMD: sea.js
CommonJS: node.js
ES6: Module
这些模块化思想,规定了在JS中我们的模块如何创建,如何导入及如何导出。
http/https 创建和管理服务的模块
fs 给予JS进行I/O操作的
url 解析URL地址的
path 管理路径的
...
less
mime
qs
express
express-session
body-parser
...
module.exports={
//这些属性的方法就是需要暴露给外面调取使用的
xxx:xxx
};
//语法
let[模块名] = require([模块的地址])
let A = require('./A')
let qs = require('qs')
// 1)可以省略.js
// 2)如果是调取自己定义的模块,则需要加/(根目录)./(当前目录)../(上级目录)这三个中的某一个
// 3)不加上述地址,则先找第三方模块(安装在自己本地的),如果没有,则找NODE中的内置模块,如果再没有,则报错。
fs全称是file system(文件系统),它是NodeJS提供的文件操作API。
提供大量的属性和方法,让JS在NODE环境中执行的时候,可以操作服务器的资源文件,也就是给予了I/O操作的能力
// 读取指定目录(相对目录和绝对目录都可以)中的文件目录
let result = fs.readdirSync('./')
console.log(result);
//异步操作是:读取成功后触发回调函数执行
fs.readdir('./',(err,result) =>{
// => ERR 存储读取失败后的错误信息
// => RESULT 存储读取成功后的结果(此时ERR=NULL)
if(err === null){
console.log(result);
}
});
// 语法
let result = fs.readFileSync('[path]','[encoding]')
//异步操作
fs.readFileSync('[path]','[encoding]','callback')
/* 例如
fs.readFile('./',‘utf-8’,(err,result) =>{
if(err === null) return;
console.log(result);
});
*/
writeFile : 同步或者异步写取某一个文件中的内容
向某个文件中写入内容(如果文件不存在,他会默认创建一个文件再写入,而且写入的方式是“把之前文件中的内容全覆盖”)
copyFile:把某个文件里面的内容拷贝到新的目录中
替换型拷贝:原来目录中存在这个文件,新拷贝的会替换原来的
fs.copyFile('./A.txt','./c.txt',err ={
console.log(err);
})
fs.mkdir('./js',err ={
console.log(err);
})
fs.rmdir('./js',err ={
console.log(err);
})
fs文档
封装fs模块的所有api返回一个promise对象使之能够实现链式操作,避免回调地狱。
let fs=require('fs'),
path = require('path')
function readFile(pathname){
//获取文件的后缀名
let suffixREG = /\.([0-9a-zA]+)$/,
suffix = suffixREG.test(pathname)?suffixREG.exec(pathname)[1]:'',
encoding = 'utf-8';
/^(PNG|GIF|JPG|JPEG|WEBP|BMP|ICO|SVG|MP3|MP4|WAV|OGG|M3U8)$/i.text(suffix)?
//=> 用户调用的时候,传递的PATH-NAME都以项目根目录作为参照(执行JS也是在根目录执行),用户只需要把读取文件,相对根目录的路径和名称传递进来即可
pathname = path.resolve(pathname);
return new Promise((resolve,reject)=>{
fs.readFile(pathname,encoding,(err,result)=>{
if (err !== null){
reject(err);
return;
}
resolve(result);
})
})
}
module.exports ={
readFile
}
let{
readFile
} = require('./utils/promiseFS');
readFile('./js/path/js').then(result =>{
console.log(result);
}).catch(reason =>{
console.log(reason);
});
let{
readdir,
readFile,
mkdir,
writeFile
} = require(./)
readdir('.css').then(result =>{
result = result.filter(item => /\.css$/i.text(item));
result = result.map(item =>{
return readFile('./css/${result[item]}')
})
return Promise.all(result);
}).then(results =>{
results = results.join('');
// 此时的results存储的是未经压缩的合并后的css代码,接下里基于less模块完成css内容的压缩
return new Promise((resolve,reject)=>{
less.render(results,{
// less模块规定:设置压缩的方式
compress:ture
},(err,result)=>{
if(err !== null) reject(err);
resolve(result.css);
});
});
}).then((css) =>{
//把压缩后的写在指定的目录中
return wrieFile('./dist/index.css',css);
console.log('创建成功');
})
let http = require('http')
url = require('url')
// http.create-server 创建服务
let server = http.createServer();
//当客户端向当前服务发送请求的时候,会触发此回调函数(请求N次,回调执行n次)而且每一次都能获得本次请求的相关信息。
//req:request req对象中存储了客户端的请求信息
//res:respomse res对象提供了对应的属性和方法,可以让服务器返回给客户端信息
//server.listen监听端口号
/*server.listen(80,()=>{
//当服务创建成功,并端口号已经监听完成,触发此回调函数执行
console.log('服务已经给予post端口启动')
})*/
let PORT=80;
function listen(PORT){
try{
server.listen(80,()=>{
console.log('服务已经给予post端口启动')
});
} catch(err){
PORT++;
listen(PORT);
}
}
listen(PORT)
let express = require('express');
// 执行express创建一个服务:返回的结果app用来操作这个服务
// app.listen:创建一个web服务,监听端口号
let app = express();
app.listen(8080,()=>{
console.log('server successfully!')
});
// 静态资源文件的请求处理
//express.static([path]):指定的目录中查找客户端需要的资源文件内容,并且将其返回
app.use(express.static('./client'));
app.use((req,res)=>{
//执行static没有找到对应资源文件(可以做404处理)
res.status(404);
res.send('NOT FOUND!')
})
中间件:在创建完服务和处理数据(文件)请求之前,我们提前做一些事情(公共的事情)
app.use([path],function)
path:是路由的url,默认参数‘/’,意义是路由到这个路径时使用这个中间件
function:中间件函数(function(request,response,next))
express-session
是express中的一个处理session的中间件,可以说是express中最常见的中间件之一了.
body-parser
body-parser是一个HTTP请求体解析的中间件,使用这个模块可以解析JSON、Raw、文本、URL-encoded格式的请求体.
body-parser还支持为某一种或者某一类内容类型的请求体指定解析方式,指定时可以通过在解析方法中添加type参数修改指定Content-Type的解析方式。
比如,对text/plain内容类型使用JSON解析
body-parser模块的API
当请求体解析之后,解析值会被放到req.body属性中,当内容为空时候,为一个空对象{}
bodyParser.json()–解析JSON格式
bodyParser.raw()–解析二进制格式
bodyParser.text()–解析文本格式
bodyParser.urlencoded()–解析文本格式
let express = require('express');
bodyParser = require('bodyParser')
promiseFS = require('./promise')
let{
dataHandle
} = require('./utils')
//创建web服务
app.listen(8080,()=>{
console.log('server successfully!')
});
//数据接口API的请求处理
//把post请求基于主体传递的信息获取到,放到req,body上
app.use(bodyParser.urlencoded({
extended:true
}));
//把json文件中所以存储的数据都获利,放到req.xxx上
app.use((req,res,next)=>{
let path = './json';
let p1 = promiseFS.readFile(path + '/user.json'
let p2 = promiseFS.readFile(path + '/customer.json'
let p3 = promiseFS.readFile(path + '/visit.json'
let p4 = promiseFS.readFile(path + '/department.json'
let p5 = promiseFS.readFile(path + '/job.json'
Promise.all([p1,p2,p3,p4,p5]).then(resqults =>{
let[$USERDATA,$CUSTOMERDATA,$VISTDATA,$DEPARTMENTDATA,$JOBDATA] = results;
req.$USERDATA = dataHandle($USERDATA);
req.$CUSTOMERDATA = dataHandle($CUSTOMERDATA);
req.$VISTDATA = dataHandle($VISTDATA);
req.$DEPARTMENTDATA = dataHandle($DEPARTMENTDATA);
req.$JOBDATA = dataHandle($JOBDATA);
next();
}).catch(err =>{
res.status(500);
res.send(err);
})
})
//构建EXPRESS路由
//请求的API地址符合xxx的,都进入到指定的路由中
app.use('/user',require('./routes/user'));
app.use('/customer',require('./routes/customer'));
app.use('/visit',require('./routes/visit'));
app.use('/department',require('./routes/department'));
app.use('/job',require('./routes/job'));
//静态资源文件的请求处理
app.use(express.static('./client'));
app.use((req,res)=>{
res.status(404);
res.send('NOT FOUND!',)
})
// 把json字符串转化Json对象,并且过滤掉STATE===1的
function dataHandle(str){
let arr =JSON.parse(str);
arr =arr.filter(item =>{
return parseInt(item.state)===0;
});
return arr;
}
module.exports ={
dataHandle
};