路由(一)
通俗来讲,路由就是一个映射结构,区分不同的页面进行不同的操作逻辑。特别是对于大型单页面应用,利用路由来进行页面的跳转和重载是再正常不过的了,像Vue就有Vue-Router来构建路由,前端会通过get请求来传递某些参数,也会通过路由去访问某些静态资源,那么对于coaplay后端的我们来说,应该如何获取前端通过路由传过来的参数呢,今天记录的是node中的路由基础。
根据URL获取前端静态资源
我们从输入一个url到展示对应的页面做起:
先创建一个static目录,存放我们的静态资源(页面等),我创建的目录如下:
大概说一下各个文件夹的作用:
- static: 存放静态资源(页面,css, 图片等)
- api.js : 将来页面要调用的api接口(前端同学应该很熟悉了,通过api接口获取数据)
- router.js: 存放路由对应关系
- server.js: 搭建服务器的文件
先说一下大概思路: 首先搭建服务器,根据不同的url返回给前端不同的数据,等到这个功能实现以后,完善login页面,尝试在前端调用api接口分别使用get和post的方式来发送请求,后端依次根据接收的参数返回响应结果,并且前端能访问到相应的响应结果。大概就是这个样子,下面我们来实现一下:
搭建服务器(server.js):
const http = require('http')
const fs = require('fs')
const server = http.createServer()
server.on('request', (req, res) => {
const myUrl.pathname = new URL(req.url, "http://10.45.129.66")
switch (pathname) {
case "/login":
res.writeHead(200, { "Content-Type": "text/html;chartset=utf8" })
res.write(fs.readFileSync("./static/login.html"), "utf-8")
break
case "/home":
res.writeHead(200, { "Content-Type": "text/html;chartset=utf8" })
res.write(fs.readFileSync("./static/home.html"), "utf-8")
break
default:
res.writeHead(200, { "Content-Type": "text/html;chartset=utf8" })
res.write(fs.readFileSync("./static/404.html"), "utf-8")
}
}).listen(10086, () => {
console.log("10086")
})
在以上基础上,如果你的文件路径存放正确,并且模块化导入没有问题,不出意外的话你应该可以试试在url访问:http://localhost:10086/login,就可以跳转到login页面,http://localhost:10086/home,就可以访问home页面。
但是,以上代码太过于臃肿,而且后期如果每新增一个页面,我就要在switch里面新增一个case吗?这样不好,我们做个精简: 将switch代码块剥离出来,做成一个函数或者对象,这样的话server.js里的代码就十分简洁了。
//server.js
const http = require('http')
const route = require('./router.js') //将抽离出的方法放置router.js文件中
const server = http.createServer()
const server = http.createServer()
server.on('request', (req, res) => {
const myUrl = new URL(req.url, "http://10.45.129.66")
route(res,myUrl.pathname)
res.end()
}).listen(10086, () => {
console.log("10086")
})
//router.js函数写法
const fs = require('fs')
function route(res, pathname) {
// 可以用switch分支
switch (pathname) {
case "/login":
res.writeHead(200, { "Content-Type": "text/html;chartset=utf8" })
res.write(fs.readFileSync("./static/login.html"), "utf-8")
break
case "/home":
res.writeHead(200, { "Content-Type": "text/html;chartset=utf8" })
res.write(fs.readFileSync("./static/home.html"), "utf-8")
break
default:
res.writeHead(200, { "Content-Type": "text/html;chartset=utf8" })
res.write(fs.readFileSync("./static/404.html"), "utf-8")
}
}
module.exports = route
封装成函数的样子好像还是避免不了得一个一个加,而且有很多冗余代码,不如采用对象的格式来试一下:
//router.js
function publicMethod(req, res, pathname, type) {
//req:请求参数
//res:响应参数
//pathname: url路径
//type: Conten-type的类型,表示请求中的媒体信息的格式
res.writeHead(200, { "Content-Type": `${type};chartset=utf8` })
res.write(fs.readFileSync(pathname), "utf-8")
res.end()
}
const routeTwo = {
"/login": (req, res) => { publicMethod(req, res, './static/login.html', 'text/html') },
"/home": (req, res) => { publicMethod(req, res, './static/home.html', "text/html") },
"/favicon.ico": (req, res) => { publicMethod(req, res, './static/test.ico', 'image/x-icon') }
}
module.exports = routeTwo
那对应的server调用也需要修改一下:
const http = require('http')
const routeTwo = require('./router.js')
const server = http.createServer()
server.on('request', (req, res) => {
const myUrl = new URL(req.url, "http://10.45.129.66")
try {
routeTwo[myUrl.pathname](res)
} catch (err) {
routeTwo["/404"](res)
}
}).listen(10086, () => {
console.log("10086")
})
这样呢,是不是看着能简单点了呢?而且基础功能也实现了呀~