文章目录

  • 1 统一处理服务器资源:
    • 1.1 关于fs.readdir() 文件目录读取:
    • 1.2 模板引擎:
      • 1.2.1 在node中使用模板引擎:
      • 1.2.2 each :
  • 2 留言板:
    • 2.1 实现功能:
    • 2.2 服务器路径:
    • 2.3 实现:
    • 2.4 实现效果:
  • 3 url 核心模块:

1 统一处理服务器资源:

var http = require('http');
var fs = require('fs');var server = http.createServer();
var wwwDir = 'F:/mdcompile/Typora/mdtotal/nodejs/代码/resource';
// var wwwDir = '../resource';
// 以上两种路径方式都可以完成访问server.on('request',function(req,res){var url = req.url;var filepath = '/index.html';if (url !== '/' ) {filepath = url;} fs.readFile(wwwDir + filepath,function(err,data) {if (err) {return res.end('404 Not Found.');}res.end(data);})
})
server.listen(3000,function () {console.log("server is running ...");
})

1.1 关于fs.readdir() 文件目录读取:

var fs = require('fs');fs.readdir('F:/mdcompile/Typora/mdtotal/nodejs/代码/resource',
function (err,files) {if (err) {return console.log('目录不存在');}console.log(files);
});

1.2 模板引擎:

art-template 不仅可以在浏览器使用,也可以在node中使用。

实现目录列表:

