基于V8引擎(谷歌浏览器的引擎)渲染JS的工具或者环境javascript
npm(node Package Managernode模块管理器)
:一个js模块(全部封装好可供其余人调取使用的称之为模块或者包)管理的工具,基于npm能够安装下载js模块node xxx.js
Read-Evaluate-Print-Loop
输入-求值-输出-循环多数人把node称之为后台编程语言,是由于:css
传统后台语言:JAVA/Python/PHP/C#html
- JS运行在客户端浏览器中=>前端
- 浏览器给js提供不少全局的属性和方法
window.setTimeout...
- JS运行在服务器端的node中=>后台
- NODE也给js提供不少内置的属性和方法:
http/fs/url/path...
等对象中都提供不少API供js操做
- 前端(浏览器运行js)是限制I/O操做的
input type='file'
这种算是I/O操做,可是须要用户手动选择(并且仅仅是读取不是写入)- 后端(node中运行js) 不限制I/O操做
node自己是基于commonJS模块规范设计的,因此模块式node的组成前端
参考: CommonJS
:模块设计思想(AMD/CMD/ES6 MOUDLE 都是模块化设计思想)java
CommonJS给每个模块(每个js)中都设置了内置的变量/属性/方法node
module
: 表明当前这个模块对象[object]module.exports
: 模块的这个属性是用来导出属性方法的[object]exports
: 是内置的一个变量,也是用来导出当前模块属性方法的,虽然和module.exports
不是一个东西,可是对应的值是一个(module.exports=exports
值都是对象)require
: CommonJS提供的内置变量,用来导入模块的(其实导入的是moudle.exports
暴露出来的东西)
about_node.js
模块中的代码自上而下执行,把exports对应对内存导入进来,因此接受的结果是一个对象require
是一个同步操做:只有把导入的模块代码执行完成,才能够获取值,而后继续执行本模块下面的代码let temp1 = require('./about_node');
//=> ./
是特地指定当前目录中的某个模块(.js
能够省略)require('./xxx')
或者../xxx
或者 /xxx
这种本身制定的路径的模式,都是为了导入自定义的模块,换句话说,想要导入自定义的模块,必须加路径jquery
require('./xxx')
首先到当前项目中的node_modules
中查找是否存在这个模块,不存在找node提供的内置模块(导入第三方或者内置的)web
__dirname
: 模块中这个内置变量是当前模块所在的绝对路径(具体到盘符:物理路径)
console.log(__dirname)
C:\Users\lenovo\Desktop\notes\NODE
__filename
: 相对于_dirname来说,多了模块名称 (即对了文件名称)
C:\Users\lenovo\Desktop\notes\NODE\about_node.js
// about_node.js
let a = 12;
let fn = b => {
return a * b
}
// console.log(1)
// setTimeout(()=>{
// console.log(1.5)
// },1000)
exports.fn = fn; // 把当前模块私有的函数放到exports导出对象中(赋值给他的某一个属性),这样在其余模块中,能够基于require导入进来使用 <=> moudle.exports.fn = fn
// console.log(2)
console.log(__dirname); //C:\Users\lenovo\Desktop\notes\NODE
console.log(__filename) //C:\Users\lenovo\Desktop\notes\NODE\about_node.js
复制代码
// about_node2.js
let a = 2;
let fn = b => {
return a / b
}
let temp1 = require('./about_node'); // ./ 是特地指定当前目录中的某个模块(.js能够省略)
// console.log(3); // 1 2 3 先把about_node.js中的代码所有执行完,再执行about_node2.js中的代码
// // 若是加定时器 1 2 3 1.5
// console.log(temp1); //此时temp1是个对象 {fn:...}
console.log(temp1.fn(10)); //120 用的是about_node.js中的变量a和fn
// // 第二次并无把about_node.js执行,由于第一次执行把导出的结果缓存了 但不多写两次
// temp1 = require('./about_node');
// console.log(temp1.fn(10)); //120
复制代码
【内置模块fs:实现I/O操做】ajax
经常使用方法:sql
fs.mkdir / fs.mkdirSync
:建立文件夹 有Sync的是同步建立,反之是异步,想要实现无阻塞I/O操做,咱们通常用异步完成 fs.mkdir(path,callback)
f
s.mkdirSync(path)`fs.readsir / fs.readdirSync
:读取文件目录中的内容fs.rmdir / fs.rmdirSync
:删除文件夹(若是文件夹中有内容不能删除)fs.readFile
:读取文件中内容fs.writeFile
:向文件中写入内容(覆盖写入:写入的新内容会替换原有内容)fs.appendFile
:追加写入新内容,原有内容还在fs.copyFile
:拷贝文件到新的位置fs.unlink
:删除文件let fs = require('fs');
//建立文件夹 同步会形成阻塞,通常用异步
fs.mkdir('./less',(err)=>{
if(err){
console.log(err);
return;
}
console.log('ok');
});
console.log(1);
//读取文件目录 异步
fs.readdir('./',(err,result)=>{
if(err){、
// console.log(err);
return;
};
console.log(result); // 当前文件目录 ['less', 'module_fs.js'] 返回结果是一个数组
});
//删除文件夹 (必须保证文件夹是空的)
fs.rmdir('./less',err=>{
if(err){
console.log(err);
return;
}
console.log('ok');
})
/* 若是文件夹中有内容 则会报错{ [Error: ENOTEMPTY: directory not empty, rmdir 'C:\Users\lenovo\Desktop\notes\NODE\module_fs\less'] */
// 读取文件内容
fs.readFile('./less/less.js','utf-8',(err,result)=>{
if(err){
// console.log(err);
return;
}
console.log(result);//文件内容(字符串格式) setTimeout(()=>{console.log(123) },1000)
// 不设置utf-8编码格式,读取出来的是buffer格式的数据,设置事后是字符串格式数据
})
// 向文件中写入内容(覆盖写入)
fs.writeFile('./less/less.js','哈哈','utf-8',(err)=>{
//第二个参数是文件写入的内容 会覆盖原内容
})
// 向文件中写入内容(追加写入)
fs.appendFile('./less/less.js','嘿嘿','utf-8',(err)=>{
//第二个参数是文件写入的内容 追加在原内容后
})
// 删除文件
fs.unlink('./less/less.js',(err)=>{
if(err){
return;
}
console.log('ok')
})
复制代码
【url内置模块】
url.parse(url[,flag]):
Url {
- protocol: 'http:', //=>协议
- slashes: true, //=>是否有双斜线
- auth: null, //=>
- host: 'baidu.com', //=>域名+端口
- port: null, //=>端口
- hostname: 'baidu.com', //=>域名
- hash: '#video', //=>哈希值
- search: '?from=qq&lx=stu', //=> 问号传参[string]
- query: 'from=qq&lx=stu', //=>问号传参[string] 不包含问号
- pathname: '/', //=> 请求资源的路径名称
- path: '/?from=qq&lx=stu', //=>pathname + search
- href: 'baidu.com/?from=qq&am…' //=> url地址 }
let url = require('url');
console.log(url.parse('http://baidu.com?from=qq&lx=stu#video',true));
// 返回一个url对象
复制代码
【http内置模块】
服务器端任务
注意:基于node建立后台程序,咱们通常都建立一个server模块,在模块中实现建立web服务,和对于请求的处理(通常会把server模块放到当前项目的根目录下)
//导入内置模块
let http = require('http');
let url = require('url');
let path = require('path');
let fs = require('fs');
//建立web服务
let port = 80;
let server = http.createServer((req,res)=>{
/* 当服务建立成功,而且客户端向当前服务发送了请求才会执行回调函数,而且发送一次请求,回调函数就会触发执行一次 客户端如何向建立的服务器发送请求? 对应好协议、域名、端口等信息,在浏览器中或者ajax等中发送请求便可 http://localhost:80/... 服务在电脑上,localhost本机域名,也就是本机的客户端服务器,访问本机的服务器端程序(也就是本身的电脑既是客户端又是服务器端) http://内网ip:80/... IP作域名访问,若是是内网IP,相同局域网下的用户能够访问这个服务,若是是外网IP,全部能联网的基本上均可以访问这个服务(局域网下访问,须要互相关掉防火墙) 查看内网IP:在CMD中输入ipconfig => 172.18.0.80 localhost:80/ 等同于 172.18.0.80:80/ */
console.log('hello world!');
});
server.listen(port,()=>{
//回调函数:当服务建立成功,而且端口号也已经监听成功后,触发的回调函数
console.log(`server is success,listen${port}!`); // server is success,listen80!
});//监听一个端口 [0~65535]
//http.createServer().linten(80);
// 当服务建立成功,命令行中会一直存在光标闪烁,证实服务器正在运行中(必定要保证服务试运行的),ctrl+c => 结束运行服务
复制代码
两个参数
req:require
请求对象,包含了客户端的请求信息(不包括hash值)req.url
存储的是请求资源的路径地址以及问号传参req.method
客户端请求方式req.headers
客户端的请求头信息(是一个对象)res:response
响应对象,包含了一些属性和方法,可让服务器端返回给客户端内容res.write
基于这个方法,服务器端能够向客户端返回内容res.end
结束响应 -res.writeHead
重写响应头信息 (是一个对象)res.writeHead(200,{
'content-Type':'text/plain;charset=utf-8'
// text/plain 纯文本类型
})
复制代码
res.setHeader
重写响应头信息 (不用写状态码) res.setHeader('Content-type','text/html; charset=utf-8');
用url模块中的parse url.parse(req.url)
// 把url中的路径地址和问号传参分别解析
let {pathname,query} = url.parse(req.url,true)
console.log(pathname,query);
/* /index.html [Object: null prototype] { uesr: 'tom', name: 'haha' } */
复制代码
let http = require('http');
let url = require('url');
let path = require('path');
let fs = require('fs');
//建立web服务
let port = 8080;
// let handle = function handle(req,res){
// }
// http.createServer(handle).listen(port);
let server = http.createServer((req,res)=>{
// console.log(url,method,headers);
// // 获取请求头中某个具体信息
// console.log(headers['user-agent']);
/* /?user=tom GET 请求头:{ host: 'localhost:8080', connection: 'keep-alive', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,;q=0.8,application/signed-exchange;v=b3', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9' } */
// res.write('hello world!');
// res.end('hello world!'); //表示服务器端返回字符串内容并结束响应 通常返回的是string或者buffer格式的数据
//重写响应头信息 是一个对象 (中文设置)
/* 对象有两个参数 1. HTTP状态码 2.'content-Type':'text/plain;charset=utf-8' 解决中文乱码问题 */
res.writeHead(200,{
'content-Type':'text/plain;charset=utf-8'
// text/plain 纯文本类型
})
res.end(JSON.stringify({name:'哈哈哈'}));//{"name":"xxx"} 返回JSON格式的字符串
});
server.listen(port);
复制代码
npm -v
查看nom版本号npm install
安装npm init -y
配置项目清单
package.json
文件// package.json文件
{
"name": "NODE",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"server": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
复制代码
<input type="text" id="txt" />
复制代码
txt.onblur = function () {
jsonp({
callback:'cb',
url:"http://localhost",
data:{
user:this.value
},
success:function(data){
console.log(data);
}
})
}
function jsonp(json) {
let opt = {
callback: 'callback',
url: '',
data: {},
}
let fnName = json.fname || 'jQuery_' + (Date.now());
window[fnName] = function (data) {
json.success(data);
// delete window[fnName];
window[fnName] = null;
}
//动态建立都异步
let oS = document.createElement('script');
// oS.src = json.url + '?' +new URLSearchParams(json.data) + '&'+json.callback+'='+fnName;
json.data[json.callback] = fnName; //cb=jquery_231231
oS.src = json.url + '?' + new URLSearchParams(json.data);
document.querySelector('head').appendChild(oS);
oS.remove();
}
复制代码
// 服务器端
//建立服务器
const http = require('http');
//建立服务
let sql = [
{
user: 'Tom',
password: 123
},
{
user: 'Jess',
password: 1234
},
{
user: 'Alex',
password: 12345
}
];
const app = http.createServer((request, response) => {
let url = request.url; //接受客户端发送的请求(参数:key=val&key2=val2... 此参数是字符串)
let obj = {};
if (url !== '/favicon.ico') {
// 把url字符串转化为对象 把字符串先转成数组,再把数组转成对象
url.split('?').split('&').forEach(item => {
let ary = item.split('=');
console.log(ary)
obj[ary[0]] = ary[1];
});
// 判断数组中是否有发送来的用户名
let isExist = sql.find(e => e.user === obj.user);
console.log(isExist)
// 中文设置
response.setHeader('Content-Type', 'text/html; charset=utf-8');
// 若是数据数组中有,说明用户名被占用
// obj.cb 是后台返回给前台的数据
if (isExist) {
response.write(obj.cb + "({code:1,msg:'用户名已被注册'})");
} else {
response.write(obj.cb + "({code:0,msg:'注册成功'})");
}
response.end();
}
})
//端口监听
app.listen(80)
复制代码
fetch('/post',{
body:'user=xiaoqiang',
method:'post',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(e=>e.json())
.then(d=>{
console.log(d);
});
复制代码
// 服务器端
const http = require('http');
const fs = require('fs');
const querystring = require('querystring');
// const
let sql = ['zhiqiang']
http.createServer((req,res)=>{
let url = req.url;
if(url !== '/favicon.ico'){
//走文件
if(url.includes('.html')){
try {
let d = fs.readFileSync('./www'+url);
res.write(d.toString());
} catch (error) {
let er = fs.readFileSync('./www/404.html');
res.write(er.toString());
}
res.end();
}else{
//走接口
if(url === '/post'){
let str = '';
req.on('data',(d)=>{
// console.log(d.toString())
str += d;
});
req.on('end',()=>{
// console.log(str.toString(),111);
let obj = querystring.parse(str);
// console.log(.user)
res.setHeader('Content-Type','text/html;charset=utf-8');
if(sql.includes(obj.user)){
res.write(JSON.stringify({code:0,msg:"失败"}));
}else{
res.write(JSON.stringify({code:1,msg:"成功"}));
}
res.end();
});
}
}
}
}).listen(80);
复制代码
====
服务器上有一堆项目代码,这堆项目代码中既可能有服务器端的程序代码,也可能有客户端的程序代码,而客户端的程序代码咱们通常放到static(静态的)这个文件夹当中
static/publice
: 都是服务器端须要返回给客户端,有客户端浏览器渲染和解析的(前端项目:包括页面、css、js、图片等)
server.js
: 都是须要在服务器端基于node执行的(后端项目:通常只有js)