一:什么是nodejs?(node可以作为一个服务器)

   官网:https://nodejs.org/en/

   nodejs是一个基于chrome V8引擎的javascript运行时(可以解析和javascript语言,没有DOM和BOM

       *:nodejs不是一门语言,类似于浏览器,但是没有图形界面

   nodejs使用高效、轻量级的事件驱动、非阻塞(异步的)的I/O模型

       *:事件驱动

       *:IO:输入与输出(异步)

   nodejs的生态系统npm是目前最大的开源包管理系统

  使用nodejs可以做什么?

   网站开发、命令行应用程序

  MEAN (mongodb express angularjs nginx(类似于apache的服务器))

  LAMP(linux apache  mysql  php )

  WAMP(windows apache mysql php)

传统的web交互模型:

二:快速上手

1.环境安装:

       (.msi格式的直接点击下一步安装)

          https://nodejs.org/en/download/

      打开cmd,输入 node -v 检查是否有node环境

2.cmd中输入node 进入node环境

  cd:切换目录

 node + 文件名:使用nodejs执行该文件

  (实际是node.exe可执行程序读取了该文件,然后解析执行文件中的代码)

3.文件操作

//导入fs模块
var fs=require('fs');
//文件的写入
//第一个参数:写入文件的路径(如果文件已经存在直接覆盖,如果不存在直接创建)
//第二个参数:指定要写入文件的数据
//注意:操作文件路径一定是相对路径或者绝对路径
//        如果是相对路径,最好加上./
//第三个参数:回调函数
//回调函数需要接受一个参数:err
//如果写入文件操作成功了,则err就是一个null
//如果写入文件操作失败了,则err就是一个异常对象
fs.writeFile('./data.txt','hello world ',function(err){
	if(err){
		throw err;
	}
	console.log('写入文件成功了');
});

 注意:

         写文件时目录名最好不要出现中文、不要出现空格、文件名也不要写中文

//导入文件模块
var fs=require('fs');
//第一个参数:尧都区的文件名
//第二个参数:可选的,用来指定读取文件的编码格式(如:utf8),此处设置了编码,下面的data就不需要toString()
//第三个参数:回调函数
//    err:
//        如果读取成功err就是null
//        如果读取失败,err就是异常对象
//    data:读取到的文件数据
fs.readFile('./data.json','utf8',function(err,data){//记得写编码格式
   if(err){
        throw err;
   }
   //注意:此处获取的文件数据默认是二进制,要想获取要原始数据,需要将data.toString()
   console.log(data); 
})

4.服务器

//导入服务器模块
var http=require('http')
//1.创建服务器
var server=http.createServer()
//2.给服务器实例对象server设置request请求事件处理函数
//request事件处理函数需要接受两个参数:
//Reques请求对象t:可以获取到客户端请求的一些数据,例如:url、请求方法
//Response响应对象:可以用来给客户端发送响应数据 server.on('request',function(req,res){
console.log(req.url) console.log(
'有客户端请求进来了。。。。。')
res.writeHead(200,{
'Content-Type':'text/html;charset=utf8'
})
//使用res响应对象的write方法向本次请求发送响应数据
//注意:可以多次使用write方法想客户端发送数据
//建议给客户端发送数据的时候,告诉客户端你发的数据是什么类型
res.write('hello')
//发送完数据后要记得通知服务器响应完毕,即使只发送一个响应头也要记得end
res.end()
************************************************************
*//也可以直接把你要返回的数据写在end()里面,就可以不用写write()*
* res.end('<h1>hello</h1>') *
************************************************************
===========================================================================
=//实现重定向
=//302状态码就表示重定向,浏览器看到302状态码后,会自动去响应报文头中找 Location属性=
=res.writeHead(302,{
= 'Location':'/' //重新跳转到首页 =
=})
=========================================================================== })
//3.启动服务器,设置绑定一个端口号 //第一个参数:用来指定绑定的端口号。。。。 //第二个参数:可选的,指定绑定的ip地址, //第三个参数:回调函数 server.listen('3000',function(){ console.log('server is running at port 3000') console.log('please visit http://127.0.0.1:3000') })

 5.art-Template模板引擎

哪个项目中要使用该模板就进入根路径,执行npm install art-Template,npm会在当前目录下找node_modules目录,如果没有,直接创建,并将要下载的问价添加到该文件夹,如果有,直接下载到该文件夹。