// 服务端代码
var http = require('http');
var fs = require('fs');
var template = require('art-template');var server = http.createServer();
var wwwDir = 'F:/mdcompile/Typora/mdtotal/nodejs/代码/resource';
server.on('request',function(req,res) {var url = req.url;// 将要用到模板引擎的页面,读取fs.readFile('./template-apache.html',function (err,data) {if (err) {return res.end('404 Not Found');};// 读取目录fs.readdir(wwwDir,function (err,files) {if (err) {return res.end('Can not find www dir.');};// data对应被读取的页面,它本来时二进制数据流,但是鉴于模板引擎识别的是字符串,因此转为字符串var htmlStr = template.render(data.toString(),{files:files})// 将被模板引擎替换过的网页字符串返回,浏览器能够识别标签,因此结果成了页面res.end(htmlStr);});});
});
server.listen(3000,function () {console.log('running...');
});
// template-apache.html 代碼
<html dir="ltr" lang="zh" i18n-processed="">
<head><meta charset="utf-8"><meta name="google" value="notranslate"><style>h1 {border-bottom: 1px solid #c0c0c0;margin-bottom: 10px;padding-bottom: 10px;white-space: nowrap;}table {border-collapse: collapse;}th {cursor: pointer;}td.detailsColumn {-webkit-padding-start: 2em;text-align: end;white-space: nowrap;}a.icon {-webkit-padding-start: 1.5em;text-decoration: none;}a.icon:hover {text-decoration: underline;}a.file {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat;}a.dir {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat;}a.up {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;}html[dir=rtl] a {background-position-x: right;}#parentDirLinkBox {margin-bottom: 10px;padding-bottom: 10px;}#listingParsingErrorBox {border: 1px solid black;background: #fae691;padding: 10px;display: none;}</style><title id="title">{{ title }}</title>
</head><body><div id="listingParsingErrorBox">糟糕!Google Chrome无法解读服务器所发送的数据。请<a href="http://code.google.com/p/chromium/issues/entry">报告错误</a>,并附上<a href="LOCATION">原始列表</a></div><h1 id="header">D:\Movie\www\ 的索引</h1><div id="parentDirLinkBox"style="display:none"><a id="parentDirLink" class="icon up"><span id="parentDirText">[上级目录]</span></a></div><table><thead><tr class="header" id="theader"><th onclick="javascript:sortTable(0);">名称</th><th class="detailsColumn" onclick="javascript:sortTable(1);">大小</th><th class="detailsColumn" onclick="javascript:sortTable(2);">修改日期</th></tr></thead>// 此处对应art-template模板引擎可识别的{{}},即字符串替换部分<tbody id="tbody">{{each files}}<tr><td data-value="apple/"><a class="icon dir" href="/D:/Movie/www/apple/">{{$value}}/</a></td><td class="detailsColumn" data-value="0"></td><td class="detailsColumn" data-value="1509589967">2017/11/2 上午10:32:47</td></tr>{{/each}}</tbody></table>
</body></html>

1.2.1 在node中使用模板引擎:

  • 使用步骤:

    • 1 安装 npm install art-template

    • 2 在需要使用的文件模板中加载art-template。该命令在哪执行就会把包下载到哪里,默认会下载到node_modules中。node_modules一旦下载后是不支持更改的。参数中的 art-template 就是所下包的名字。

      • var template = require('art-template')
    • 3 查看文档,使用模板引擎的 API

fs.readfile() :读取到的数据是默认二进制。

模板引擎的 render 方法接收的是字符串。

在node中如何使用模板引擎:(下图与上图结合即服务端渲染)

render(): 参数分别为,字符串与字符串中所用到的数据集。

HTML将字符串存放到了script中,而node将字符串存放的单一的文件中 。

1.2.2 each :

each 是 art-template 的模板语法,专属的。

  • {{each 被遍历数据集}}
  • {{$value}}
  • {{/each}}

2 留言板:

2.1 实现功能:

  1. 在首页查看所有留言。
  2. 发表留言时,跳转到另一个界面。
  3. 留言成功会跳转回首页,即可看到留言。
  4. 发生错误跳转到 404 页面。
  5. 注:
  • ​ 将所需的模块放在文件模块的最上面,避免在使用中途导入依赖包。
  • ​ 不推荐将服务端文件与页面文件放在同一个文件夹下。
  • ​ 浏览器收到html响应内容之后,就要开始从上到下一次解析,挡在解析的过程中,如果发现:link、script、iframe、img、video、audio等具有 src 或者 href(link) 属性标签(-- 外链标签 --)的时候,浏览器会自动对这些资源发起新的请求,如果修改了这些内容的外链服务端是不用重启的。(这里不包括a链接)页面中的每一个资源都是一个请求
  • ​ 将文件路径转化为服务器路径,虽然实质上任然是在访问文件路径,但是我们在引用路径时可以写成服务器路径的形式。
  • ​ 表单提交分为两种:其一,默认的提交行为;其二,表单异步提交。

2.2 服务器路径:

var http = require('http');
var fs = require('fs');
// 简写创建服务
http.createServer(function (req,res) {var url = req.url;//首页if (url === '/' ) {fs.readFile('./views/index.html',function (err, data) {if (err) {return res.end('404 Not Found');}res.end(data);});}//在服务器端将所有静态资源引入路径都换成服务器路径,这是控制客户端浏览资源的前提//公开静态资源文件夹,即由服务器确定哪些内容是客户端可以看的,else if (url.indexOf('/public') === 0) {fs.readFile('.' + url,function (err,data) {if (err) {return res.end('404 Not Found.')}res.end(data);});} else {// 处理页面的404状况fs.readFile('./views/404.html',function (err,data) {if (err) {return res.end('404 Not Found.')}res.end(data);})}
}).listen(3000,function(){console.log("server is running");
})

2.3 实现:

面向客户的界面:

// index.html 即留言板的首页
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>留言本</title><!-- / 在这里就是 url 根路径的意思。浏览器在真正发请求的时候会最终把 http://127.0.0.1:3000 拼上不要再写文件路径了,把所有的路径都想象成 url 地址--><link rel="stylesheet" href="/public/lib/bootstrap/bootstrap.css">
</head>
<body><div class="header container"><div class="page-header"><h1>峡谷趣闻录<small>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;今日新篇</small></h1><a class="btn btn-success" href="/post">发表留言</a></div></div><div class="comments container"><ul class="list-group">{{each comments}}<li class="list-group-item">{{ $value.name }}说:{{ $value.message }} <span class="pull-right">{{ $value.dateTime }}</span></li>{{/each}}</ul></div>
</body>
</html>
// post.index 留言页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title><link rel="stylesheet" href="/public/lib/bootstrap/bootstrap.css">
</head>
<body><div class="header container"><div class="page-header"><h1><a href="/">首页</a> <small>发表评论</small></h1></div></div><div class="comments container"><!-- 以前表单是如何提交的?表单中需要提交的表单控件元素必须具有 name 属性表单提交分为:1. 默认的提交行为2. 表单异步提交action 就是表单提交的地址,说白了就是请求的 url 地址method 请求方法getpost--><form action="/pinglun" method="get"><div class="form-group"><label for="input_name">来者姓名</label><input type="text" class="form-control" required minlength="2" maxlength="10" id="input_name" name="name" placeholder="请写入你的姓名"></div><div class="form-group"><label for="textarea_message">留言</label><textarea class="form-control" name="message" id="textarea_message" cols="30" rows="10" required minlength="5" maxlength="20"></textarea></div><button type="submit" class="btn btn-default">发表</button></form></div>
</body>
</html>
// 404.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><h1>抱歉!  您访问的页面失联啦...</h1>
</body>
</html>

服务器:

// app application 应用程序
// 把当前模块所有的依赖项都声明再文件模块最上面
// 为了让目录结构保持统一清晰,所以我们约定,把所有的 HTML 文件都放到 views(视图) 目录中
// 我们为了方便的统一处理这些静态资源,所以我们约定把所有的静态资源都存放在 public 目录中
// 哪些资源能被用户访问,哪些资源不能被用户访问,我现在可以通过代码来进行非常灵活的控制
// / index.html
// /public 整个 public 目录中的资源都允许被访问
// 前后端融会贯通了,为所欲为var http = require('http')
var fs = require('fs')
var url = require('url')
var template = require('art-template')var comments = [{name: '张三',message: '今天天气不错!',dateTime: '2015-10-16'},{name: '张三2',message: '今天天气不错!',dateTime: '2015-10-16'},{name: '张三3',message: '今天天气不错!',dateTime: '2015-10-16'},{name: '张三4',message: '今天天气不错!',dateTime: '2015-10-16'},{name: '张三5',message: '今天天气不错!',dateTime: '2015-10-16'}
]// /pinglun?name=的撒的撒&message=的撒的撒的撒
// 对于这种表单提交的请求路径,由于其中具有用户动态填写的内容
// 所以你不可能通过去判断完整的 url 路径来处理这个请求
//
// 结论:对于我们来讲,其实只需要判定,如果你的请求路径是 /pinglun 的时候,那我就认为你提交表单的请求过来了http.createServer(function (req, res) { // 简写方式,该函数会直接被注册为 server 的 request 请求事件处理函数// 使用 url.parse 方法将路径解析为一个方便操作的对象,第二个参数为 true 表示直接将查询字符串转为一个对象(通过 query 属性来访问)var parseObj = url.parse(req.url, true)// 单独获取不包含查询字符串的路径部分(该路径不包含 ? 之后的内容)var pathname = parseObj.pathnameif (pathname === '/') {fs.readFile('./views/index.html', function (err, data) {if (err) {return res.end('404 Not Found.')}var htmlStr = template.render(data.toString(), {comments: comments})res.end(htmlStr)})} else if (pathname === '/post') {// 其它的都处理成 404 找不到fs.readFile('./views/post.html', function (err, data) {if (err) {return res.end('404 Not Found.')}res.end(data)})} else if (pathname.indexOf('/public/') === 0) {// /public/css/main.css// /public/js/main.js// /public/lib/jquery.js// 统一处理://    如果请求路径是以 /public/ 开头的,则我认为你要获取 public 中的某个资源//    所以我们就直接可以把请求路径当作文件路径来直接进行读取fs.readFile('.' + pathname, function (err, data) {if (err) {return res.end('404 Not Found.')}res.end(data)})} else if (pathname === '/pinglun') {// 注意:这个时候无论 /pinglun?xxx 之后是什么,我都不用担心了,因为我的 pathname 是不包含 ? 之后的那个路径// 一次请求对应一次响应,响应结束这次请求也就结束了// res.end(JSON.stringify(parseObj.query))// 我们已经使用 url 模块的 parse 方法把请求路径中的查询字符串给解析成一个对象了// 所以接下来要做的就是://    1. 获取表单提交的数据 parseObj.query//    2. 将当前时间日期添加到数据对象中,然后存储到数组中//    3. 让用户重定向跳转到首页 ///       当用户重新请求 / 的时候,我数组中的数据已经发生变化了,所以用户看到的页面也就变了var comment = parseObj.querycomment.dateTime = '2017-11-2 17:11:22'comments.unshift(comment)// 服务端这个时候已经把数据存储好了,接下来就是让用户重新请求 / 首页,就可以看到最新的留言内容了// 如何通过服务器让客户端  重定向  ?//    1. 状态码设置为 302 临时重定向//        statusCode//    2. 在响应头中通过 Location 告诉客户端往哪儿重定向//        setHeader// 如果客户端发现收到服务器的响应的状态码是 302 就会自动去响应头中找 Location ,然后对该地址发起新的请求// 所以你就能看到客户端自动跳转了res.statusCode = 302res.setHeader('Location', '/')res.end()} else {// 其它的都处理成 404 找不到fs.readFile('./views/404.html', function (err, data) {if (err) {return res.end('404 Not Found.')}res.end(data)})}}).listen(3000, function () {console.log('running...')})// Node 不适合从来没有接触过服务端的人学习
// 如果想要真正的学号服务端,还是老牌的 Java、PHP 这些平台
// Node 不是特别适合入门服务端,但不代表 Node 不强大
// Node 很厉害,具有经验的人可以玩儿的非常的牛
// 不适合新手的原因就在于比较偏底层、而且太灵活
// Java、PHP 好入门的原因就在于:这些平台屏蔽了一些底层
// res.redirect('重定向')// 晚上写案例照着下面的步骤写:
// 1. / index.html
// 2. 开放 public 目录中的静态资源
//    当请求 /public/xxx 的时候,读取响应 public 目录中的具体资源
// 3. /post post.html
// 4. /pinglun
//    4.1 接收表单提交数据
//    4.2 存储表单提交的数据
//    4.3 让表单重定向到 /
//        statusCode
//        setHeader// 明天:
// 模块系统
// Express(第三方 Web 开发框架)
//    这两做的事儿,在框架里面就是一个 API 的事儿
//    使用框架的目的就是让我们更加专注于业务,而不是底层细节

2.4 实现效果:

3 url 核心模块:

url.parse():

url.parse(’/pinglun?name=&message=’,true):可以将获取的语句转换成对象。

一次请求对应一个响应,响应结束这次请求也就结束了。因此,需要将当此的响应添加在请求最末尾。

【Nodejs】留言板案例相关推荐

  1. Nodejs留言板案例总结

    1. 案例需求分析 主页 主页一开始呈现的是一部分用户的评论数据, 其中一条评论数据包含的信息有: 用户名, 用户评论内容,评论时间. 页面左上角有一个 发表留言 的按钮,用户点击按钮就会跳转到填写留 ...

  2. React(05):使用react完成简单留言板案例

    前言 之前学了react基本语法和jsx/组件化,这里还是用ts学习时候的本地留言板案例来实践一下之前的学习语法: 正文 注意点 引入react.react-dom.babel,development ...

  3. 三、案例:留言板 url.parse()

    1. url.parse()的使用 2. 留言板案例 index.html: <!DOCTYPE html> <!-- saved from url=(0027)http://192 ...

  4. web前端必学功法之一:留言板

    web前端必学功法之一:留言板 案例效果: css部分 <style>.container{width: 600px;}.mes-board{margin: 25px 0;padding: ...

  5. NLP自然语言处理—主题模型LDA案例:挖掘人民网留言板文本数据

    全文链接:tecdat.cn/?p=2155 随着网民规模的不断扩大,互联网不仅是传统媒体和生活方式的补充,也是民意凸显的地带.领导干部参与网络问政的制度化正在成为一种发展趋势,这种趋势与互联网发展的 ...

  6. Tornado入门案例:留言板

    Tornado入门案例:留言板 前言 Tornado框架 实操:搭建一个hello world 完整代码与前端页面 前言 所使用的框架:Torndao框架 python 主流的开发框架 Tornado ...

  7. 机器学习实战4.2 朴素贝叶斯案例:屏蔽社区留言板的侮辱性言论

    机器学习实战4.2 朴素贝叶斯案例:屏蔽社区留言板的侮辱性言论 参考地址:https://cuijiahua.com/blog/2017/11/ml_4_bayes_1.html 一.引子 很久没更新 ...

  8. Vue基础案例(水果搜索,购物车,todolist,留言板,跑马灯)

    Vue基础案例(水果搜索,购物车,todolist,留言板,跑马灯) 01.水果搜索案例 思路以及运用知识点 通过computed计算 keyword与list ,算出findlist 如果list中 ...

  9. 主题模型(LDA)案例:挖掘人民网留言板文本数据

    原文链接://tecdat.cn/?p=2155 随着网民规模的不断扩大,互联网不仅是传统媒体和生活方式的补充,也是民意凸显的地带.领导干部参与网络问政的制度化正在成为一种发展趋势,这种趋势与互联网发 ...

最新文章

  1. 【Python-ML】SKlearn库密度聚类DBSCAN模型
  2. 【MPI编程】MPI_Bcast广播讲解和使用
  3. Java语言程序设计实验指导_《java语言程序设计》上机实验指导手册(4).doc
  4. uat环境是什么环境_环境污染会对环境造成怎样的损害?污水处理活性炭能起到什么效果呢?...
  5. Python之精心整理的二十五个文本提取及NLP相关的处理案例
  6. 建议 Solr 用户更新 Apache POI
  7. 请解释Spring Bean 的生命周期?
  8. 百度地图api的密钥申请地址
  9. 评分组件(RatingBar)
  10. Windows下的函数
  11. mysql 函数定义常量_php如何定义一个自定义常量
  12. freeswitch添加tls加密
  13. python字符串出栈方法_Python学习之路_day_04(字符串与列表的内置方法)
  14. linux yum资源下载,yumdownloader命令 – 从yum存储库下载rpm包
  15. 会议panel是什么意思中文_topanel中文是什么意思
  16. 安卓手机如何投屏到电视上_孩子在家上课,如何把手机投屏到电视上
  17. 从0开始学代码第五周!!!
  18. vs使用html写出分层次字,Javascript 升阶 10-2 样版字面额方法:VSCode 配搭 Emmet 编写 HTML 构造...
  19. 漫谈递归——递归需要满足的两个条件
  20. RecyclerView图片错乱复用问题

热门文章

  1. SpringBoot将数据放入Excel里面通过浏览器直接下载到本地
  2. (二)linux下ping不通的解决方法
  3. OFDM技术与FDM技术区别
  4. Delphi 多线程编程(1)
  5. 手机进水开机android,手机进水后开机只有启动画面进不了桌面怎么处理?
  6. idea 导入别人的项目后,显示包的名称错误does not correspond to the file path
  7. zip压缩包密码解密
  8. 数组中的slice()方法和splice()
  9. 正则表达式习题解答-Python核心编程3 第一章
  10. devc++ value of xxx too large for field of 4 bytes at xxx 并且源文件未编译