node js 笔记

####https://github.com/nswbmw/N-blog/tree/master/book

####启动服务

  • mongod --config /usr/local/etc/mongod.conf

  • cd /usr/local/bin 终端进去
  • ./mongo 查看并且链接

####终止服务

  • pkill mongod

  • 引入:

    • import {firstName, lastName, year} from './profile';
  • 输出:

    • export {firstName, lastName, year};
  • 初始化:

    • npm init
  • 下载模块:

    • npm i express --save
var express = require('express');
var app = express();
app.use(express.bodyParser());//现实body
app.all('/', (req, res) => {
  res.send(req.body.title + req.body.text);
});

app.listen(3000);
复制代码
  • res.send('Hello World') 比 res.end('Hello World')

    • 省去诸如添加Content-Length之类的事情
  • 每次修改代码保存后,就自自动启动

    • npm WARN checkPermissions Missing write access(权限问题

    • sudo npm install -g supervisor

    • 运行 supervisor --harmony index 启动程序 cd进去

    • kill node 关闭

    • supervisor start app

    • 停止进程: control+c

//localhost:3000/users/nswbmw
const express = require('express')
const app = express()

app.get('/',(req,res) => {
   res.send('hello, express ')
 })

app.get('/users/:name',(req,res) => {
	res.send('hello' + req.params.name)
})

app.listen(3000)
复制代码
  • req.query: 解析后的 url 中的 querystring,如 ?name=haha,req.query 的值为 {name: 'haha'}
  • req.params: 解析 url 中的占位符,如 /:name,访问 /haha,req.params 的值为 {name: 'haha'}
  • req.body: 解析后请求体,需使用相关的模块,如 body-parser,请求体为 {"name": "haha"},则 req.body 为 {name: 'haha'}

###模块加载

exports.Hello = Hello 
var Hello = require('./hello').Hello 来获取
--
module.exports = Hello
var Hello = require('./hello')


复制代码

###路由 ######index.js

'use strict'

const express = require('express')
const app = express()

const indexRouter = require('./routes/index')
const userRouter = require('./routes/users')

app.use('/',indexRouter)
app.use('/users',userRouter)

app.listen(3000)
复制代码

######router index.js

'use strict'

const express = require('express')
const router = express.Router()

router.get('/', (req, res) => {
  res.send('hello, express')
})

module.exports = router
复制代码

######router users.js

'use strict'

const express = require('express')
const router = express.Router()

router.get('/users/:name',(req,res) => {
 res.send('hello, '+req.params.name)
})

module.exports = router
复制代码

  • npm i ejs --save

###模版 #####index.js

'use strict'

const path = require('path')
const express = require('express')
const app = express()

const indexRouter = require('./routes/index')
const userRouter = require('./routes/users')

app.set('views', path.join(__dirname, 'views'))// 设置存放模板文件的目录,查找模版路径
app.set('view engine', 'ejs')// 设置模板引擎为 ejs

app.use('/',indexRouter)
app.use('/users',userRouter)

app.listen(3000)

复制代码

#####routes/users.js

'use strict'

const express = require('express')
const router = express.Router()

router.get('/:name', (req, res) =>{
  res.render('users', {
    name: req.params.name
  })
})

module.exports = router

//通过调用 res.render 函数渲染 ejs 模板,res.render 第一个参数是模板的名字,这里是 users 则会匹配 views/users.ejs,第二个参数是传给模板的数据,这里传入 name,则在 ejs 模板中可使用 name。res.render 的作用就是将模板和数据结合生成 html,同时设置响应头中的 Content-Type: text/html,告诉浏览器我返回的是 html,不是纯文本,要按 html 展示。现在我们访问 localhost:3000/users/haha
复制代码

#####views/users.ejs

<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
    </style>
  </head>
  <body>
    <h1><%= name.toUpperCase() %></h1>
    <p>hello, <%= name %></p>
  </body>
</html>
复制代码

#####上面html name.toUpperCase()大写

<% code %>:运行 JavaScript 代码,不输出
<%= code %>:显示转义后的 HTML内容
<%- code %>:显示原始 HTML 内容
复制代码
        supplies: ['mop', 'broom', 'duster']
		//模版拼接
		<ul>
		<% for(var i=0; i<supplies.length; i++) {%>
		   <li><%= supplies[i] %></li>
		<% } %>
		</ul>
		//形成的样式
		<ul>
		  <li>mop</li>
		  <li>broom</li>
		  <li>duster</li>
		</ul>
复制代码

###模版引用

我们使用模板引擎通常不是一个页面对应一个模板,这样就失去了模板的优势,而是把模板拆成可复用的模板片段组合使用,如在 views 下新建 header.ejs 和 footer.ejs,并修改 users.ejs:

#####views/header.ejs

<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
    </style>
  </head>
<body>
复制代码

#####views/footer.ejs

</body>
</html>
views/users.ejs
复制代码

#####拼接成网页<%-include('文件名字')%>

<%- include('header') %>
  <h1><%= name.toUpperCase() %></h1>
  <p>hello, <%= name %></p>
<%- include('footer') %>
复制代码

###中间件 index.js

const express = require('express');
const app = express();

app.use(function(req, res, next) {
  console.log('1');
  next();
});

app.use(function(req, res, next) {
  console.log('2');
  res.status(200).end();
});

app.listen(3000);
复制代码

#####访问 localhost:3000,终端会输出:

1
2
复制代码

###错误处理

#####index.js

const express = require('express');
const app = express()

app.use(function(req, res, next) {
  console.log('1')
  next(new Error('haha'))
});

app.use(function(req, res, next) {
  console.log('2')
  res.status(200).end()
});

//错误处理
app.use(function(err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

app.listen(3000)
//此时访问 localhost:3000,命令行输出:1,浏览器会显示:Something broke!。
复制代码

###events 事件


var events = require('events');

var emitter = new events.EventEmitter()

emitter.on('someEvent', function(arg1, arg2) { 
   console.log('listener1', arg1, arg2)
})

emitter.on('someEvent', function(arg1, arg2) { 
   console.log('listener2', arg1, arg2)
})

emitter.emit('someEvent', 'byvoid', 1991)

//运行结果
//listener1 byvoid 1991
//listener2 byvoid 1991

以上例子中,emitter 为事件 someEvent 注册了两个事件监听器,然后发射了 someEvent 事件。运行结果中可以看到两个事件监听器回调函数被先后调用。这就是EventEmitter最简单的用法。接下来我们介绍一下EventEmitter常用的API。 
	EventEmitter.on(event, listener) 为指定事件注册一个监听器,接受一个字
符串event 和一个回调函数listener。
 	EventEmitter.emit(event, [arg1], [arg2], [...]) 发射 event 事件,传
递若干可选参数到事件监听器的参数表。
 	EventEmitter.once(event, listener) 为指定事件注册一个单次监听器,即
监听器最多只会触发一次,触发后立刻解除该监听器。
 	EventEmitter.removeListener(event, listener) 移除指定事件的某个监听
器,listener 必须是该事件已经注册过的监听器。
 	EventEmitter.removeAllListeners([event]) 移除所有事件的所有监听器, 如果指定 event,则移除指定事件的所有监听器。

复制代码

###fs.readfile

//异步的 fs.readFile()
//同步的 fs.readFileSync()

var fs = require('fs');
fs.readFile('content.txt', function(err, data) { 
	if (err) {
		console.error(err); 
	} else {
        console.log(data);
      }
});
//假设 content.txt 中的内容是 UTF-8 编码的 Text 文本文件示例,运行结果如下:
//<Buffer 54 65 78 74 20 e6 96 87 e6 9c ac e6 96 87 e4 bb b6 e7 a4 ba e4 be 8b>
复制代码
    var fs = require('fs');
    fs.readFile('content.txt', 'utf-8', function(err, data) {
      if (err) {
        console.error(err);
      } else {
        console.log(data);
      }
	});


//那么运行结果则是:
//Text 文本文件示例
复制代码

###npm 无参数的 npm install 的功能就是 检查当前目录下的 package.json,并自动安装所有指定的依赖。

###express 架构分离

  • 这是一个典型的 MVC 架构,浏览器发起请求,由路由控制器接受,根据不同的路径定 向到不同的控制器。控制器处理用户的具体请求,可能会访问数据库中的对象,即模型部分。控制器还要访问模板引擎,生成视图的 HTML,最后再由控制器返回给浏览器,完成一次请求。

###express 路径匹配 如我们想要展示一个用户的个人页面,路径为 /user/[username],可以用下面的方法定义路由规则:

app.get('/user/:username', function(req, res) { 
    res.send('user: ' + req.params.username);
});

复制代码

###REST风格

  • 请求方式 安全 幂等
  • GET 是 是
  • POST 否 否
  • PUT 否 是
  • DELETE 否 是
  • 所谓安全是指没有副作用,即请求不会对资源产生变动,连续访问多次所获得的结果不受访问者的影响。而幂等指的是重复请求多次与一次请求的效果是一样的,比如获取和更新操作是幂等的,这与新增不同。删除也是幂等的,即重复删除一个资源,和删除一次是 一样的。

###Express 对每种 HTTP 请求方法绑定:

  • GET
    app.get(path, callback)

  • POST
    app.post(path, callback)

  • PUT
    app.put(path, callback)

  • DELETE
    app.delete(path, callback)

  • PATCH
    app.patch(path, callback)

  • TRACE
    app.trace(path, callback)

  • CONNECT
    app.connect(path, callback)

  • OPTIONS
    app.options(path, callback)

  • 所有方法
    app.all(path, callback)

Express 路由控制权转移

Express 提供了路由控制权转移的方法,即回调函数的第三个参数next,通过调用 next(),会将路由控制权转移给后面的规则,例如:

app.all('/user/:username', function(req, res, next) { 
	console.log('all methods captured');
    next();
});

app.get('/user/:username', function(req, res) {
    res.send('user: ' + req.params.username);
});   

//如果调用next(“route”),则会跳过当前路由的其它中间件,直接将控制权交给下一个路由。

复制代码

###使用模版引擎

我们在 app.js 中通过以下两个语句设置了模板引擎和页面模板的位置:

 app.set('views', __dirname + '/views');
 app.set('view engine', 'ejs');

复制代码

表明要使用的模板引擎是 ejs,页面模板在 views 子目录下。在 routes/index.js 的 exports.index 函数中通过如下语句调用模板引擎:

res.render('index', { title: 'Express' });

复制代码

res.render 的功能是调用模板引擎,并将其产生的页面直接返回给客户端。它接受 两个参数,第一个是模板的名称,即 views 目录下的模板文件名,不包含文件的扩展名;第 二个参数是传递给模板的数据,用于模板翻译。index.ejs 内容如下:

   <h1><%= title %></h1>
   <p>Welcome to <%= title %></p>

复制代码

上面代码其中有两处 <%= title %>,用于模板变量显示,它们在模板翻译时会被替换 成 Express,因为 res.render 传递了 { title: 'Express' }。

    ejs 的标签系统非常简单,它只有以下3种标签。
   <% code %>:JavaScript 代码。
   <%= code %>:显示替换过 HTML 特殊字符的内容。 
   <%- code %>:显示原始 HTML 内容。 我们可以用它们实现页面模板系统能实现的任何内容。

复制代码

会话支持Cookie

  为了在无状态的 HTTP 协议之上实现会话,Cookie 诞生了。Cookie 是一些存储在客户 端的信息,每次连接的时候由浏览器向服务器递交,服务器也向浏览器发起存储 Cookie 的 请求,依靠这样的手段服务器可以识别客户端。我们通常意义上的 HTTP 会话功能就是这样 实现的。具体来说,浏览器首次向服务器发起请求时,服务器生成一个唯一标识符并发送给 客户端浏览器,浏览器将这个唯一标识符存储在 Cookie 中,以后每次再发起请求,客户端 浏览器都会向服务器传送这个唯一标识符,服务器通过这个唯一标识符来识别用户。

              
复制代码

###methodOverride

因为我们单击出发的是post,而服务器上是put事件.
现在想让服务器端依然是put接受,html上依然是post请求. 加app.use(express.methodOverride());  
http://www.bubuko.com/infodetail-503315.html

复制代码

###重定位

'use strict'

const express = require('express')
const app = express()

app.get('/', function (req, res) {
  
    console.log('1')

});

app.get('/one', function(req, res) {
    
    console.log('2')

    return res.redirect('/');//是重定向功能,

})
//访问http://localhost:3000/one 会输出:2,1

复制代码

###connect-flash


const express = require('express')
const session = require('express-session')
const flash = require('connect-flash');

const app = express()


app.use(session({
  secret: 'one',  //通过设置 secret 来计算 hash 值并放在 cookie 中,使产生的 signedCookie 防篡改
  cookie: {maxAge: 60000}, // 过期时间,过期后 cookie 中的 session id 自动删除

}))

app.use(flash());//中间件

app.get('/', function (req, res) {
  //取出来,然后就消失了
  	console.log(req.flash('one'))
  	res.send('success')

})

app.get('/one', function(req, res) {
    
	req.flash('one','1')//存 key value值
    return res.redirect('/')//是重定向功能,

})
复制代码

//这是session 设置详情

'use strict'

const express = require('express')
const session = require('express-session')
const flash = require('connect-flash')
const MongoStore = require('connect-mongo')(session);

const app = express()

app.use(session({ 
	name: 'app'
  	secret: 'one',  //通过设置 secret 来计算 hash 值并放在 cookie 中,使产生的 signedCookie 防篡改
  	cookie: {maxAge: 60000}, // 即60000后session和相应的cookie失效过期除
  	resave: false,//是指每次请求都重新设置session cookie,假设你的cookie是10分钟过期,每次请求都会再设置10分钟
    saveUninitialized: true//是指无论有没有session cookie,每次请求都设置个session cookie ,默认给个标示为 connect.sid

  //数据库储存
   store: new MongoStore({   //创建新的mongodb数据库
         host: 'localhost',    //数据库的地址,本机的话就是127.0.0.1,也可以是网络主机
         port: 27017,          //数据库的端口号
         db: 'test-app'        //数据库的名称。
     })

}))

app.use(flash());//中间件

app.get('/', function (req, res) {
  //取出来,然后就消失了
  	console.log(req.flash('one'))
  	res.send('success')

});

app.get('/one', function(req, res) {
    
	req.flash('one','1')//存 key value值
    return res.redirect('/')//是重定向功能,

})


// 监听端口,启动程序
app.listen(3000, function () {
  console.log(`success`)
})

复制代码

###require


我们要在 /home/byvoid/develop/foo.js 中使用 require('bar.js') 命令,Node.js会依次查找:
 /home/byvoid/develop/node_modules/bar.js
 /home/byvoid/node_modules/bar.js
 /home/node_modules/bar.js
 /node_modules/bar.js
复制代码

###循环便利,里面异步回调-有坑

var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (var i = 0; i < files.length; i++) { 
    fs.readFile(files[i], 'utf-8', function(err, contents) {
        console.log(files);
        console.log(i);
        console.log(files[i]);
    }); 

}
运行结果如下:
    [ 'a.txt', 'b.txt', 'c.txt' ]
    3
    undefined
    [ 'a.txt', 'b.txt', 'c.txt' ]
    3
    undefined
    [ 'a.txt', 'b.txt', 'c.txt' ]
    3
    undefined
//三次输出的 i 的值都是 3,超出了 files 数组的下标 范围,因此 files[i] 的值就是 undefined 了。
//现在问题就明朗了:原因是3次读取文件的回调函数事实上是同一个实例,退出循环时 i 的值就是 files.length 的值。既然 i 的值是 3,引用到的 i 值是上面循环执行结束后的值,因此不能分辨。

//解决方案

var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
files.forEach(function(filename) {
   fs.readFile(filename, 'utf-8', function(err, contents) {
   console.log(filename + ': ' + contents); 
   });
});
    
复制代码

###构造函数

//创建复杂的对象。
function User(name, uri) { 
   this.name = name;
   this.uri = uri; 
   this.display = function() {
	   console.log(this.name); 
   }
}
//以上是一个简单的构造函数,接下来用new 语句来创建对象: 
 var someuser = new User('byvoid', 'http://www.byvoid.com');
//然后就可以通过someuser 来访问这个对象的属性和方法了。

复制代码

###this指针

//this 指针不属于某个函数,而是函数调用时所属的对象。
var someuser = { 
	name: 'byvoid', 
	func: function() {
		console.log(this.name); 
	}
 }; 
var foo = { 
	name: 'foobar'
};
someuser.func(); // 输出 byvoid
foo.func = someuser.func; 

foo.func(); // 输出 foobar
name = 'global';
func = someuser.func; func(); // 输出 global

复制代码

call 和 apply

//call 和 apply 的功能是一致的,两者细微的差别在于 call 以参数表来接受被调用函 数的参数,而 apply 以数组来接受被调用函数的参数。
var someuser = {
    name: 'byvoid',
    display: function(words) {
    console.log(this.name + ' says ' + words); 
    }
};
var foo = { 
    name: 'foobar'
};
someuser.display.call(foo, 'hello'); // 输出 foobar says hello

输出了 foobar.someuser.display 是 被调用的函数,它通过 call 将上下文改变为 foo 对象,因此在函数体内访问 this.name 时,实际上访问的是 foo.name,因而输出了foobar。

复制代码

bind绑定

bind 方法来永久地绑定函数的上下文,使其无论被谁调用,上 下文都是固定的
var someuser = { 
	name: 'byvoid', 
	func: function() {
	console.log(this.name);
	} 
};

var foo = { 
	name: 'foobar'
};
foo.func = someuser.func;
foo.func(); // 输出 foobar
foo.func1 = someuser.func.bind(someuser);
foo.func1(); // 输出 byvoid func = someuser.func.bind(foo);
func(); // 输出 foobar func2 = func;
func2(); // 输出 foobar


使用 bind 绑定参数表
bind 方法还有一个重要的功能:绑定参数表
var person = {
	name: 'byvoid', 7 says: function(act, obj) {
	console.log(this.name + ' ' + act + ' ' + obj); }
};
	person.says('loves', 'diovyb'); // 输出 byvoid loves diovyb
	byvoidLoves = person.says.bind(person, 'loves'); 
	byvoidLoves('you'); // 输出 byvoid loves you

可以看到,byvoidLoves 将 this 指针绑定到了 person,并将第一个参数绑定到 loves,之后在调用 byvoidLoves 的时候,只需传入第三个参数。这个特性可以用于创建 一个函数的“捷径”.
复制代码

###原型链

两个特殊的对象: Object 与 Function,它们都是构造函数,用于生成对象。Object.prototype 是所有对象的祖先,Function.prototype 是所有函数的原型,包括构造函数。
我把 JavaScript 中的对象分为三类:
一类是用户创建的对象,用户创建的对象,即一般意义上用 new 语句显式构造的对象。
一类是构造函数对象,构造函数对象指的是普通的构造函数,即通过 new 调用生成普通对象的 函数。
一类是原型对象,原型对象特指构造函数 prototype 属性指向的 对象。
这三类对象中每一类都有一个 __proto__ 属 性,它指向该对象的原型,从任何对象沿着它开始遍历都可以追溯到 Object.prototype。
构造函数对象有 prototype 属性,指向一个原型对象,通过该构造函数创建对象时,被创 建对象的 __proto__ 属性将会指向构造函数的 prototype 属性。原型对象有 constructor 属性,指向它对应的构造函数。
function Foo() {
}
Object.prototype.name = 'My Object'; 
Foo.prototype.name = 'Bar';
var obj = new Object();
var foo = new Foo();
console.log(obj.name); // 输出 My Object
console.log(foo.name); // 输出 Bar
console.log(foo.__proto__.name); // 输出 Bar 
console.log(foo.__proto__.__proto__.name); // 输出 My Object 
console.log(foo.__proto__.constructor.prototype.name); // 输出 Bar

复制代码

[图片上传失败...(image-b add9-1512039587570)]

###对象定义

尽量将所有的成员函数通过原型定义,将属性在构造函数内定义,然后对构造函数使用 new 关键字创建对象。绝对不要把属性作为原型定义,因为当要定义的属性是一个对象的 时候,不同实例中的属性会指向同一地址。
正确:
function FooObj(bar) { 
	//在构造函数中初始化属性 
	this.bar = bar; 
	this.arr = [1, 2, 3];
}
//使用原型定义成员函数 
FooObj.prototype.func = function() {
	console.log(this.arr); 
};
var obj1 = new FooObj('obj1'); 
var obj2 = new FooObj('obj2');
obj1.arr.push(4);
obj1.func(); // [1, 2, 3, 4]
obj2.func(); // [1, 2, 3]

复制代码

转载于:https://juejin.im/post/5a31f14f6fb9a045170536bd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值