Node.js学习笔记(三)

1 使用 nodemon 工具来自动重启web服务器

1.1 nodemon的作用:能够实时监听当前项目中,文件的变化;只要监听到了文件的变化,则 nodemon 工具,会自动重新启动 web 服务器,从而使最新的代码生效;免去了程序员手动重启服务器的困扰;

1.2 如何安装:运行 npm i nodemon -g 全局安装即可;
1.3 如何使用

nodemon .\01-express中使用art-template.js

2 Node 中开发web项目的框架 - express

定义(什么是Express):一个快速的网站开发框架,封装了原生的http模块,用起来更方便;API更人性化

2.1 express 框架的特点

  1. 基于Node.js平台之上,进一步封装了 http 模块,从而提供了更好用,更友好的 API
  2. 使用Express创建网站,比使用原生的http模块更加方便;
  3. Express 并没有覆盖 原生 http 模块中的方法,而是基于 原生方法之上,做了更友好的封装,让用户体验更好

2.2 express 框架的安装和基本使用

  • 安装:
 npm i express -S
  • 创建基本的 express 服务器:
// 导入 expree第三方模块
const express = require('express')
// 创建服务器的实例
const app = express()
// 监听客户端请求
app.get('/',(req,res) => {
    // res.end('你好!')  //end()为http模块的方法,express也可以用  乱码问题
    res.send("你好!") //express方法 没有乱码问题
})
// 启动服务器
app.listen(3000,() => {
    console.log('server running at http://127.0.0.1:3000')
})

2.3 express 中的快捷方法

  1. res.send()
app.get('/',(req,res) => {
   res.send('Ok') //普通字符串
   res.send({name:'cc',age:16}) //对象 {"name":"cc","age":16} json格式
   res.send(['吃饭','睡觉','打豆豆']) //数组  ["吃饭","睡觉","打豆豆"]
   res.send(new Buffer('123'))  //二进制  下载效果 不常用
})
  1. res.sendFile()
  • 注意:res.sendFile() 可以向浏览器发送 静态页面;
app.get('/',(req,res) => {
    // 一个参数:这个参数必须是绝对路径
    // res.sendFile(path.join(__dirname,'./public/index.html'))
    // 两个参数: 第一个实参可传相对路径  第二个必须是绝对路径
    res.sendFile('./public/index.html',{root:__dirname})
})
app.get('/movie',(req,res) => {
    res.sendFile('./public/movie.html',{root:__dirname})
})
app.get('/about',(req,res) => {
    res.sendFile('./public/about.html',{root:__dirname})
})

2.4 使用 express.static() 快速托管静态资源

app.use(express.static('./public'))
// app.use()专门用来注册中间件
// express.static()把指定的目录托管为静态资源目录,这样指定目录下的所有文件都可以直接被浏览器访问,是express的内置中间件;
app.use('/page',express.static('./public'))
    //  /page:指定要挂载的虚拟路径

2.5 为 express 框架配置模板引擎渲染动态页面

  • 安装 ejs 模板引擎
npm i ejs -S
  • 注意,模板页面的 后缀名,可以省略不写!
// 使用 app.set('view engine',引擎模板的名称)
app.set('view engine','ejs')
//设置模板页面的默认存放路径 app.set('views','模板页面的具体存放路径')
app.set('views','./ejs_pages')  //默认存放路径
app.get('/',(req,res) => {
    //若想调用res.render,必须先配置引擎模板
    res.render('index.ejs',{name:'cc',age:16,hobby:['吃饭','睡觉','打豆豆']})
})

2.6 在 express 中配置 art-template

cnpm i art-template express-art-template -S
const artTemplate = require('express-art-template')
// 注意: 安装两个包 art-template  express-art-template  安装多个包用空格隔开
// 1.使用app.engine方法自定义模板引擎(模板引擎的名字,artTemplate)
    // 这个位置配置的模板引擎的名字将会是模板文件的后缀名称
app.engine('html',artTemplate)
// 2 使用app.set('view engine','指定模板引擎名称')来配置项目中用到的模板引擎
app.set('view engine','html')
// 3 配置模板页面的存放路径  配置模板引擎的根目录
app.set('views','./art-pages')

app.get('/',(req,res) => {
    res.render('index.html',{name:'cc',age:16,hobby:['吃饭','睡觉','打豆豆']})
})

2.7 使用 express 框架中提供的路由来分发请求

  • 什么是路由:路由就是对应关系;

  • 什么叫做后端路由:前端请求的URL地址,都要对应一个后端的处理函数,那么 这种URL地址到 处理函数之间的对应关系,就叫做后端路由;

  • 定义路由模块

      // 1. 封装单独的 router.js 路由模块文件
      const express = require('express')
      // 创建路由对象
      const router = express.Router()
    
      router.get('/', (req, res)=>{})
      router.get('/movie', (req, res)=>{})
      router.get('/about', (req, res)=>{})
    
      // 导出路由对象
      module.exports = router
  • 使用路由模块
      // 导入自己的路由模块
      const router = require('./router.js')
      // 使用 app.use() 来注册路由
      app.use(router)

2.8 Express 框架里 中间件的概念

  • 什么是中间件

定义:中间件就是一个处理函数;只不过这个函数比较特殊,包含了三个参数,分别是 req,res,next

注意:中间件方法中的三个参数:

  • req:请求对象;
  • res:响应对象;
  • next:next()可以被调用,表示调用下一个中间件方法;
  • Express 框架中对中间件的5种分类
  1. 应用级别的中间件: 挂载到 app 上的中间件 app.get(‘URL地址’, (req, res, next)=> {});
  2. 路由级别的中间件: 挂载到 router 对象上的中间件 router.get(‘url地址’, (req, res, next)=>{})
  3. 错误级别的中间件: 回调函数中,有四个参数 app.use((err, req, res, next)=>{})
  4. 唯一内置的中间件: express.static()
  5. 第三方中间件: 非express框架提供的,需要程序员手动安装才能使用的中间件;body-parser 解析post 表单数据
