NodeJS_02

NodeJS七天课程学习笔记_第2天

JS编码风格:

[JavaScript Standard Style](https://standardjs.com/readme-zhcn.html)

[Airbnb JavsScript Style](https://mitsuruog.github.io/javascript-style-guide/)

当采用无分号分格时,需要特别注意,以下3种情况:

行首是 ( )     [  ]    ` 这3个时,必须在前面加上分号,否则报错

注意: 第3个是 esc键下方的 反引号

反引号是 ES6 中新增的字符串包裹方式,即模板字符串

它 支持非常方便的拼接变量 和 换行 ,类似于pre标签

比如:

;(function (){

console.log(‘beyond’);

})()

再比如:

;[5,2,6,7].forEach(function (element) {

console.log(element)

})

再比如

;`未闻花名`.toString()

因此你可能会看到一些第3方代码,一上来就是前面打了一个分号,目的就是避免遇到上面3种情况报错

NodeJS七天课程主讲老师:李鹏周

node_11.js实现功能如下:

地址栏里输入任何路径,如果存在,则读取该文件并输出显示

如果不存在,则显示404 Not Found

代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

// http请求演示
// 导入http模块
var http = require('http')
var server = http.createServer()
function onReciveFuntion (request,response) {
	// 所有的url都是以 / 开头
	var url = request.url
	var filePath = ''
	if(url === '/'){
		// 根目录的话,显示首页
		filePath = '/index.html'
	}else {
		// 其他路径显示对应的文件
		filePath = url
	}
	// 读文件
	var fs = require('fs')
	var rootDir = '/Users/beyond/sg_node'
	NSLog('文件路径1: ' + filePath)
	filePath = rootDir + filePath
	NSLog('文件路径2: ' + filePath)
	// 读文件回调函数
	function readCompleteBlock (error,data) {
		// 失败
		if (error) {
			return response.end("404 Not Found")
		}
		// 后缀名判断,从而指定不同的响应头
		var path = require('path')
		var extname = path.extname(filePath)
		// 还是要处理一下头
		if (url === '/') {
			response.setHeader("Content-Type","text/html;charset=utf-8")
		} else if(extname === '.txt'  || extname === '.js'  || extname === '.css'){
			// 如果是txt文件
			response.setHeader("Content-Type","text/plain;charset=utf-8")
		} else if(extname === '.html'){
			// 如果是html文件
			response.setHeader("Content-Type","text/html;charset=utf-8")
		}
		// 输出到浏览器
		response.end(data)
	}
	// 读文件
	fs.readFile(filePath,readCompleteBlock)
}
// 注册事件
server.on("request",onReciveFuntion)
function onLaunchFinishFunction () {
	NSLog("服务启动成功",false)
}
// 监听端口,启动服务
// 访问地址:localhost:5267
server.listen(5267,onLaunchFinishFunction)

效果如下

fs.readdir(dirPath,callbackFunction)演示:

代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

// 读目录演示
var fs = require('fs')
// 要读取的目录
var dirPath = '/Users/beyond/sg_node'
// 开始读取目录
fs.readdir(dirPath,onCompleteFunction)
// 回调函数
function onCompleteFunction (error,fileArr) {
	if (error) {
		return NSLog('目录不存在')
	}
	// 去掉第1个的 .DS_Store
	fileArr.shift()
	NSLog(fileArr)
}

效果如下:

node_14.js实现一个功能

判断当前路径下的images目录中的png是一个file而非dir

代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

var fs = require('fs')
// 当前路径下的images目录下的png文件
// 注意,相对路径最前面不要有  ./
file = 'images/menma.png'
fs.stat(file,onFileStateFunction)
function onFileStateFunction (error,stats) {
	if (stats.isDirectory()) {
		NSLog(file + ' is 目录')
	}else{
		NSLog(file + ' is 文件')
	}
}

效果如下:

node_15.js实现的是通过读取模板.html文件后,

用replace(/placeHolderString/ig,newString)全局替换

因为 有可能 占位字符串会有多处

代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

var fs = require('fs')
// 读取模板
var templeFile = '/Users/beyond/sg_node/fileindex.html'
fs.readFile(templeFile,onReadCompleteFunction)
// 读取模板
function onReadCompleteFunction (error,data) {
	data = data.toString()
	// 注意: 必须使用全局替换/beyond_trListPlaceholder/ig
	// 因为 有可能 占位字符串会有多处
	data = data.replace(/beyond_trListPlaceholder/ig,"aaaaaaa")
	data = data.replace('beyond_fileFullPath',"bbbbbbbbb")
	NSLog(data)
}

node_13.js实现了一个类似于在线文件目录列表的功能

代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

// http请求演示
// 导入http模块
var http = require('http')
var server = http.createServer()
function onReciveFuntion (request,response) {
	// 显示文件列表模板
	// 读目录演示
	var fs = require('fs')
	// 要读取的目录
	var dirPath = ''
	var url = request.url
	// 如果是 / 则
	if (url === '/') {
		dirPath = '/Users/beyond/sg_node'
	} else{
		dirPath = '/Users/beyond/sg_node' + url
	}
	NSLog('dirPath: ' + dirPath)
	// 后缀名
	var path = require('path')
	var extName = path.extname(dirPath)
	if (extName.length > 0) {
		// 如果是文件,直接读写到浏览器
			return fs.readFile(dirPath,function(error,data) {

				if(extName === '.txt'  || extName === '.js'  || extName === '.css'){
					// 如果是txt文件
					response.setHeader("Content-Type","text/plain;charset=utf-8")
				} else if(extName === '.html'){
					// 如果是html文件
					response.setHeader("Content-Type","text/html;charset=utf-8")
				}



				// 直接写到浏览器
				return response.end(data)
			})
	}
	
	// 开始读取目录
	fs.readdir(dirPath,onCompleteFunction)
	// 回调函数
	function onCompleteFunction (error,fileArr) {
		if (error) {
			return response.end('www目录不存在')
		}
		// 去掉第1个的 .DS_Store
		// fileArr.shift()
		NSLog(fileArr)
		// 遍历,生成n个tr,并且,替换掉fileindex.html里的占位符号
		var trListContent = ''
		fileArr.forEach(function(file) {
			// 判断是不是目录
			var originFile = file
			
			if (url === '/') {

			} else{
				//   /7day_videos
				file = url.substring(1) + '/' + file
			}
			NSLog('file: ' + file)
			fs.stat(file,onFileStateFunction)
			function onFileStateFunction (error,stats) {
				if (stats.isDirectory()) {
					// 目录
					trListContent += `
					  <tr>
				        <td data-value="${originFile}/"><a class="icon dir" draggable="true" href="${originFile}/">${originFile}/</a></td>
				        <td class="detailsColumn" data-value="0"></td>
				        <td class="detailsColumn" data-value="${stats.mtimeMs}">${stats.mtime}</td>
				      </tr>
				      `
				} else{
					// 文件
					trListContent += `
					  <tr>
				        <td data-value="${originFile}"><a class="icon file" draggable="true" href="${originFile}">${originFile}</a></td>
				        <td class="detailsColumn" data-value="${stats.size}">${stats.size} B</td>
				        <td class="detailsColumn" data-value="${stats.mtimeMs}">${stats.mtime}</td>
				      </tr>
				      `
				}
			}


		})
		// 读取模板
		var templeFile = '/Users/beyond/sg_node/fileindex.html'
		fs.readFile(templeFile,onReadCompleteFunction)
		// 读取模板
		function onReadCompleteFunction (error,data) {
			data = data.toString()


			var fileFullPath = '/Users/beyond/sg_node/'
			if (url !== '/') {
				fileFullPath = fileFullPath + url.substring(1)
			}
			NSLog('fileFullPath: ' + fileFullPath);
			// 全局替换 必须用ig,不然多处占位字符串只能替换掉第一个
			data = data.replace(/beyond_fileFullPath2/ig,fileFullPath)
			data = data.replace('beyond_trListPlaceholder',trListContent)

			// 写到浏览器
			response.end(data)
		}
	}
}
// 注册事件
server.on("request",onReciveFuntion)
function onLaunchFinishFunction () {
	NSLog("服务启动成功",false)
}
// 监听端口,启动服务
// 访问地址:localhost:5267
server.listen(5267,onLaunchFinishFunction)

效果如下:

下面使用模板引擎[art-template](http://aui.github.io/art-template/zh-cn/docs/index.html)

先使用npm安装:

cd node_code所在目录,然后执行:

npm install art-template

会在当前路径生成一个6M大小的目录node_modules

如图所示:

在目录/Users/beyond/sg_node/node_modules/art-template/lib/下面

有一个template-web.js

我们先写一个node_16.html文件来演示一下web引擎的使用方法

第1步,

第2步,

第3步,

完整node_16.html代码如下:

<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY,XML,JSON,C,C++,C#,OC,PHP,JAVA,JSP,PYTHON,RUBY,PERL,LUA,SQL,LINUX,SHELL,汇编,日语,英语,泰语,韩语,俄语,粤语,阿语,魔方,乐理,动漫,PR,PS,AI,AE">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="beyondbasestylewhite5.css">
    <script type="text/javascript" src="nslog.js"></script>

    <!--[if lt IE 9]>
        <script src="//apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script>


        <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.js">
        </script>
    <![endif]-->

    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="beyondbuttongreen.css">

    <!-- 引入 jquery 2.1.4 -->
    <!--[if gte IE 9]><!--> 
    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js">
    </script>
    <!--<![endif]-->

</head>  
  
<body>  
        <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
            未闻花名
        </h1>
        <!-- 第1步,引用模板引擎 -->
        <script src="node_modules/art-template/lib/template-web.js"></script>
        <!-- 第2步,定义模板引擎 -->
        <!-- type只要 不是javascript即可,随便起,无意义 
             id 在第3步填充数据时用到
        -->
        <script type="text/beyondtemplate" id="art_template">
	        hello {{ author }},
            Here is {{ girlName }},She is {{ girlAge }}岁
        </script>
        <!-- 第3步,给模板引擎绑定数据 -->
        <script type="text/javascript">
            // 注意: 函数名,必须是template
            // 参数1: 模板的id
            // 参数2: 要填充的数据封装成的 对象
	        var resultHTML = template('art_template',{
	        	// body...
	        	girlName : 'mathilda',
                girlAge : 12,
                author : 'beyond'
	        })
	        $(document).ready(
	        	function () {
	        		// body...
	        		$('.class_btn_green').click(
	        			function () {
	        				// 打印替换后的内容
	        				NSLog('result: ' + resultHTML)
	        			}
        			)
	        	}
        	)
        </script>
        <button class="class_btn class_btn_green" type="button" style="display:block;margin:auto;margin-top:10px;">点我试试</button>
        
        <p class="sgcenter"><b>注意:</b>art-templateのtemplate-web.js演示</p>
        <footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
    
</body>  
</html>  

效果如下:

带遍历的模板,及数据

完整代码如下:

<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY,XML,JSON,C,C++,C#,OC,PHP,JAVA,JSP,PYTHON,RUBY,PERL,LUA,SQL,LINUX,SHELL,汇编,日语,英语,泰语,韩语,俄语,粤语,阿语,魔方,乐理,动漫,PR,PS,AI,AE">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="beyondbasestylewhite5.css">
    <script type="text/javascript" src="nslog.js"></script>

    <!--[if lt IE 9]>
        <script src="//apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script>


        <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.js">
        </script>
    <![endif]-->

    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="beyondbuttongreen.css">

    <!-- 引入 jquery 2.1.4 -->
    <!--[if gte IE 9]><!--> 
    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js">
    </script>
    <!--<![endif]-->

</head>  
  
<body>  
        <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
            未闻花名
        </h1>
        <!-- 第1步,引用模板引擎 -->
        <script src="node_modules/art-template/lib/template-web.js"></script>
        <!-- 第2步,定义模板引擎 -->
        <!-- type只要 不是javascript即可,随便起,无意义 
             id 在第3步填充数据时用到
        -->
        <script type="text/beyondtemplate" id="art_template">
	        hello {{ author }},
            Here is {{ girlName }},She is {{ girlAge }}岁
            She likes 
            {{ each loveArr }} 
    			 {{ $index }} : {{ $value }} 
   	    {{ /each }}
        </script>
        <!-- 第3步,给模板引擎绑定数据 -->
        <script type="text/javascript">
            // 注意: 函数名,必须是template
            // 参数1: 模板的id
            // 参数2: 要填充的数据封装成的 对象
	        var resultHTML = template('art_template',{
	        	girlName : 'mathilda',
                girlAge : 12,
                author : 'beyond',
                loveArr : ['leon','milk','imitation show']
	        })
	        $(document).ready(
	        	function () {
	        		// body...
	        		$('.class_btn_green').click(
	        			function () {
	        				// 打印替换后的内容
	        				NSLog('render result: \n' + resultHTML)
	        			}
        			)
	        	}
        	)
        </script>
        <button class="class_btn class_btn_green" type="button" style="display:block;margin:auto;margin-top:10px;">点我试试</button>
        
        <p class="sgcenter"><b>注意:</b>art-templateのtemplate-web.js演示</p>
        <footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
    
</body>  
</html>  

效果如下:

{{ }} 被戏称为 八字胡语法 mustache

甚至,模板内容  还可以是  完整的html页面

node_18.html完整代码如下:

<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY,XML,JSON,C,C++,C#,OC,PHP,JAVA,JSP,PYTHON,RUBY,PERL,LUA,SQL,LINUX,SHELL,汇编,日语,英语,泰语,韩语,俄语,粤语,阿语,魔方,乐理,动漫,PR,PS,AI,AE">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="beyondbasestylewhite5.css">
    <script type="text/javascript" src="nslog.js"></script>

    <!--[if lt IE 9]>
        <script src="//apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script>


        <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.js">
        </script>
    <![endif]-->

    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="beyondbuttongreen.css">

    <!-- 引入 jquery 2.1.4 -->
    <!--[if gte IE 9]><!--> 
    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js">
    </script>
    <!--<![endif]-->

</head>  
  
<body>  
        <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
            未闻花名
        </h1>
        <!-- 第1步,引用模板引擎 -->
        <script src="node_modules/art-template/lib/template-web.js"></script>




        <!-- 第2步,定义模板引擎 -->
        <!-- type只要 不是javascript即可,随便起,无意义 
             id 在第3步填充数据时用到
        -->
        <script type="text/beyondtemplate" id="art_template">
<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY,XML,JSON,C,C++,C#,OC,PHP,JAVA,JSP,PYTHON,RUBY,PERL,LUA,SQL,LINUX,SHELL,汇编,日语,英语,泰语,韩语,俄语,粤语,阿语,魔方,乐理,动漫,PR,PS,AI,AE">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="beyondbasestylewhite5.css">
    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="beyondbuttongreen.css">
</head>  
  
<body>  
        <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
            未闻花名
        </h1>       
	        hello {{ author }},
            Here is {{ girlName }},She is {{ girlAge }}岁
            She likes 
            {{ each loveArr }} 
    			 {{ $index }} : {{ $value }} 
   		    {{ /each }}
<footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
</body>  
</html>  
        </script>





        <!-- 第3步,给模板引擎绑定数据 -->
        <script type="text/javascript">
            // 注意: 函数名,必须是template
            // 参数1: 模板的id
            // 参数2: 要填充的数据封装成的 对象
	        var resultHTML = template('art_template',{
	        	girlName : 'mathilda',
                girlAge : 12,
                author : 'beyond',
                loveArr : ['leon','milk','imitation show']
	        })
	        $(document).ready(
	        	function () {
	        		// body...
	        		$('.class_btn_green').click(
	        			function () {
	        				// 打印替换后的内容
	        				NSLog('render result: \n' + resultHTML)
	        			}
        			)
	        	}
        	)
        </script>
        <button class="class_btn class_btn_green" type="button" style="display:block;margin:auto;margin-top:10px;">点我试试</button>
        
        <p class="sgcenter"><b>注意:</b>art-templateのtemplate-web.js演示</p>
        <footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
    
</body>  
</html>  

效果如下:

在node中使用art-template

步骤1: npm install art-template

步骤2:require(‘art-template’)

如图所示:

备注:

var template = require(‘art-template’)

template(templateFileFullPath,dataObject)

步骤3:使用核心方法(有三个)

node_19.js完整演示代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

// 模板引擎最早是用于服务端,后面才在前端使用
// 在node中 使用art-template步骤:
// 1.安装 npm install art-template 
// 2.var artTemplate = require('art-template')
// 3.使用构造方法artTemplate(templateFileFullPath,dataObject)
// 4.将渲染后的内容,写到浏览器


var artTemplate = require('art-template')
var templateFile = '/Users/beyond/sg_node/node_19_template.html'
// 填充的数据对象
var dataObject = {
		        	girlName : 'mathilda',
	                girlAge : 12,
	                author : 'beyond',
	                loveArr : ['leon','milk','imitation show']
		         }
// 使用构造方法artTemplate(templateFileFullPath,dataObject)		         
var resultHTML = artTemplate(templateFile,dataObject)
NSLog('resultHTML: ' + resultHTML)

模板node_19_template.html代码如下:

<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="beyondbasestylewhite5.css">
    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="beyondbuttongreen.css">
</head>  
  
<body>  
        <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
            未闻花名
        </h1>       
	        hello {{ author }},
            Here is {{ girlName }},She is {{ girlAge }}岁
            She likes 
            {{ each loveArr }} 
    			 {{ $index }} : {{ $value }} 
   		    {{ /each }}
<footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
</body>  
</html>  

运行效果如下:

下面结合http server,将渲染后的内容 通过response.end(resultHTML),写到浏览器

node_20.js完整代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

// 开启服务器
var http = require('http')
var server = http.createServer()
function onRequestFunction (request,response) {
	var url = request.url
	if (url === '/') {
		// 模板引擎最早是用于服务端,后面才在前端使用
		// 在node中 使用art-template步骤:
		// 1.安装 npm install art-template 
		// 2.var artTemplate = require('art-template')
		// 3.使用构造方法artTemplate(templateFileFullPath,dataObject)
		// 4.将渲染后的内容,写到浏览器
		var artTemplate = require('art-template')
		var templateFile = '/Users/beyond/sg_node/node_19_template.html'
		// 填充的数据对象
		var dataObject = {
				        	girlName : 'mathilda',
			                girlAge : 12,
			                author : 'beyond',
			                loveArr : ['leon','milk','imitation show']
				         }
		// 使用构造方法artTemplate(templateFileFullPath,dataObject)		         
		var resultHTML = artTemplate(templateFile,dataObject)
		// 将渲染后的内容回传给浏览器
		// 记得设置http头
		response.setHeader('Content-Type','text/html;charset=utf-8')
		response.end(resultHTML)
	} else{
		// 这儿还要对css, js ,png等进行响应
		var fs = require('fs')
		NSLog('url: ' + url)
		var filePath = url.substring(1)
		fs.readFile(filePath,function(error,data) {
			if (error) {
				return response.end('404 Not Found')
			}
			// 读到数据了,进行回写
			response.end(data)
		})
		
	}
}
// 注册事件
server.on('request',onRequestFunction)
// 监听端口,启动服务
// 访问地址:localhost:5267
server.listen(5267,function (error) {
	if (error) {
		return NSLog('启动失败: ' + error)
	}
	NSLog("服务启动成功",false)
})

效果如下:

推荐了电子书《编写可维护的JavaScript》

客户端渲染:
第1次请求:拿到html页面
第2次请求:在浏览器中使用ajax发送请求到服务器后,获取数据回来
第3步:在html页面中,使用模板引擎template-web.js进行渲染()
具体的客户端渲染方法请参见:node_17.html

服务端渲染:在服务端使用模板引擎(字符串replace)
具体就是:
第1步: 直接在html模板中使用 {{ placeHoler }}
第2步: 读取html后,使用模板引擎进行字符串的全局replace(/placeHolder/ig,dataString)
第3步: 把所有替换后的内容response.end(resultHTML)写给客户端

如果查看是服务端渲染还是客户端渲染,只要查看源代码就知道了
如果是客户端ajax请求回数据后用模板引擎渲染的,则没有源代码
如果是服务端渲染过后,一次性返回的html内容,则可看到源代码

像商品分页列表,一般是服务端渲染好,直接返回html内容
这儿之所以这样,主要是考虑爬虫SEO搜索引擎优化

像评论列表一般是ajax请求,客户端渲染
ajax请求,客户端渲染的内容  爬虫是爬不到滴
也就是说,客户端渲染ajax异步请求,不利于SEO搜索引擎优化

静态资源
如果html在解析过程中,遇到ajax、link(href)、script、img、video、audio、iframe等带有src属性的标签的时候,会自动发起新请求

html中,开头的/代表网站url的根路径
比如<img src=’/public/img/menma.png’ />
比如<link rel=’stylesheet’ href=’/public/css/main.css’ />

url模块中的parse(‘urlStr’,true)方法
可以返回一个object,其中键query的值 是一个对象,里面包含了查询的所有的键值对;

其中的键pathname的值 就是请求的路径如 /xxx
如下所示:
var urlObject = url.parse(‘http://baidu.com/s?wd=anohana’,true)
urlObject {
protocol: ‘http:’,
slashes: true,
auth: null,
host: ‘baidu.com’,
port: null,
hostname: ‘baidu.com’,
hash: null,
search: ‘?wd=anohana’,
query: { wd: ‘anohana’ },
pathname: ‘/s’,
path: ‘/s?wd=anohana’,
href: ‘http://baidu.com/s?wd=anohana’ }
>

浏览器插件: json view

服务器重定向
301 永久重定向
302 临时重定向(较多)

response.setStatusCode(302)
response.setHeader(‘Location’,’/’)
response.end

控制台里勾选preserve log复选框,就可以看到重定向的全过程了

下面是day02的最后一个demo,结合了art-template服务端模板引擎功能

node_21.js演示了一个无数据库的简易留言板示例

效果如下:

项目结构目录如下:

根目录下的文件只有node_21.js

根目录下的views目录中,存放着404页面,node_21_index.html页面,node_21_write.html页面

根目录下的public目录中,又分成了img,js,css,lib四个目录,代表所有的可公开访问的静态资源

本示例中,art-template安装在了根目录,其实应该安装在public/lib/下面最好

/根目录的node_21.js代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};};  

// 演示一下留言本
// 开启服务器
var http = require('http')
var server = http.createServer()
var url = require('url')
var fs = require('fs')
var artTemplate = require('art-template')
var dataObject = {
	recordArr:[
		{
			girlName: '面码',
			girlDescription: '未闻花名',
			pubTime: '2006-06-07'
		},
		{
			girlName: 'mathilda',
			girlDescription: '这个杀手不太冷',
			pubTime: '2006-06-07'
		}
	]
}
function onRequestFunction (request,response) {
	// 利用核心模块将url解析成对象
	var urlObject = url.parse(request.url,true)
	// 访问路径(不带参数)
	var pathname = urlObject.pathname
	if(pathname === '/'){
		// 根路径
		var templateFileFullPath = '/Users/beyond/sg_node/views/node_21_index.html'
		// 使用模板引擎 替换字符串
			// 使用构造方法artTemplate(templateFileFullPath,dataObject)		
		var resultHTML = artTemplate(templateFileFullPath,dataObject)
		// 将渲染后的内容回传给浏览器
		response.setHeader('Content-Type','text/html;charset=utf-8')
		response.end(resultHTML)
	}else if(pathname === '/write'){
		// 写评论
		fs.readFile('./views/node_21_write.html',function (error,data) {
			if (error) {
				return response.end('404 Not Found')
			}
			response.setHeader('Content-Type','text/html;charset=utf-8')
			response.end(data)
		})
	}else if(pathname === '/insert'){
		// 提交评论,理论上应该插入数据库,然后重新刷新
		var formObj = urlObject.query
		formObj.pubTime = '2018-05-20'
		// 这儿只是临时加到数组的最前面
		dataObject.recordArr.unshift(formObj)
		// 临时重定向,且必须手动end
		response.statusCode = 302
		response.setHeader('Location','/')
		response.end()
	}else if(pathname.indexOf('/public/') === 0){
		// 公共静态资源
		var filePath = '.' + pathname;
		fs.readFile(filePath,function (error,data) {
			if (error) {
				return response.end('404 Not Found')
			}
			// 将公共资源写入浏览器
			response.end(data)
		})
	}else{
		// 其他一律404伺候
		fs.readFile('./views/404.html',function (error,data) {
			if (error) {
				return response.end('404 Not Found')
			}
			response.end(data)
		})
	}

}
// 注册事件
server.on('request',onRequestFunction)
// 监听端口,启动服务
// 访问地址:localhost:5267
server.listen(5267,function (error) {
	if (error) {
		return NSLog('启动失败: ' + error)
	}
	NSLog("服务启动成功",false)
})

其中node_21_index.html是模板页面,代码如下:

<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="/public/img/beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="/public/css/beyondbasestylewhite5.css">
    <script type="text/javascript" src="/public/js/nslog.js"></script>

    <!--[if lt IE 9]>
        <script src="//apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script>


        <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.js">
        </script>
    <![endif]-->

    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("/public/img/sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="/public/css/beyondbuttongreen.css">

    <!-- 引入 jquery 2.1.4 -->
    <!--[if gte IE 9]><!--> 
    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js">
    </script>
    <!--<![endif]-->


    <link rel="stylesheet" type="text/css" href="/public/lib/bootstrap/bootstrap.css">
</head>  
  
<body>  
        
        
        
        <div class="header container">
            <div class="page-header">
                <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
                未闻花名
                </h1>
                <a href="/write" class="btn btn-success">
                    添加动漫
                </a>
            </div>
        </div>

        <div class="comments container">
            <ul class="list-group">
                {{ each recordArr }}
                <li class="list-group-item" style="background:transparent">
                    {{ $value.girlName }}の说说: {{ $value.girlDescription }} <span class="pull-right">{{ $value.pubTime }}</span>
                </li>
                {{ /each }}
            </ul>
        </div>
        
        <footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
    
</body>  
</html>  

node_21_write.html是填写内容页面,代码如下:

<!DOCTPYE html>  
<html lang="zh">  
<head>  
    <link rel="icon" href="/public/img/beyond2.jpg" type="image/x-icon"/>
    <meta charset="UTF-8">
    <meta name="author" content="beyond">
    <meta http-equiv="refresh" content="520">
    <meta name="description" content="未闻花名-免费零基础教程-beyond">
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
    <meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY">
    <title>beyond心中の动漫神作</title>
    <link rel="stylesheet" type="text/css" href="/public/css/beyondbasestylewhite5.css">
    <script type="text/javascript" src="/public/js/nslog.js"></script>

    <!--[if lt IE 9]>
        <script src="//apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script>


        <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.js">
        </script>
    <![endif]-->

    <style type="text/css">
        body{
            font-size: 100%; 
            /*声明margin和padding是个好习惯*/  
            margin: 0;  
            padding: 0; 
            background-image: url("/public/img/sakura4.png");  
            background-repeat: no-repeat;  
            background-position: center center;  
        }
    </style>
    <!-- 绿色按钮的css效果 -->
    <link rel="stylesheet" type="text/css" href="/public/img/beyondbuttongreen.css">

    <!-- 引入 jquery 2.1.4 -->
    <!--[if gte IE 9]><!--> 
    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js">
    </script>
    <!--<![endif]-->


    <link rel="stylesheet" type="text/css" href="/public/lib/bootstrap/bootstrap.css">
</head>  
  
<body>  
        <div class="header container">
            <div class="page-header">
                <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  
                    <a href="/" style="color:white">未闻花名</a><small style="color:white">添加新动漫</small>
                </h1>
            </div>
        </div>

        <div class="comments container">
            <form action="/insert" method="get">
                <div class="form-group">
                    <label for="id_input_name">
                        妳的名字:
                    </label>
                    <input id="id_input_name" type="text" class="form-control" required minlength='2' maxlength="10" name="girlName" placeHolder='请输入芳名' style="background:transparent" />
                </div>

                <div class="form-group">
                    <label for="id_textarea_description">
                        动漫推荐:
                    </label>
                    <textarea id="id_textarea_description" name="girlDescription" class="form-control" cols="5" rows="5" required minlength="3" maxlength="20" style="background:transparent"></textarea>
                </div>

                <button type="submit" class="btn btn-default">
                提交
                </button>
            </form>
        </div>
        
        <footer id="copyright">
            <p style="font-size:14px;text-align:center;font-style:italic;">  
            Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  
            </p>        
        </footer>
    
</body>  
</html>  

附录:

# Node.js 第2天课堂笔记

## 知识点

## 反馈
+ HTML 也是标记语言
+ markdown 标记语言
+ `#` 就是标题
+ `-`、`*` 就是列表
+ `**加粗内容**`
+ `GFM`

### 代码风格

“`javascript
var foo = ‘bar’
var foo =’bar’
var foo= ‘bar’
var foo = “bar”

if (true) {
console.log(‘hello’)
}

if (true) {
console.log(‘hello’)
}

if (true ){
console.log(‘hello’)
}
“`

为了约定大家的代码风格,所以在社区中诞生了一些比较规范的代码风格规范:

– [JavaScript Standard Style](https://standardjs.com/)
– Airbnb JavaScript Style  推荐!

## 复习

## 上午总结

– 代码风格
– 无分号
+ `(`
+ `[`
+ `
+ 最好前面补分号,避免一些问题
+ 《编写可维护的 JavaScript》
+ 不仅是功能,还要写的漂亮
– 服务端渲染
+ 说白了就是在服务端使用模板引擎
+ 模板引擎最早诞生于服务端,后来才发展到了前端

– 服务端渲染和客户端渲染的区别
+ 客户端渲染不利于 SEO 搜索引擎优化
+ 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的
+ 所以你会发现真正的网站既不是纯异步也不是纯服务端渲染出来的
+ 而是两者结合来做的
+ 例如京东的商品列表就采用的是服务端渲染,目的了为了 SEO 搜索引擎优化
+ 而它的商品评论列表为了用户体验,而且也不需要 SEO 优化,所以采用是客户端渲染

未完待续,下一章节,つづく