//加载第三方包,不需要指定路径
var template=require('art-Template')
//1.调用template.compile函数,传入模板字符串
//调用该函数之后会得到一个render渲染函数
var render=template.compile('<h1>{{title}}</h1>')
//2.调用render渲染函数,传入一个数据对象
//返回解析替换后的字符串
render({
    title:'hello world'
})
//条件表达式
{{if admin}}
    <p>admin</p>
{{else if code > 0}}
    <p>master</p>
{{else}}
    <p>error!</p>
{{/if}}
//数组和对象的遍历
{{each list as value index}}
    <li>{{index}} - {{value.user}}</li>
{{/each}}
亦可以被简写:
{{each list}}
    <li>{{$index}} - {{$value.user}}</li>
{{/each}}

6.路径模块

var url=require('url')
//导入服务器模块
var http=require('http')
//导入处理post请求体的模块
var querystring=require('querystring')
//1.创建服务器
var server=http.createServer()
//2.给服务器实例对象server设置request请求事件处理函数
server.on('request',function(req,res){
//url模块中的parse方法可以将一个路径解析为一个对象
// 可以得到一个路径中的 请求路径部分、查询字符串部分、端口号 等信息
// 可以通过指定第二个参数为 true,自动将解析到的查询字符串解析为一个对象
var urlObj=url.parse(req.url,true)
// 拿到请求路径中的查询字符串对象(get请求的获取方式)
var queryObj = urlObj.query
//获取post请求中的请求体
//表单post提交数据可能是很大的,所以post会把提交的数据进行分块传输
//在服务端也需要一块一块的接收
//通过监听req请求对象的data事件和end事件就可以接收
var data=''
req.on('data',function(chunk){
//chunk接收到是二进制数据,和字符串拼接会自动调用toString()方法
//二进制数据有一个length属性,获取到的就是二进制数据的字节
  data+=chunk
})
req.on('end',function(){
   //通过使用内置模块去二院string的parse将一个查询字符串转换为一个对象
  var body=querystring.parse(data)
})
//
// 只拿到请求路径中的路径部分(不包含查询字符串)
var pathname = urlObj.pathname
       console.log('有客户端请求进来了。。。。。')
})
//3.启动服务器,设置绑定一个端口号
server.listen('3000',function(){
    console.log('server is running at port 3000')
    console.log('please visit http://127.0.0.1:3000')
})

三:nodejs中的模块化

//一个文件就是一个模块
//每个模块就是一个私有的作用域
//默认模块内部定义的所有成员都只能在模块内部使用
//require函数用来加载一个模块
//    1.从头到尾执行模块中的代码
//    2.可以得到模块内部的通信接口对象:module.exports
var add=require('./add')
//node中完全就是模块化的编程方式
//每个js文件就是一个模块
//每个模块就是一个私有作用域
//在每个模块内部还提供了一个通信接口对象:module.eports接口对象
//模块与模块之间可以通过require函数进行加载执行,并得到被加载模块内部的接口对象
//模块与模块之间还可以互相依赖
//module.exports用来向外暴露该模块内部的数据
//在每个模块内部还提供了一个成员:eports接口对象
//exports就是module.exports接口对象的一个引用
//exports===module.exports
//使用require注意事项:
//   1.加载相对路径文件模块一定要以./或者../开头
//   2.加载模块文件时后缀名可以省略,node中推荐省略后缀名
//如果一个模块想要向外暴露一个单独的接口成员
//例如:只暴露一个函数、字符串、数字、数组等成员
//就需要通过module.exports接口对象赋值即可
module.exports=function(){
    return x+y;
}
//注意:每个模块内部最终向外暴露的是module.exports
//exports只是module.exports接口对象的一个引用
//所以一旦给exports接口对象赋值,exports和 module.exports就失去引用关系

核心模块(node内置)

1.核心模块就是node内置的模块,需要通过唯一的标识名来进行获取。

2.每一个核心模块基本上都只是暴露了一个对象,里面包含了一些方法供我们使用

3.一般在加载核心模块的时候,变量的起名最好就和核心模块的标识名同名即可

    eg:`var fs=require('fs')`