const querystring = require('querystring');

// 定义应用级别的中间件
app.use((req,res,next) => {
    let dataStr = ''
    // 只要客户端向服务器提交了表单,都会触发req的data事件
    // 在data事件中,可以获取客户端每次提交过来的不完整的数据
    req.on('data',chunk => {
        dataStr += chunk
    })

    // 只要req出发了end事件,就表示表单数据提交完毕
    req.on('end',() => {
        // console.log(dataStr) //username=cc&userage=12
        //想要把 username=ls&password=123 字符串,
        //解析为 { username: 'ls', password: 123 }
        // querystring.parse() 方法将 URL 查询字符串 dataStr 解析为键值对的集合。
        const obj = querystring.parse(dataStr)
        
        req.body = obj

        // 注意:在中间件中,最后一定要合理调用next(),否则服务器无法结束这次响应
        next()
    })
})

// get请求
app.get('/',(req,res) => {
    res.sendFile('./11-中间件index.html',{root:__dirname})
})
// post请求
app.post('/postdata',(req,res) => {
    res.send(req.body)   //{"username":"cc","userage":"123"}
})

2.9 Express 中进行数据库操作

  • 配置 MySql 数据库环境
npm i mysq
  • mysql 第三方模块的介绍和基本配置
// 1.导入mysql模块
const mysql = require('mysql')
// 2.创建mysql的连接对象
const conn = mysql.createConnection({
    host:'localhost',
    user:'root',
    password:'root',
    database:'express-mysql'
})
  • 使用 mysql 第三方模块实现 CRUD
  1. 查询
// 查询conn.query('sql语句',回调函数)
const sql ='SELECT * FROM `user` '
conn.query(sql,(err,result) => {
    if(err) return console.log('获取数据失败'+err.message)
    console.log(result) 
    //[ RowDataPacket { id: 1, name: 'cc', age: 16, gender: 'girl' } ]
})
  1. 新增
const user = {name:'zz',age:22,gender:'boy'}
const sql = "INSERT INTO `user` SET ?"
conn.query(sql,user,(err,result) => {
    if(err) return console.log('插入数据失败'+err.message)
    console.log(result) 
    // OkPacket {
    //     fieldCount: 0,
    //     affectedRows: 1,
    //     insertId: 6,
    //     serverStatus: 2,
    //     warningCount: 0,
    //     message: '',
    //     protocol41: true,
    //     changedRows: 0 
    // }
})
  1. 修改
const user ={id:6,name:'zz',age:18}
const sql = 'UPDATE `user` SET ? WHERE id = ?'
//若sql语句中包含多个?占位符,第二个实参必须传递一个数组,并一一对应
conn.query(sql,[user,user.id],(err,result) => {
    if(err) return console.log("修改数据失败")
    console.log(result)
    // OkPacket {
    //     fieldCount: 0,
    //     affectedRows: 1,
    //     insertId: 0,
    //     serverStatus: 2,
    //     warningCount: 0,
    //     message: '(Rows matched: 1  Changed: 1  Warnings: 0',
    //     protocol41: true,
    //     changedRows: 1 
    // }
})
  1. 删除
const sql = 'DELETE FROM `user` WHERE id=?'
conn.query(sql, 1, (err, result) => {
    if (err) return console.log('删除失败!' + err.message)
    console.log(result)
    // OkPacket {
    //     fieldCount: 0,
    //     affectedRows: 1,
    //     insertId: 0,
    //     serverStatus: 2,
    //     warningCount: 0,
    //     message: '',
    //     protocol41: true,
    //     changedRows: 0 
    // }
})

模块加载机制

  1. 优先从缓存中加载
  • 当一个模块初次被 require 的时候,会执行模块中的代码,当第二次加载相同模块的时候,会优先从缓存中查找,看有没有这样的一个模块!
  • 好处:提高模块的加载速度;不需要每次都重新执行并加载模块!
  1. 核心模块的加载机制
  • 先查找缓存;
  • 如果缓存中没有,再去加载核心模块;
  1. 用户模块的加载机制
  • 先查找缓存;
  • 如果缓存中没有则尝试加载用户模块;
  • 如果在加载用户模块时候省略了后缀名,则:
    首先,严格按照指定的名称去查找
    其次,尝试加载后缀名是 .js 的文件
    如果没有.js的文件,则尝试加载 .json 结尾的文件
    如果没有 .json 的文件,则尝试加载 .node 结尾的文件
    查找规则:index -> index.js -> index.json -> index.node
  1. 第三方模块的加载机制【了解】
  • 先在项目根目录中查找node_modules文件夹
  • 在node_modules文件夹下,查找模块相关的文件夹
  • 在对应的文件夹下,查找package.json的文件
  • 查找package.json文件中的main属性(指定了模块的入口文件)
  • 如果找到了main属性,同时,main属性指定的文件路径存在,那么尝试加载指定的文件模块
  • 加入没有main属性,或者main属性对应的文件不存在,或者没有package.json,那么会依次尝试加载index.js,index.json,index.node;
  • 如果没有index相关的文件,或者没有指定模块对应文件夹,或者,当前项目根目录中没有node_modules文件夹,则向上一层目录中查找node_modules,查找规则同上!
  • 最后,如果在项目所在磁盘的盘符根目录中,还找不到对应模块,则报错:cannot find module ***

你可能感兴趣的:(node.js)