服务器搭建
let http = require('http')
// 调用createServer方法创建实例
let server = http.createServer()
// 绑定一个request事件处理函数
// 这个函数得作用就是处理接收请求,并且根据url进行不同得处理
// 接收到请求,后面有两个回调函数得参数,分别是请求得信息,和响应得信息
server.on('request',(req,res)=>{
// 设置请求头编码
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
let url = req.url
if (url === '/') {
res.end('<h1>首页</h1>')
}else if (url=== 'fenlei') {
res.end('<h1>分类</h1>')
}else if (url === 'wode') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>404</h1>')
}
})
// 开始服务器,监听端口号
server.listen(3000,()=>{
console.log('服务器已经开启,可以通过访问http://127.0.0.1:3000/来获取数据');
})
设置状态码和响应头
response.writeHead(200, { 'Content-Type': 'text/plain' });
设置响应头
response.setHeader('Content-Type', 'text/html');
写入内容
response.write(fileData);
结束响应
response.end();
封装服务器
let http = require('http')
let path = require('path')
let url = require('url')
class app {
constructor(){
console.log('进来');
this.server = http.createServer()
// 定义一个对象来存放url和他得回调函数,在调用on得使用,根据url来调用函数
this.objEvent = {}
// },
// '/aa':function (req,res){ console.log('<h1>我得<h1>');
this.server.on('request',(req,res)=>{
// 解析路径,比如 "/" { root: '/', dir: '/', base: '', ext: '', name: '' }
let pathObj =path.parse(req.url)
// 检测url是否为obj对象中已经定义好得对象,否则就404
// 由于在objEvent中定义得 是以url 为键值 ,以fn为值得形式
// 在执行on方法得事情,其实if也是一种循环,当检测到objEvent里面得有值得时候,就会执行下面得东西
if (pathObj.dir in this.objEvent) {
// 把路径后面得传给下面req
req.path1 = pathObj.base
this.objEvent[pathObj.dir](req,res)
}else{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
res.end('<h1>404<h1>')
}
})
}
on(url,fn){
// 把fn赋值给键值url得值
this.objEvent[url] = fn;
}
run(port,callback){
this.server.listen(port,callback)
}
}
let a = new app()
a.on('/',(req,res)=>{
res.end('aaa')
})
a.on('/aa',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
if (req.path1 === 'index.html') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>其他</h1>')
}
})
a.run(80,()=>{
console.log("服务器其启动");
})
实现静态服务器
能够根据需要请求的文件,原封不动的将服务器磁盘中的数据直接返回给到浏览器。
let http = require('http')
let path = require('path')
let fs = require('fs')
class app {
constructor(){
this.server = http.createServer()
this.objEvent = {}
// 第一步首先在构造函数里面定义一个访问静态目录得url
this.staticdir = '/static'
this.server.on('request',(req,res)=>{
let pathObj =path.parse(req.url)
if (pathObj.dir in this.objEvent) {
req.path1 = pathObj.base
this.objEvent[pathObj.dir](req,res)
// 第二步然后判断如果是访问静态目录
}else if (pathObj.dir == this.staticdir ) {
// 第三步,改变一下后缀名
res.writeHead(200,{'Content-Type': this.getgetContentType(pathObj.ext)})
// 第四步,读取静态目录里面得内容
let rs = fs.createReadStream('./static/'+ pathObj.base)
// 第五步,返回给浏览器
rs.pipe(res)
}
else{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
res.end('<h1>404<h1>')
}
})
}
on(url,fn){
// 把fn赋值给键值url得值
this.objEvent[url] = fn;
}
run(port,callback){
this.server.listen(port,callback)
}
getgetContentType(extName){
switch (extName) {
case ".jpg":
return "image/jpeg";
case ".html":
return "text/html;charset=utf-8";
case ".js":
return "text/javascript;charset=utf-8";
case ".json":
return "text/json;charset=utf-8";
case ".gif":
return "image/gif";
case ".css":
return "text/css"
}
}
}
let a = new app()
// 第六步,也是重点,在这里可以惊醒修改访问静态目录得url
a.staticdir = '/qqq'
a.on('/',(req,res)=>{
res.end('aaa')
})
a.on('/aa',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
if (req.path1 === 'index.html') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>其他</h1>')
}
})
a.run(80,()=>{
console.log("服务器其启动");
})
实现通关url进行动态渲染
根据url的值来获取不同序列号的值
let http = require('http')
let path = require('path')
class app {
constructor(){
console.log('进来');
this.server = http.createServer()
// 定义一个对象来存放url和他得回调函数,在调用on得使用,根据url来调用函数
this.objEvent = {}
// },
// '/aa':function (req,res){ console.log('<h1>我得<h1>');
this.server.on('request',(req,res)=>{
// 解析路径,比如 "/" { root: '/', dir: '/', base: '', ext: '', name: '' }
let pathObj =path.parse(req.url) // 第三步,获取路由
// 检测url是否为obj对象中已经定义好得对象,否则就404
// 由于在objEvent中定义得 是以url 为键值 ,以fn为值得形式
// 在执行on方法得事情,其实if也是一种循环,当检测到objEvent里面得有值得时候,就会执行下面得东西
if (pathObj.dir in this.objEvent) { // 第四步,检测路由在不在保存得对象里
this.objEvent[pathObj.dir](req,res) // 第五步,再得话执行回调函数
req.path1 = pathObj.base // 第六步,定义路由后面得子路由,放到req里面
}else{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
res.end('<h1>404<h1>')
}
})
}
on(url,fn){ // 第二步,把路由通关键值为序号,回调为值得方式保存起来
// 把fn赋值给键值url得值
this.objEvent[url] = fn;
}
run(port,callback){
this.server.listen(port,callback)
}
}
let a = new app()
a.on('/',(req,res)=>{
res.end('aaa')
})
a.on('/aa',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
if (req.path1 === 'index.html') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>其他</h1>')
}
})
a.on('/movie',(req,res)=>{ // 第一步,定义路由
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
let movie=[
{
title:'aa',
bef:'11111111111111111111111111111111111111111'
},
{
title:'bb',
bef:'22222222222222222222222222222222222222222'
}
]
// 这里就是把绑定url里面的值来把序列号里面的值
let index = req.path1 // 第八步,从请求体中拿出来子路由
res.send(movie[index].title) // 第九步,通关子路由展示不同得内容
})
a.run(80,()=>{
console.log("服务器其启动");
})
实现简单{{}}语法
首先讲述一下正则的exec方法,匹配到的内容是再返回的结果中序列号第二个,并且执行一次匹配一次,再继续执行则往下面匹配
这里使用这个方法,其实和上面动态使用路由思路差不多,但是这里使用这个render函数代表输出。
这个render函数得作用就是匹配html文件里面使用 类似 {{title}} 这样得参数,并且使用正则匹配,当匹配到{{}} 就根据里面得内容,就替换掉
let http = require('http')
let path = require('path')
let fs = require('fs')
class app {
constructor(){
console.log('进来');
this.server = http.createServer()
this.objEvent = {}
this.server.on('request',(req,res)=>{
let pathObj =path.parse(req.url)
let pathAll = pathObj.dir
if (pathAll in this.objEvent) {
res.render = render // 第一步,定义一个render函数赋值render
// 把路径后面得传给下面req
req.path1 = pathObj.base
this.objEvent[pathAll](req,res)
}else{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
res.end('<h1>404<h1>')
}
})
}
on(url,fn){
// 把fn赋值给键值url得值
this.objEvent[url] = fn;
}
run(port,callback){
this.server.listen(port,callback)
}
}
let a = new app()
a.on('/',(req,res)=>{
res.end('aaa')
})
a.on('/aa',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
if (req.path1 === 'index.html') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>其他</h1>')
}
})
a.on('/movie',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
let movie=[
{
title:'aa',
bef:'11111111111111111111111111111111111111111'
},
{
title:'bb',
bef:'22222222222222222222222222222222222222222'
}
]
let index = req.path1
// res.end(movie[index].title)
res.render(movie[index],'./index.html') // 第二步,把数据和html模板传进来
})
function render(options,path) {
fs.readFile(path,{encoding:'utf-8',flag:'r'},( (err,data)=>{ // 第三步,读取模板,匹配{{}},
if (err) {
}else{
let reg = /\{\{(.*?)\}\}/igs
let result;
// 下面以循环的方式来多次执行exec方法来匹配全部值出来
while (result= reg.exec(data)) {
// 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
let strKey = result[1].trim() // 第四步,拿到{{}}里面得值作为键值
// 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
let strValue = options[strKey] // 通过键值拿到相对应得内容
data = data.replace(result[0],strValue) // 把读取到得内容替换掉
}
}
// end方法就是打印出来
// 因为已经把render函数复制给res,并且上面使用箭头函数,这里得this就是res
this.end(data)
}))
}
a.run(80,()=>{
console.log("服务器其启动");
})
{{}}便利遍历数组得封装
html代码
<ul>
{%for {stars} %}
<li>{{item}}</li>
{%endfor%}
</ul>
js封装代码-
let http = require('http')
let path = require('path')
let fs = require('fs')
class app {
constructor(){
console.log('进来');
this.server = http.createServer()
// 定义一个对象来存放url和他得回调函数,在调用on得使用,根据url来调用函数
this.objEvent = {}
// },
// '/aa':function (req,res){ console.log('<h1>我得<h1>');
this.server.on('request',(req,res)=>{
// 解析路径,比如 "/" { root: '/', dir: '/', base: '', ext: '', name: '' }
let pathObj =path.parse(req.url)
let pathAll = pathObj.dir
// 检测url是否为obj对象中已经定义好得对象,否则就404
// 由于在objEvent中定义得 是以url 为键值 ,以fn为值得形式
// 在执行on方法得事情,其实if也是一种循环,当检测到objEvent里面得有值得时候,就会执行下面得东西
if (pathAll in this.objEvent) {
res.render = render
// 把路径后面得传给下面req
req.path1 = pathObj.base
this.objEvent[pathAll](req,res)
}else{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
res.end('<h1>404<h1>')
}
})
}
on(url,fn){
// 把fn赋值给键值url得值
this.objEvent[url] = fn;
}
run(port,callback){
this.server.listen(port,callback)
}
}
let a = new app()
a.on('/',(req,res)=>{
res.end('aaa')
})
a.on('/aa',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
if (req.path1 === 'index.html') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>其他</h1>')
}
})
// 下面就进行动态渲染,通关url的的值来动态渲染出内容
a.on('/movie',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
let movie=[
{
title:'aa',
bef:'11111111111111111111111111111111111111111',
stars:['aaa','bbb','ccc']
},
{
title:'bb',
bef:'22222222222222222222222222222222222222222'
}
]
// 这里就是把绑定url里面的值来把序列号里面的值
let index = req.path1
// res.end(movie[index].title)
res.render(movie[index],'./index.html')
})
function render(options,path) {
fs.readFile(path,{encoding:'utf-8',flag:'r'},( (err,data)=>{
if (err) {
}else{
// 匹配字符串
// 这里注释掉方法得原因是,这里会匹配到数组中得{{}}并且会替换掉,会导致下面匹配不到
// data = replaceStr(data,options)
// 匹配数组
// 空格也是匹配对象,下面要是没有空格,会匹配不到
let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
let result = ''
while (result = reg.exec(data)) {
let arrKey = result[1].trim()
let arrValue = options[arrKey]
let listArr = ''
// 这里拿到得值是一个数组,对数组进行循坏
arrValue.forEach((item,i) =>{
// replaceStr函数返回得是匹配后得到得值也就是<li>和内容,每一次匹配就把内容相加,再替换得时候就可以直接呈现出来
// 因为options参数要求是有键值得,所以这里得item需要有键值
listArr = listArr + replaceStr(result[2],{item})
})
// 把上面获得得内容进行替换
data = data.replace(result[0],listArr)
}
}
// end方法就是打印出来
// 因为已经把render函数复制给res,并且上面使用箭头函数,这里得this就是res
this.end(data)
}))
}
function replaceStr(data,options){
let reg = /\{\{(.*?)\}\}/igs
let result;
// 下面以循环的方式来多次执行exec方法来匹配全部值出来
while (result= reg.exec(data)) {
// 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
let strKey = result[1].trim()
// 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
let strValue = options[strKey]
data = data.replace(result[0],strValue)
}
return data
}
a.run(80,()=>{
console.log("服务器其启动");
})
其实上面这段代码有可以改进得地方,假如要匹配得是一个数组里面得对象
title:'bb',
bef:'22222222222222222222222222222222222222222',
stars:[
{name:'aa',sex:'bb'}
]
怎么把上面得值匹配到下面得html中呢
<ul>
{%for {stars} %}
<li>{{item.name}}</li>
<li>{{item.sex}}</li>
{%endfor%}
</ul>
其实只需要再根据键值获取值得时候,改成eval方法来对获取值进行加工就行,如代码
function replaceStr(data,options){
let reg = /\{\{(.*?)\}\}/igs
let result;
// 下面以循环的方式来多次执行exec方法来匹配全部值出来
while (result= reg.exec(data)) {
// 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
let strKey = result[1].trim()
// 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
// let strValue = options[strKey]
let strValue = eval('options.'+strKey) // 再这里使用这个方法,这个方法把里面得字符串当成js代码来执行
data = data.replace(result[0],strValue)
}
return data
}
实现使用正则来写动态路径
let http = require('http')
let path = require('path')
let fs = require('fs')
class app {
constructor(){
this.server = http.createServer()
this.objEvent = {}
this.server.on('request',(req,res)=>{
let pathObj =path.parse(req.url)
let pathAll = pathObj.dir
for (const key in this.objEvent) { // 第一步,从这里开始,因为调用on会弄进对象中,循坏对象拿出on上面的路径
let regstr = key
let reg = new RegExp(key,'igs') // 生成正则对象
if (reg.test(req.url)) { // 然后匹配网页上填写的路径是否符合正则
res.render = render
req.path1 = pathObj.base
this.objEvent[key](req,res) // 符合就执行
break;
}
}
// if (pathAll in this.objEvent) {
// res.render = render
// // 把路径后面得传给下面req
// req.path1 = pathObj.base
// this.objEvent[pathAll](req,res)
// }else{
// res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
// res.end('<h1>404<h1>')
// }
})
}
on(url,fn)
this.objEvent[url] = fn;
}
run(port,callback){
this.server.listen(port,callback)
}
}
let a = new app() // 下面的on里面使用正则路径
a.on('^\/$',(req,res)=>{
res.end('aaa')
})
a.on('/aa/(.*)',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
if (req.path1 === 'index') {
res.end('<h1>我得</h1>')
}else{
res.end('<h1>其他</h1>')
}
})
// 下面就进行动态渲染,通关url的的值来动态渲染出内容
a.on('/movie/[01]',(req,res)=>{
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
let movie=[
{
title:'aa',
bef:'11111111111111111111111111111111111111111',
stars:['aaa','bbb','ccc']
},
{
title:'bb',
bef:'22222222222222222222222222222222222222222',
stars:[
{name:'aa',sex:'bb'}
]
}
]
// 这里就是把绑定url里面的值来把序列号里面的值
let index = req.path1
// res.end(movie[index].title)
res.render(movie[index],'./index.html')
})
function render(options,path) {
fs.readFile(path,{encoding:'utf-8',flag:'r'},( (err,data)=>{
if (err) {
}else{
let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
let result = ''
while (result = reg.exec(data)) {
let arrKey = result[1].trim()
let arrValue = options[arrKey]
let listArr = ''
arrValue.forEach((item,i) =>{
listArr = listArr + replaceStr(result[2],{item})
})
data = data.replace(result[0],listArr)
}
}
this.end(data)
}))
}
function replaceStr(data,options){
let reg = /\{\{(.*?)\}\}/igs
let result;
// 下面以循环的方式来多次执行exec方法来匹配全部值出来
while (result= reg.exec(data)) {
// 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
let strKey = result[1].trim()
// 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
// let strValue = options[strKey]
let strValue = eval('options.'+strKey)
data = data.replace(result[0],strValue)
}
return data
}
a.run(80,()=>{
console.log("服务器其启动");
})