4.核心模块本质上也是文件模块

   核心模块已经被编译到了node的可执行程序,一般看不到

   可以通过查看node的源代码看到核心模块文件

   核心模块也是基于commonjs模块规范

  --------------------------------------------------------------------------------------------------------------------------------------

  -----------CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。---------------------------------

  -----------AMD规范则是非同步加载模块,允许指定回调函数。

  -----------由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,-----------------------

  -----------不用考虑非同步加载的方式,所以CommonJS规范比较适用。----------------------------------------------------------

  -----------但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。---

  --------------------------------------------------------------------------------------------------------------------------------------

每个模块都提供了单一的功能,以下是常用的核心模块
|     模块名称    |    模块作用       |
| ---------------|----------------- |     
|     fs         |   文件操作        |
|     http       |   http服务       |
|     path       |   路径处理        |
|     url        |   处理url路径     |
|   querystring  |   处理查询字符串   |
|     os         |   操作系统相关     |
|     net        |   socket网络编程  |
|     util       |   工具函数        |
|                |                  |

模块的加载流程:

     *:优先从缓存加载

     *:在一个模块系统中,模块第一次被加载的时候会执行模块中的代码,通过把该模块的接口对象缓存起来。

     *:如果多次加载该模块,不会执行该模块中的代码了,直接从缓存中将该模块的接口对象取出来。

     *:加载模块得到的是内部接口对象的复制

     *:一旦第一次加载过后,拿到的是接口数据的备份,如果模块内部的成员被修改了,是不会影响到外部的使用。

5.

//读取文件的时候
//如果文件是以/ 开头的,则直接去当前文件所属盘符根目录去找
//读取文件的时候相对路径是以相对于执行node命令的时候所处的目录的
var path=require('path')
//拼接路径
//join方法支持拼接多个路径,也支持拼接上一级路径
//path.join('/a/b/c','./d','../e')
path.join('__dirname','index.js')

6.momentjs插件

//转换中文格式
moment.local('zh-cn')
moment('20120311','YYYYMMDD').fromNow();//5 years age
var time=new Date().getTime();//获取当前时间
moment(time).startOf('second').fromNew();//x minutes age
//获取当前时间并且格式化
moment().format('YYYY-MM-DD hh-mm-ss')//2017-03-11 10:21:16

四:node中的javascript

ECMAScript
console
setInterval()
setTimeout()
clearInterval(id)
clearTimeout(id)
clearImmediate()
setImmediate()
__dirname
__filename
global
process
require()
exports
module

五:MongoDB数据库

- 官网:https://www.mongodb.com/
- 菜鸟教程:http://www.runoob.com/mongodb/mongodb-tutorial.html
- MongoDB 是一个面向文档存储(JSON)的 **非关系型** 数据库,可以用来存储网站应用程序的数据
  + MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成
  + MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组
  + **非关系型** 后面给大家介绍 MySQL 数据库就会了解各大数据库的区别了
- MongoDB 数据库是跨平台的,可以在 Linux、Mac OSX、Windows 等平台使用
- MongoDB 诞生于 2009 年,由 10gen 团队创建

安装MongoDB

 下载地址:https://www.mongodb.com/download-center
  + 根据自己的操作系统下载对应的数据库版本
- 在 Windows 平台安装 MongoDB 数据库环境
  + 教程:http://www.runoob.com/mongodb/mongodb-window-install.html
  + 注意:所谓的 MongoDB 数据库环境其实是个服务,没有图形界面
- 验证是否安装成功
  + 在终端中输入 `mongod --version` 命令进行查看
  + 如果能看到安装好的 MongoDB 数据库版本号,说明安装成功

**注意:** 如果安装成功,但是执行 `mongod --version` 命令提示不是内部命令的错误,
这个时候将 MongoDB 的安装目录中的 bin 目录配置到环境变量,然后再次尝试。

