nodejs中没有DOM和BOM

console.log(document)
console.log(window)

代码运行报错如下:

C:\Users\Dell\Desktop\node\1.js:1
(function (exports, require, module, __filename, __dirname) { console.log(docume
nt)
                                                                          ^
ReferenceError: document is not defined
    at Object. (C:\Users\Dell\Desktop\node\1.js:1:75)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3

以读取文件为例,来看看异步回调函数中的参数
读取一个不存在的文件 error为一个对象,data为undefined

var fs=require('fs');
fs.readFile('./2.html',function(error,data){
	console.log(error);
	/*
	{ Error: ENOENT: no such file or directory, open 'C:\Users\Dell\Desktop\node\2.html'
	  errno: -4058,
	  code: 'ENOENT',
	  syscall: 'open',
	  path: 'C:\\Users\\Dell\\Desktop\\node\\2.html' }
	*/
	console.log(data);  //undefined
	if(error){
		console.log(error);
	}else{
		console.log(data);
	}
})

读取一个存在的文件

var fs=require('fs');
fs.readFile('./2.html',function(error,data){
	console.log(error);  //null
	console.log(data.toString());  //2.html中的内容
	if(error){
		console.log(error);
	}else{
		console.log(data);  // 十六进制内容
	}
})

请求成功时,回调函数中的参数

 data  数据
 error null

请求失败时,回调函数中的参数

 data undefined
 error 对象

综上,可以根据error来判断是否发生错误,操作是否成功

”.toString()结果为空,null.toString()会报错

http服务器

var http=require('http')
var server=http.createServer()
server.on('request',function(request,response){
	console.log(request.url+'已收到请求')
	//response.write可以使用多次,最后一定要用response.end来结束响应,否则客户端会一直等待
	response.write('hello')
	response.end('nodejs')
})
server.listen(3000,function(){
	console.log('服务器启动成功,可以通过http://127.0.0.1:3000来访问')
})

https://lvtao.net/content/book/node.js.htm

三种模块
具名的核心模块
用户自己编写的文件模块

require引入模块文件路径
同路径下,文件路径必须加./,直接require(‘文件名’)会报找不到文件,可以省略后缀名.js

在node中,没有全局作用于,只有模块作用域

import用法解释
import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js后缀可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。某些打包工具可以允许或要求使用扩展名。
默认导出,export 命名导出需要export 名字和import名字严格一致。而export default命令,为模块指定默认输出,在import 的时候可以随意命名名字。一个模块只能有一个默认输出,也就是说 export default 一个模块只能用一次。

node中exports的使用
模块文件
3.js

exports.ext='js';
exports.add=function(a,b){
	return a+b;
}

导入模块的文件
2.js

var obj=require('./3.js');
console.log(obj);  // { ext: 'js', add: [Function] }
console.log(obj.ext);   // js
var result=obj.add(100,200); 
console.log(result);  // 300

模块间的通信
exports默认是一个空对象,你可以在模块中自定义模块成员和属性.

node中module.exports的使用
通过module对象可以访问到当前模块的一些相关信息,但最多的用途是替换当前模块的导出对象。例如模块导出对象默认是一个普通对象,如果想改成一个函数的话,可以使用以下方式。
模块文件

module.exports=function add(a,b){
  return a*b;
}

导入模块的文件

var addFun=require('./4.js')
var result=addFun(100,250);
console.log(result);  // 25000

一个模块中的JS代码仅在模块第一次被使用时执行一次,并在执行过程中初始化模块的导出对象。之后,缓存起来的导出对象被重复利用。

ip地址用来定位计算机,端口号用来定位软件.所有需要联网的软件都需要一个端口号

获取发送请求的端口
request.socket.remotePort

var http=require('http')
var server=http.createServer()
server.on('request',function(request,response){
	console.log(request.socket.remotePort)  //获取用户访问端口
	response.end('nodejs')
})
server.listen(3000,function(){
	console.log('服务器启动成功,可以通过http://127.0.0.1:3000来访问')
})

响应中文乱码

var http=require('http');
var server=http.createServer();
server.on('request',function(request,response){
	response.write('服务器发送来的响应')
	response.end()
})
server.listen(5000,function(){
	console.log('http创建成功,可以通过访问127.0.0.1:3000访问')
})

默认响应以utf8编码方式返回给浏览器,但是浏览器无法识别这是utf8的内容,浏览器在不知道是什么编码的内容,会以当前操作系统的默认编码去解析内容,中文操作系统默认是gbk。
解决方法:

var http=require('http');
var server=http.createServer();
server.on('request',function(request,response){
	response.setHeader('Content-type','text/plain;charset=utf-8');  
	// text/plain当做普通文本解析,text/html当做html内容解析
	response.write('服务器发送来的响应')
	response.end()
})
server.listen(5000,function(){
	console.log('http创建成功,可以通过访问127.0.0.1:3000访问')
})

根据不同的响应内容,设置不同的content-type

var http=require('http');
var server=http.createServer();
var fs=require('fs')
server.on('request',function(request,response){
	if(request.url==='/index' || request.url==='/'){
		fs.readFile('./static/index.html',function(error,data){
			if(error){
				response.setHeader('content-type','text/plain;charset=utf-8');
				response.end('请求发生错误');
			}else{
				response.setHeader('content-type','text/html;charset=utf-8');
				response.end(data);
			}
		})
	}else if(request.url==='/zs'){
		fs.readFile('./static/zs.jpg',function(error,data){
			if(error){
				response.setHeader('content-type','text/plain;charset=utf-8');
				response.end('请求发生错误');
			}else{
				response.setHeader('content-type','image/jpeg');
				response.end(data);
			}
		})
	}
})
server.listen(5000,function(){
	console.log('http创建成功,可以通过访问127.0.0.1:3000访问')
})

注意:只有内容为字符文本内容数据时,才有必要设置编码,像图片之类的内容没有必要。
代码中是否用分号
当一行代码以 ( , [ , ` 开头的时候,则前面加上一个分号用以避免一些语法解析错误。

function say() {
    console.log('hello');
}
say()  //在这里加上分号可以解决报错问题
(function(){
	console.log('hello')
})()

报错:

hello
C:\Users\Dell\Desktop\node\1.js:5
(function(){
^

TypeError: say(...) is not a function
    at Object. (C:\Users\Dell\Desktop\node\1.js:5:1)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3

服务器端渲染
模板文件template.html

<tbody id="tbody">
{{each data}}
<tr><td data-value="1111"><a class="icon file" draggable="true" href="/E:/MUI%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B/MUI%E5%BE%AE%E4%BF%A1%E5%AE%9E%E6%88%98/01-HTML5%E6%B7%B7%E5%90%88%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E4%B8%8EMUI%E6%A1%86%E6%9E%B6.mp4"> {{$value}}</a></td><td class="detailsColumn" data-value="96543985">92.1 MB</td><td class="detailsColumn" data-value="1546563599">2019/1/4 上午8:59:59</td></tr>
{{/each}}
</tbody>

nodejs读取某个文件的目录数据,并渲染页面

var http=require('http')
var fs=require('fs')
var server=http.createServer()
var template=require('art-template')
server.on('request',function(request,response){
	//路径名称必须用正斜杠
	fs.readdir('../node',function(error,data){
		if(error){
			return console.log(error)
		}
		var files=''
		console.log(JSON.stringify(data))
        var html=template(__dirname + '/template.html',{data:data})
		response.end(html);
	})
})
 
server.listen(3000,function(){
	console.log('server is running');
})

静态资源
注意:在服务端中,文件中的路径就不要去写相对路径了。
因为这个时候所有的资源都是通过 url 标识来获取的
我的服务器开放了 /public/ 目录
所以这里的请求路径都写成:/public/xxx
/ 在这里就是 url 根路径的意思。
浏览器在真正发请求的时候会最终把 http://127.0.0.1:3000 拼上
不要再想文件路径了,把所有的路径都想象成 url 地址

执行

> url.parse('https://www.baidu.com/s?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d0002
21a5&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3
=6&rsv_sug1=6&rsv_sug7=101')
 
Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: null,
  search:
   '?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_idx
=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101',
  query:
   'wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_idx=
2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101',
  pathname: '/s',
  path:
   '/s?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_i
dx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101',
  href:
   'https://www.baidu.com/s?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp
=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_su
g1=6&rsv_sug7=101' }

执行

> url.parse('https://www.baidu.com/s?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101',true)
Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: null,
  search:
   '?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101',
  query:
   [Object: null prototype] {
     wd: 'melody',
     rsv_spt: '1',
     rsv_iqid: '0xec3cb13d000221a5',
     issp: '1',
     f: '8',
     rsv_bp: '0',
     rsv_idx: '2',
     ie: 'utf-8',
     tn: 'baiduhome_pg',
     rsv_enter: '1',
     rsv_sug3: '6',
     rsv_sug1: '6',
     rsv_sug7: '101' },
  pathname: '/s',
  path:
   '/s?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101',
  href:
   'https://www.baidu.com/s?wd=melody&rsv_spt=1&rsv_iqid=0xec3cb13d000221a5&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101' }

node.js实现简易留言板代码
post.html发表留言页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" href="/public/css/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 请求方法
            get
            post
     -->
    <form action="/postcomment" 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="content" 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>

留言展示页面 index.html

<!DOCTYPE html>
<!-- saved from url=(0027)http://192.168.150.76:3000/ -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>留言本</title>
  <!-- 
    浏览器收到 HTML 响应内容之后,就要开始从上到下依次解析,
    当在解析的过程中,如果发现:
      link
      script
      img
      iframe
      video
      audio
    等带有 src 或者 href(link) 属性标签(具有外链的资源)的时候,浏览器会自动对这些资源发起新的请求。
   -->
   <!-- 
      注意:在服务端中,文件中的路径就不要去写相对路径了。
      因为这个时候所有的资源都是通过 url 标识来获取的
      我的服务器开放了 /public/ 目录
      所以这里的请求路径都写成:/public/xxx
      / 在这里就是 url 根路径的意思。
      浏览器在真正发请求的时候会最终把 http://127.0.0.1:3000 拼上
 
      不要再想文件路径了,把所有的路径都想象成 url 地址
    -->
  <link rel="stylesheet" href="/public/css/bootstrap.css">
</head>
 
<body>
  <div class="header container">
    <div class="page-header">
      <h1>Example page header <small>Subtext for header</small></h1>
      <a class="btn btn-success" href="/post">发表留言</a>
    </div>
  </div>
  <div class="comments container">
    <ul class="list-group">
      {{each $data}}
      <li class="list-group-item">{{$value.name}} 说:{{$value.content}} <span class="pull-right">2017-11-2 17:11:22</span></li>
      {{/each}}
    </ul>
  </div>
</body>
</html>

main.js

var http = require('http')
var fs = require('fs')
var url = require('url')
var template = require('art-template')
 
var comments = [
    { name: 'xiaoming', content: '今年找到女友了没?' },
    { name: 'xiaogang', content: '前段时间找了个,但是人家要车要房!' },
    { name: 'xiaoming', content: '然后?' },
    { name: 'xiaogang', content: '然后就被甩了~' }
];
console.log(comments);
 
http
    .createServer(function (request, response) {
 
        var path = url.parse(request.url, true)  //获取一个url参数相关的对象
        var pathName = path.pathname  //获取url全路径,不包括问号以及问号之后的内容
 
 
        if (pathName === '/') {  //评论首页内容
            fs.readFile('./index.html', function (error, data) {
                if (error) {
                    return console.log('404 not found');
                }
                var html = template(__dirname+'/index.html', comments)
 
                response.end(html);
            })
        } else if (pathName === '/post') {  //评论页面
            fs.readFile('./post.html', function (error, data) {
                if (error) {
                    return console.log(error);
                }
                response.end(data);
            })
 
        } else if (pathName === '/postcomment') {  //用户发表评论内容
            var name = path.query.name
            var content = path.query.content
            comments.push({ name: name, content: content });
 
            console.log('push后的数据' + comments);
 
            response.statusCode = 302
            response.setHeader('location', '/')
            response.end()
 
        } else if (pathName.indexOf('/public/') === 0) {  //静态资源
            fs.readFile('./' + pathName, function (error, data) {
                if (error) {
                    return console.log('404 not found');
                }
                response.end(data);
 
            })
        } else {  //404处理
            response.end('404');
        }
    }).listen(3000)

如何通过服务器让客户端重定向?
1.状态码设置为302临时重定向
statusCode
2.在响应头中通过location告诉客户端往哪儿重定向
setHeader
如果客户端发现收到服务器的响应的状态码是302,就会自动去响应头去找location
最后就可以看到客户端跳转

require 加载规则
优先从缓存加载
不可能有任何一个第三方包和核心模块的名字是一样的

require(‘模块标识符’)
路径形式的模块
以’./’,’../’开头的相对路径
以’/’开头,在这里表示的是当前文件模块所属磁盘根路径,另外还有带盘符的路径,不推荐使用.

第三方模块加载(以art-template为例)
require(‘art-template’)
node_modules/art-template
node_modules/art-template/package.json
根据main属性中,记录了该模块的入口文件,如果package.json文件不存在或者main指定的入口模块也没有,则node会自动找该目录下的index.js
如果以上任何一个条件都不成立,则会从上一个目录的node_modules查找,上级目录也找不到,则会一直往上找,直到磁盘根目录的node_modules,如果找不到则报错
./是否可以省略
文件操作中的相对路径./可以省略,require(‘模块标识符’)中的模块标识符如果是以路径标识,相对路径./不能省略.
express框架
npm install express -S

const express = require('express')
const app = express()
 
app.get('/', function (request,response) {
    response.send('hello word')
})
 
app.get('/about', function (request,response) {
    response.send('about us')
})
 
app.get('/love', function (request,response) {
    response.send('love u')
})
 
//http://127.0.0.1:3000/static/zs.jpg  访问static目录下的zs.jpg文件 路径static下,url包含static
//app.use('/static', express.static('./static'))
 
//http://127.0.0.1:3000/zs.jpg  访问static目录下的zs.jpg文件  路径static下,url中不包含static
app.use(express.static('static'))
//http://127.0.0.1:3000/zs2.jpg  访问public目录下的zs2.jpg文件  路径public下,url不包含public
app.use(express.static('public'))
 
app.listen(3000, function () {
    console.log('服务器启动,可以通过127.0.0.1:3000访问')
})

使用express-art-template
express-art-template安装

npm install --save art-template
npm install --save express-art-template

在编写调试Node.js项目,修改代码后,需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon这个工具,它的作用是监听代码文件的变动,当代码改变之后,自动重启。

nodemon安装
npm install nodemon -g

nodemon使用
使用nodemon app.js执行node命令,以后此文件有修改则自动保存文件

express重写留言板

const express = require('express')
const app = express()
 
var comments = [
    { name: 'xiaoming', content: '今年找到女友了没?' },
    { name: 'xiaogang', content: '前段时间找了个,但是人家要车要房!' },
    { name: 'xiaoming', content: '然后?' },
    { name: 'xiaogang', content: '然后就被甩了~' }
];
 
//静态资源存放路径 url可以省略public
app.use(express.static('public'))
 
app.engine('html', require('express-art-template'))
 
app.get('/', function (req,res) {
    res.render('index.html', {comments})
})
 
app.get('/post-comment', function (req, res) { //提交评论数据
    comments.push({name:req.query.name, content:req.query.content})
    res.redirect('/');
})
 
app.get('/post', function (req, res) {
    res.render('post.html')
})
 
app.listen(3000, function () {
    console.log('服务器启动成功')
})

express利用body-parser解析表单post数据
安装
npm install body-parser -S

const express = require('express')
const app = express()
var bodyParser = require('body-parser');
 
 
var comments = [
    { name: 'xiaoming', content: '今年找到女友了没?' },
    { name: 'xiaogang', content: '前段时间找了个,但是人家要车要房!' },
    { name: 'xiaoming', content: '然后?' },
    { name: 'xiaogang', content: '然后就被甩了~' }
];
 
// 静态资源存放路径 url可以省略public
app.use(express.static('public'))
 
// 解析 application/json
app.use(bodyParser.json()); 
 
// 解析 application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true })); 
 
app.engine('html', require('express-art-template'))
 
app.get('/', function (req,res) {
    res.render('index.html', {comments})
})
 
app.post('/post', function (req, res) { //提交评论数据
    console.log(req.body)  //{ name: '3432423', content: '345345345345' }
    comments.push({name:req.body.name, content:req.body.content})
    res.redirect('/');
})
 
app.get('/post', function (req, res) {
    res.render('post.html')
})
 
app.listen(3000, function () {
    console.log('服务器启动成功')
})

建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题

npm install --registry=https://registry.npm.taobao.org

发表评论

邮箱地址不会被公开。 必填项已用*标注