Node.js 笔记 - 第六节 - Node.js 内置功能

一、fs模块

fs模块最重要的一个功能就是异步读取文件(readFile),第一个参数文件,第二个参数是回调函数。

fs.readFile('文件名', (err, data) => {
  if (err) throw err;
  console.log(data);
});

我们现在要结合这个方法进行一个页面的读取内容。

var http = require("http");
var fs = require("fs");
// 创建服务器
var server = http.createServer(function(req,res){
  fs.readFile("./public/zhoujielun.html",function(err,data) {
    res.end(data)
  })
})
// 监听
server.listen(3000)



二、路由(※)

上面的案例,我无论输入什么URL都会显示zhoujielun.html这个页面。

var server = http.createServer(function(req,res){
  fs.readFile("./public/zhoujielun.html",function(err,data) {
    res.end(data)
  })
})


上面的路由地址是随便写的,你会发现无论路由什么样,都会显示该页面,此时我们就可以利用这个特性完成我们的路由设计。
我们可以通过req.url()得到用户输入的URL地址。

var server = http.createServer(function(req,res){
  // 设置字符集
  res.setHeader("Content-Type","text/html;charset=UTF8");
  if(req.url === "/star/zhoujielun") {
    fs.readFile("./public/zhoujielun.html",function(err,data) {
      res.end(data)
    })
  } else if(req.url === "/star/wanglihong"){
    fs.readFile("./public/wanglihong.html",function(err,data) {
      res.end(data)
    })
  } else {
    res.end("无页面显示")
  }
})

比如我们访问/star/zhoujielun

再比如我们要访问/star/wanglihong

我们之前的认知是路由即文件夹,但是我们Node.js颠覆了我们的认知,通过路由进行页面的读取,这个就是顶层路由设计。
顶层路由设计:
△:物理文件层级的URL是没有任何关系的;
△:Node.js是可以做顶层路由设计的!一个页面的URL是可以自定义的;
△:用户输入的URL是可以映射任何HTML页面的;
现在有很多大型网站都是这种顶层路由设计,比如知乎。
https://www.zhihu.com/people/guozi-51-501/answer        用户的回答
https://www.zhihu.com/people/guozi-51-501/zvideos       用户的提问
https://www.zhihu.com/people/guozi-51-501/asks            用户的提问
https://www.zhihu.com/people/guozi-51-501/posts          用户的文章
https://www.zhihu.com/people/guozi-51-501/columns     用户的专栏
老一代的路由实际上都是映射服务器的物理文件夹目录。比如https://weibo.com/p/1005052970323452/photos?from=page_100505&mod=TAB#place。

三、模仿知乎路由的顶层设计。

var server = http.createServer(function(req,res){
  // 设置字符集
  res.setHeader("Content-Type","text/html;charset=UTF8");
  // 得到用户的url
  var url = req.url;
  // 使用正则表达式进行信息的获取
  var arr = url.match(/\/user\/(.+)\/(.+)$/);
  console.log(arr)
  // 如果没有对应的路由地址,抛出错误
  if(!arr) {
    res.end("<h1>无页面显示</h1>")
    return;
  }
  // 获取信息
  // 正则的第一项
  var $1 = arr[1];
  // 正则的第二项
  var $2 = arr[2]
  // 数据模拟
  var user = {
    "zhoujielun":"周杰伦",
    "zhangyi":"张译",
    "wujing":"吴京",
    "yiyangqianxi":"易烊千玺",
  };
  var list = {
    "post":"文章",
    "ask":"提问",
    "answer":"回答",
    "pins":"想法",
  }
  // 页面返回的内容
  res.write("<h1>"+user[$1]+"你好</h1>")
  res.end("<h2>欢迎来到"+list[$2]+"版块</h2>")
})

我们就模拟了知乎的路由设计。


四、顶层路由设计会遇到的问题。

我们请求zhoujielun.html文件为例,路由地址是/star/zhoujielun
页面的内容:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>你好,我是周杰伦</h1>
  <img src="images/zhoujinlun.jpg" alt="">
</body>
</html>


通过上图你会发现页面中只有文字的展示,没有图片的展示,但是HTML结构中是有img标签的,为什么不能加载?
答:该图片的URL路径是没有物理文件夹的。
现在这张图片的真实物理地址是:http://127.0.0.1:3000/star/images/zhoujielun.html,但是图片物理存放地址是在:C:\node_study\public\images,所以一定不能按需加载。
那么解决办法就是对每一张图片进行请求设置。

var server = http.createServer(function(req,res){
  console.log(req.url)
  // 设置字符集
  res.setHeader("Content-Type","text/html;charset=UTF8");
//对页面的内容进行请求
  if(req.url === "/star/zhoujielun") {
    fs.readFile("./public/zhoujielun.html",function(err,data) {
      res.end(data)
})
//对页面的图片地址进行请求
  } else if(req.url=="/star/images/zhoujinlun.jpg"){
    res.setHeader("Content-Type","image/jpg");
    // 读取图片
    fs.readFile("./public/images/zhoujinlun.jpg",function(err,data){
      res.end(data)
    })
  }else{
    res.end("无页面显示")
  }
})


问题来了,如果图片的数量很多怎么办?每一张都势必要进行对路由的请求和渲染,也就是要给每一张图片开辟路由地址,不仅仅是图片,其他文件也是一样的。
解决办法就是我们后面要学习的express的中间件来静态化一个文件夹。目的就是当前这个文件夹内部的文件自动就有了URL路由,不用每个都单独设置。
需要注意的是:使用Node.js进行请求文件或资源的时候,需要设置对应的Content-Type,就是文件的请求类型。
常见的类型有:
text/html:HTML格式
text/css:CSS格式
text/plain:纯文本格式
text/xml:XML格式
image/gif:GIF文件格式
iamge/jpeg:JPEG图片格式
image/png:PNG图片格式

res.setHeader("Content-Type","text/html;charset=UTF8") //HTML
res.setHeader("Content-Type"," text/css ") //CSS
res.setHeader("Content-Type"," image/png ") //png格式的图片