启动和关闭 MongoDB 数据库服务程序
> Tips:以下操作请确保你执行 `mongod --version` 能看到安装的服务版本号 `mongod` 命令用来启动 MongoDB 数据库,但是如果你第一次执行该命令,你会发现报错了。 这是因为 MongoDB 服务默认使用 `C:/data/db` 目录作为自己的数据存储目录, 这个时候如果没有该目录,则自己手动创建 `C:/data/db` 该目录,然后再次使用 `mongod` 启动数据库服务。 如果你想要使用别的数据存储目录,则可以通过 `mongod --dbpath=数据存储路径` 的形式启动 MongoDB 服务。 启动成功之后,你会发现控制台输出一大堆字符,并且没有退出,那这个时候表示 MongoDB 服务启动成功, 然后就可以把这个控制台最小化了,只要不关闭该窗口,MongoDB 服务实例就会一直运行。 如果想要关闭 MongoDB 服务,则可以在运行 MongoDB 服务的控制台中通过 `Ctrl + C` 关闭服务。 上述都是针对 64 位操作系统的操作步骤,如果是 32 位操作系统,则可以使用下面的方式启动 MongoDB 数据服务: ```bash $ mongod --dbpath 数据存储路径 --journal --storageEngine=mmapv1 ```
//打开终端,输入'mongod'回车
//'mongod'命令用来启动MongoDB数据服务
//MongoDB服务默认将C:/data/db目录作为数据目录
//所以需要先在C盘根目录下新建一个目录:C:/data/db
//当执行mongod命令的时候,就会默认使用C:/data/db作为目录存储数据
//如果你不想使用C:/data/db
//mongod --dbpath=路径 --journal --storageEngine=mmapv1
//一个计算机上只能安装一个mongodb应用服务实例
//一个mongodb服务实力上可以创建多个数据库
//一个数据库中可以有多个集合,一个集合中存储的就是文档(其实就是json对象)

mongodb启动

//打开终端输入mongod
//再打开一个终端输入mongo
//注意:是两个终端,不可以关闭其中任意一个
//mongodb默认连接到127.0.0.1:27017

 操作数据库

show dbs //查看mongodb服务中有哪些数据库
use + '数据库名字'//切换数据库
    //如果该数据库不存在,会先进入该数据库
    //只有当你真正在该数据库中存储了一个集合之后,才会真正的创建数据库
db //查看当前所属的数据库
db.dropDatabase()//删除数据库(要先进入该数据库)
db.collection.drop()//删除集合
show collection//进入数据库查看所有的集合
//增加数据 db.集合名.insert({name:jack,age:10})//插入数据
//查询数据 db.集合名.find()//查询指定集合的所有数据 db.集合名.find().pretty()//格式化的形式读取集合数据
//更新数据 db.集合名.update({更新条件},{要更新的数据对象})//默认更新所有,其实就是替换了 db.集合名.update({更新条件},{$set:{要更新的字段名:要更新的字段值}})//更新指定字段 //如果被更新的字段已经存在则直接更新,如果不存在,则直接向被匹配的文档中增加该字段 db.集合名.update({更新条件},{$set:{要更新的字段名:要更新的字段值}},{multi:true})//替换符合条件的多个 db.集合名.save({})//插入数据 db.集合名.save({_id:ObjectId('')},{key:value})//整体替换
//删除数据 db.集合名.remove({匹配条件})//删除指定数据(默认删除匹配到的所有数据) db.集合名.remove({匹配条件},{justOne:true})//只删除符合条件的第一个

 nodejs操作mongodb

//node中操作mongodb
npm install mongodb  --save//安装mongodb模块

var mongodb=require('mongodb')
var MongoClient=mongodb.MongoClient()
MongoClient.connect('mongodb://localhost:27017/数据库名',function(err,db){
    if(err){
        throw new Error('连接失败')
    }
    //添加数据
    db.collection('集合名')
    .insertMany([
        {key:value}
        ],function(err,result){
            if(err){
                throw new Error('添加失败')
            }
        })
    //查询所有
    db.collection()
    .find({})//查询指定,则只需传入查询条件
    .toArray(function(err,docs){
        if(err){
            throw new Error('查询失败')
        }
    })
  //操作完数据库后,要关闭连接
  db.close()
})

六:express框架

//初始化项目结构
npm init  //在当前文件的根目录初始化一个package.json文件
 //(项目说明文件)
   name:项目名称
   version:版本
   description:项目描述
   main:入口文件
   scripts:{
           'test':'',
           'start':'node app.js'
   }
        *:当你在终端输入npm start的时候
        *:npm会自动找到package.json中的scripts中的start属性
        *:然后帮你执行start属性配置好的命令
   
   dependencies:{} 项目的依赖项(第三方包)
        *:npm install    //会自动找到package.json中的dependencies依次安装依赖包

express基本使用

//导入express模块
var express=require('express')
//1.调用express()得到一个app应用实例
//express()就相当于http.createServer()
//app就相当于原来的server
var app=express()
//在express中,render方法是需要单独来配置
//对于express来说需要单独配置要使用的模板引擎
//express 框架本身很灵活,很多功能需要单独配置才可以使用
//相对于 express 来说,配置这些东西其实就是插件
// 只要通过下面的配置,在 express 中就可以正常的使用 render 方法了
// 一定要记得使用 render 的时候,加上后缀名
app.render('', function(err, html){
  // ...
});

