zoukankan      html  css  js  c++  java
  • node-day2

    (1)前言

      大纲:

        

      其他:

        

         详见Markdown标记语言 

    (2)代码风格及封号详见下节

    (3)初步实现Apache功能

      1、审查node进程

        

         Ctrl+C关闭node服务后,再次审查

        

         此时便没有了node进程

      2、Apache服务

    Apache服务器软件---默认有一个www目录,所有存放在www目录中的资源都可以通过网址来浏览

        

         Apache默认功能,默认显示index.html

         如上所示,在c盘下新建app目录,里面新建多个文件,接下来想实现某个效果:类似于Apache,可以通过文件路径直接访问读取www下的文件,在网页内展示

         

         

         

      3、类似于Apache统一处理资源

         

         接续处理,完善读取

        

      4、实例验证如下

        ①在D盘下新建www目录

          

        ②放入相应文件

           

        ③ 编写代码实现功能

    // 引入网络构建服务模块
    var http = require('http')
    // 引入fs文件系统模块
    var fs = require('fs')
    
    // 创建server服务器
    var server = http.createServer()
    
    var wwwDir = 'D:/www'
    //接收请求,处理响应事件
    server.on('request',function(req,res){
        var url = req.url
        var filePath = '/index.html'
        if(url !== '/'){
            filePath = url
        }
        fs.readFile(wwwDir+filePath,function(error,data){
            if(error){
                return res.end('404 Not Found')
            }
            res.end(data)
        })
    })
    
    // 启动服务器,监听端口
    server.listen(3000,function(){
        console.log('服务器启动成功,端口号为3000...')
    })

      此时,启动服务器后便可以通过设定好的路径去访问相应文件

      

       

            

       

       需求升级:要求有图形操作页面,如下所示

        

    (4)Apache目录列表模板

    首先需要了解Apache默认行为,即如果目录下有index.html,则显示该页面。如果没有则显示目录列表

      1、删除index.html文件。显示目录列表

      2、编写代码

        ①访问模板页面(模板页面代码可以直接复制过来,模板代码参加下篇文章)

        

        

         ②问题解决

        

         ③读取目录API

        

        ④具体渲染见下节(5)

    代码及文件结构如下:

        

    // 引入网络构建服务模块
    var http = require('http')
    // 引入fs文件系统模块
    var fs = require('fs')
    
    // 创建server服务器
    var server = http.createServer()
    
    var wwwDir = 'D:/www'
    //接收请求,处理响应事件
    server.on('request',function(req,res){
        var url = req.url
        fs.readFile('./template.html',function(error,data){
            if(error){
                return res.end('404 Not Found')
            }
            res.end(data)
        })
    })
    
    // 启动服务器,监听端口
    server.listen(3000,function(){
        console.log('服务器启动成功,端口号为3000...')
    })

    此时启动服务器,便会查看到网页模板页面

    (5)Apache目录列表渲染

        1、分析

    接下来只需要将获取到的目录下的文件和文件名,替换到template.html即可

      2、读取文件目录

    var fs = require('fs')
    fs.readdir('D:/www',function(error,files){
        if(error){
            return console.log('目录不存在')
        }
        console.log(files)
    })

      

      3、结合Apache目录渲染①

    首先在模板里写入标记,后期替换

      4、结合Apache目录渲染②

     替换标记

    验证如下:

      5、结合Apache目录渲染③

    如何将文件名和目录名替换到template.html里
        1、在template.html中需要替换的位置预留一个特殊的标记(类似之前模板引擎的特殊标记)
        2、根据files生成需要的HTML内容

      第一步:预留位置存放特殊标记

        

      第二步:动态生成HTML内容

        

    (6)浏览器使用模板引擎artTemplate

      1、安装

        在当前目录下安装模板引擎,会自动下载到新创建的node_modules文件夹下

        

         

    artTemplate相关的依赖文件都会一起下载下来,所以下载完成后的目录会包含其他文件

        

         

      2、浏览器中使用模板引擎(注意:模板引擎不关心内容)

        

        模板引擎只关心{{}}八字符里面的内容,验证如下

        

      3、模板遍历语法

        

         

         注意:mustache八字胡语法

        

    (7)node.js使用模板引擎artTemplate

      1、步骤

        

      2、node中引用第三方脚本库,不能使用script,而是使用require导入

        

      3、文档API

        这里注意,浏览器的语法在这里无效,没有script标签

        

    浏览官方文档后的API:
        template.render('模板字符串',替换对象),验证如下

        

      4、替换HTML模板进行测试

    j    

         

         

         这样便可以实现node使用模板引擎解析替换对应内容,但这样模板内容太多,过于累赘,所以一般是从外部读取

      5、外部引入HTML模板

        

         接下来使用fs文件系统模块读取文件

        

         

      6、最后修改之前文件,不再手动拼接字符串

    接下来使用模板引擎解析替换HTML页面

        

         整体代码如下

    // 引入网络构建服务模块
    var http = require('http')
    // 引入fs文件系统模块
    var fs = require('fs')
    //引入模板引擎
    var template = require('art-template')
    
    // 创建server服务器
    var server = http.createServer()
    
    var wwwDir = 'D:/www'
    //接收请求,处理响应事件
    server.on('request',function(req,res){
        var url = req.url
        fs.readFile('./template-web.html',function(error,data){
            if(error){
                res.setHeader('Content-Type','text/plain;charset=utf-8')
                return res.end('404 Not Found')
            }
            fs.readdir(wwwDir,function(error,files){
                if(error){
                    return res.end('目录不存在')
                }
                /*使用模板引擎解析替换data里的模板字符串*/
                var htmlStr = template.render(data.toString(),{
                    files:files,
                    title:'网页标题'
                })
                /*发送解析替换过后的响应数据*/
                res.end(htmlStr)
            })
        })
    })
    
    // 启动服务器,监听端口
    server.listen(3000,function(){
        console.log('服务器启动成功,端口号为3000...')
    })
    template-web.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: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> <tbody id="tbody"> {{each files}} <tr> <td data-value="apple/"><a class="icon dir" href="#">{{$value}}/</a></td> <td class="detailsColumn" data-value="0"></td> <td class="detailsColumn" data-value="1509589967">2018/11/2 上午10:32:47</td> </tr> {{/each}} </tbody> </table> </body> </html>

      最终解析结果

      

        7、添加判断

    目前为止,已经做到了服务器端渲染。
    区别于之前的技术,在前端拿到数据,模板引擎解析替换,是浏览器做的。
    注意:这里使用服务器端+模板引擎进行了渲染,最早之前模板引擎是后端技术

       

      8、

    (8)客户端渲染+服务器端渲染

       1、客户端渲染

        

         所以一般会发两次请求,第一次请求页面字符串,第二次请求数据

      2、服务端渲染

        

         当然,ajax等异步请求也会用到,只是看具体应用场景

      3、如何判断网页是客户端渲染还是服务器渲染

    查看网页源代码,如果源代码里有页面对应内容,则是服务端渲染。如果没有页面对应内容,则是客户端渲染

        ①查看网页源代码,发现里面有商品信息,所以这里是服务端渲染

          

           

        ②查看商品评价,明显有异步操作,没有刷新页面,但局部更新了页面部分内容,这里便使用了客户端渲染技术

          

           如果是客户端后期动态追加的,便从源码里找不到相应内容

      4、小结

    分析后得出,商品列表为服务端渲染,在发送响应时,将页面和数据一起给了浏览器,可以在审查源代码里找到。
    而商品评价为客户端渲染,是客户端发送请求,后期动态生成的,审查源代码找不到。
    所以,一个网站既有服务端渲染,又有客户端渲染。

      5、SEO问题

    之所以将客户端渲染和服务器渲染结合,这里主要考虑SEO搜索引擎优化问题。
    ajax异步渲染的数据,使用爬虫无法获取,即客户端渲染不利于SEO

        

      6、使用场景

    如果需要考虑SEO搜索引擎优化,则必须使用服务端渲染,否则使用客户端渲染可以更快一些,用户体验也更好

    (9)【留言板案例】---处理网站里的静态资源

      需求:对之前文件做下完善,目录是目录样式,文件是文件样式,目录也可以点击进入,但这里已经对服务端渲染有了基本了解,所以接下来不再做处理

      接下来做个留言板案例

      1、启动服务简写

    将创建服务和监听端口合并到一步,简写如下

        

      2、读取模板文件

    为了让目录结构保持统一清晰,约定把所有的HTML文件都放到views目录中

        

      3、注意

        

        验证分析:

        

         

    分析:之所有有这么多请求,首先,页面是一个请求,页面里的相关资源也是请求

        此时网站之所以一直卡着不动,是因为没有对静态资源做处理

        

      4、服务端处理静态资源

    此时不可能一依次添加判断,为了统一处理这些静态资源,我们约定将所有静态资源都存放在public目录中。

           === >  

    除此之外,还可以包含lib目录,用于存放第三方包

        

         

         此时再次启动服务器测试,请求成功

    public目录已经开放开来,如果后期还用到静态资源,直接放到对应目录下即可。
    这里将bootstrap放到lib目录下,然后修改引用路径

        

         app.js完整代码如下:

    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(error,data){
                if(error){
                    return res.end('404 Not Found.')
                }
                res.end(data)
            })
        }else if(url.indexOf('/public/' === 0)){
            fs.readFile('.' + url,function(error,data){
                if(error){
                    return res.end('404 Not Found.')
                }
                res.end(data)
            })
        }
    }).listen(3000,function(){
        console.log('服务启动完毕,3000端口访问... ...')
    })

        此时便可以正确渲染了

        

       5、小结

    public专门用于存放客户端静态资源
    例如css、图片、js、jquery(服务端没有DOM,所以不可能用到jquery)

         客户端如果想用,引入即可

        

    (10)页面跳转+404

       1、输入无效url时,跳转至404页面

        这里之所以不用设置请求头信息类型,因为在404.html已经设置了元标签meta标签

        

         

    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(error,data){
                if(error){
                    return res.end('401 Not Found.')
                }
                res.end(data)
            })
        }else if(url.indexOf('/public/')=== 0){
            fs.readFile('.' + url,function(error,data){
                if(error){
                    return res.end('402 Not Found.')
                }
                res.end(data)
            })
        }else{
            fs.readFile('./views/404.html',function(error,data){
                if(error){
                    return res.end('403 Not Found.')
                }
                res.end(data)
            })
        }
    }).listen(3000,function(){
        console.log('服务启动完毕,3000端口访问... ...')
    })

      2、发表留言页面跳转

         点击留言时,跳转至留言页面

        

         

    (11)渲染评论首页

      1、首先在服务端写个数组,然后在模板页面进行遍历

          

           

           结果如下

        

      2、接下来在服务端使用模板引擎

    核心模块为node自带,不用安装
    第三方模块需要下载安装

        

        

        

         

    (12)处理表单get提交

      1、表单提交行为

    表单提交行为大概分为两种
        1、默认的提交行为(同步提交)
        2、异步提交

        

      2、点击后跳转到对应url

        

      3、url模块解析API

        将提交后的url进行解析,如下所示

        

         加入true参数,如下所示

        

    url模块解析API
        url.parse(url链接)
        url.parse(url链接,true)

      4、注意

        

      5、url模块

        

      6、使用url模块

    var http = require('http')
    var fs = require('fs')
    var template = require('art-template')
    var url = require('url')
    
    var comments = [
        {name:'tony',message:'你好tony,感觉人生达到了巅峰',data:'2016-02-12'},
        {name:'bob',message:'你好bob,感觉人生达到了巅峰',data:'2016-03-02'},
        {name:'jack',message:'你好jack,感觉人生达到了巅峰',data:'2016-11-18'}
    ]
    
    http.createServer(function(req,res){
        var parseObj = url.parse(req.url,true)
        /*单独获取不包含查询字符串的路径部分,该路径不包含?之后的内容*/
        var pathname = parseObj.pathname
        if(pathname === '/'){
            fs.readFile('./views/index.html',function(error,data){
                if(error){
                    return res.end('404 Not Found.')
                }
                var htmlStr = template.render(data.toString(),{
                    comments:comments
                })
                res.end(htmlStr)
            })
        }else if(pathname.indexOf('/public/')=== 0){
            fs.readFile('.' + pathname,function(error,data){
                if(error){
                    return res.end('404 Not Found.')
                }
                res.end(data)
            })
        }else if(pathname === '/post'){
            fs.readFile('./views/post.html',function(error,data){
                if(error){
                    return res.end('404 Not Found.')
                }
                res.end(data)
            })
        }else if(pathname === '/pinglun'){
            /*这里不能再判断url,因为是动态的,所以只需要判断pathname即可*/
            res.end(JSON.stringify(parseObj.query))
        }else{
            fs.readFile('./views/404.html',function(error,data){
                if(error){
                    return res.end('404 Not Found.')
                }
                res.end(data)
            })
        }
    }).listen(3000,function(){
        console.log('服务启动完毕,3000端口访问... ...')
    })

      

       

       现在已经收到数据,接下来开始进行下一步解析处理

      

    (13)表单提交重定向

      接着上面的操作

       1、如何通过服务器让客户端重定向(服务器重定向)

        先写个死数据测试下

                如何通过服务器让客户端重定向? 
                  1、设置状态码为302临时重定向(301为永久重定向)
                  2、在响应头中通过Location告诉客户端网哪里重定向
                  3、如果客户端发现收到的服务器响应状态码是302,就会自动去响应头中找Location然后对该地址发送新请求
                  4、因此便可以看到客户端自动跳

        

    else if(pathname === '/pinglun'){
            /*这里不能再判断url,因为是动态的,所以只需要判断pathname即可
            测试res.end(JSON.stringify(parseObj.query))
            */
            /*添加数据-注意:不是持久化存储,后期介绍*/
            var comment = parseObj.query
            comment.dateTime = '2017-11-3 12:12:30'
            comments.push(comment)
            /*重定向到首页*/
            /*
                如何通过服务器让客户端重定向? 
                  1、设置状态码为302临时重定向(301为永久重定向)
                  2、在响应头中通过Location告诉客户端网哪里重定向
                  3、如果客户端发现收到的服务器响应状态码是302,就会自动去响应头中找Location然后对该地址发送新请求
                  4、因此便可以看到客户端自动跳转
            */
            res.statusCode = 302
            res.setHeader('Location','/')
            res.end()/*结束响应*/
        }

        接下来做下测试,点击Network中的Preverse log保存重定向日志,然后提交数据

        

    浏览器发现状态码为302,然后去请求头Header里找Location,再次对新路径发起请求,进行重定向跳转

          

      2、接下来即可通过本地局域网ip进行访问测试

        

         

    (14)小结

      1、node底层

        

      2、步骤

        

      3、 接下来

        

    .

  • 相关阅读:
    Spring bean的实例化
    提交本地代码到github
    ORM框架——SQLAlchemy
    代码发布项目(三)——python操作git、代码发布流程(服务器管理、项目管理)
    代码发布项目(二)——django实现websocket(使用channels)、基于channels实现群聊功能、gojs插件、paramiko模块
    代码发布项目(一)——实现服务端主动给客户端推送消息(websocket)
    索引补充(索引种类,正确使用索引,其他注意事项,慢日志查询)
    mysql索引种类(索引种类和建立索引)
    centos6安装Docker遇到的问题(升级centos6内核)
    Django1.11下载安装xadmin
  • 原文地址:https://www.cnblogs.com/fightjianxian/p/12141763.html
Copyright © 2011-2022 走看看