//2.给app应用实例挂载路由
app.get('/',function(req,res){
  res.end('hello world')
})
//3.绑定端口,启动服务器
app.listen('3000',function(){
    console.log('server is running.......')
})

七:nunjucks插件

nunjuck基本配置使用:


//nunjucks模板引擎----------nodejs中超牛的模板引擎
npm install nunjucks --save


var
express = require('express') var nunjucks = require('nunjucks')
var app = express() // 在 express 中,render方法需要单独配置的 // 对于express来说,需要单独配置使用的模板引擎 // 相对于express来说,配置这些东西其实就是插件 //只要通过下面的配置,在express中就可以正常使用render方法了
nunjucks.configure('views',{
express:app
}) app.get('/',function(req,res){
res.render('index.html')
})
app.listen(3000, function () { console.log('running...') })

 nunjucks模板引擎处理静态资源:

var express = require('express')
var nunjucks = require('nunjucks')
var path = require('path')
var router = require('./router')
var bodyParser = require('body-parser')
var app = express()

// 在 express 中暴露公共资源
// 在 express ,也是通过配置的形式提供对静态资源的处理
// 第一个参数用来配置静态资源的前缀路径
// 第二个参数用来指定该模糊路径查找的磁盘路径
// 第一个参数是可选参数,可以不指定
//    如果不指定第一个参数,则请求的时候,就不要加任何前缀
//    ,直接请求该目录中的资源路径就可以了
//    例如你要请求 node_modules/bootstrap/dist/css/bootstrap.css
//    则请求的时候,不要加 /node_modules 前缀,直接 /bootstrap/dist/css/bootstrap.css 就可以了
app.use('/node_modules',express.static(path.join(__dirname, 'node_modules')))
app.use('/public', express.static(path.join(__dirname, 'public')))

//配置nunjucks模板引擎
// noCache 用来指定缓存配置,默认是 false
var env = nunjucks.configure(config.viewPath, {
  noCache: true
})
env.express(app)


// 配置解析表单 post 提交数据的插件
// 该插件的名字叫:body-parser
// 可以专门用来和 express 结合使用,解析请求体中表单 post 提交的数据
// 只要使用了下面的配置,该插件会自动帮你把表单 post 请求体数据解析成一个对象,
// 然后挂载给 req 请求对象的 body 属性
// 也就是说,在后面的所有的处理函数中,如果想要拿到表单 post 请求体数据,
// 直接通过 req.body 来拿就可以了
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

// 2. 给 app 应用实例挂载路由
app.use(router)

// 3. 绑定端口,启动服务器
app.listen(3000, function () {
  console.log('running...')
})

 八、改完代码自动重启服务器

通过使用第三方命令行工具 `nodemon` 来解决改完代码重启服务器的问题

`nodemon` 是一个基于 Node 开发的一个第三方命令行工具,要想使用,在终端中通过:

```bash
$ npm install --global nodemon
```

安装完毕之后,把原来使用 `node app.js` 替换成 `nodemon app.js`,
这样的话就可以实现服务器端代码修改,直接自动重启服务器。

注意:全局命令行工具一次安装,永久使用,以后再使用,就不用再次安装了。

九、cnpm

 通过 cnpm 改变镜像源地址的方式解决 npm 被墙问题

- http://npm.taobao.org/

淘宝 NPM 镜像,这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。

只需要在下载包的时候,加上 `--registry=https://registry.npm.taobao.org`,那这样的话就会通过
淘宝的 `cnpm` 去下载,例如:

```bash
$ npm install 包名 --registry=https://registry.npm.taobao.org
```

这样话虽然可以解决,但是每次下载包的时候,还要自己手动加上这个参数,有一个更好的:


```bash
$ npm config set registry=https://registry.npm.taobao.org
```

该命令表示设置 npm 下载的镜像源地址为: `https://registry.npm.taobao.org`,
只要做了执行了该命令,那以后所有的 `install` 都会使用该地址。

如果想要删除该配置,使用下面的命令:

```bash
$ npm config delete registry
```

还可以通过下面的命令查看当前 npm 的配置列表:

```bash
$ npm config list
```

 十、requirejs基本使用