IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Node.js学习笔记二 -> 正文阅读

[JavaScript知识库]Node.js学习笔记二

五、过渡内容

  • 模块系统

    • 核心模块
    • 第三方模块
      • art-template
      • 必须通过npm来下载才可以使用
    • 自己写的模块
      • 自己创建的文件
  • npm

  • package.json

  • Express

    • 第三方Web开发框架
    • 高度封装了http模块
    • 更加专注于业务,而非底层
  • 增删改查

    • 使用文件来保存数据
  • MongoDB

    • 所有方法都封装好了
  • 什么是模块化

    • 文件作用域
    • 通信规则
      • 加载require
      • 导出
  • CommonJS模块规范

    在Node中的JavaScript还有一个很重要的概念,模块系统

    • 模块作用域
    • 使用require方法来加载模块
    • 使用exports接口对象来导出模块中的成员
  • 加载require

    语法:

    var 自定义变量名称 = require('模块')
    

    两个作用:

    • 执行被加载模块中的代码
    • 得到被加载模块中的exports导出接口对象
  • 导出exports

    • Node中是模块作用域,默认文件中所有的成员只在当前文件模块中有效

    • 对于希望可以被其他模块访问的成员,我们需要把这些公开的成员挂载到exports接口对象

    • 导出多个成员(必须在对象中)

      exports.a = 123
      exports.b = 'hello'
      exports.c = function () {
      	console.log('ccc')
      }
      exports.d = {
          foo: 'bar'
      }
      
    • 导出单个成员(拿到的就是:函数、字符串)

      module.exports = 'hello'
      

      以下情况会覆盖:

      module.exports = 'hello'
      
      //以这个为准
      module.exports = {
      	add: function() {
      		return x + y
      	}
      	str: 'hello'
      }
      
    • 也可以这样来导出多个成员

      module.exports = {
      	add: function() {
              return x + y
          },
          str: 'hello'
      }
      
    • 原理解析

      exports和module.exports是一个引用

      console.log(exports === module.exports)  //true
      exports.foo = 'bar'
      
      //等价于
      module.exports.foo = 'bar'
      
    • exports与module.exports的一些注意点

      • exports === module.exports结果为true
      • 对于module.exports.xxx=xxx的方式完全可以使用exports.xxx=xxx
      • 当一个模块需要导出单个成员时,这个时候必须使用module.exports=xxx的方式
      • 不要使用exports=xxx,不管用
      • 每个模块向外return的是module.exports
      • exports只是module.exports的一个引用
      • 即便为exports=xx重新赋值,也不会影响module.exports
      • 但是有一种赋值方式比较特殊:exports=module.exports,这个用来重新建立引用关系
  • require加载规则

    • 优先从缓存加载
    • 判断模块标识
  • package.json

    • 我们建议每一个项目都要有一个package.json文件(包描述文件,就像产品说明书一样)

    • 这个文件可以通过npm init的方式初始化

      • 对于咱们目前来说,最有用的是dependencies选项,可以帮我们保存第三方包的依赖信息
      • 如果node_module删除了也不用担心,npm install会自动把package.json中的dependencies
    • 示例

      C:\Users\zc\Desktop\npm-demo>npm init
      This utility will walk you through creating a package.json file.
      version: (1.0.0)
      See `npm help init` for definitive documentation on these fields
      and exactly what they do.
      
      Use `npm install <pkg>` afterwards to install a package and
      save it as a dependency in the package.json file.
      
      version: (1.0.0) 0.0.1
      description: 这是一个测试项目
      entry point: (index.js) main.js
      test command:
      git repository:
      keywords:
      author: zc
      license: (ISC)
      About to write to C:\Users\zc\Desktop\npm-demo\package.json:
      
      {
        "name": "npm-demo",
        "version": "0.0.1",
        "description": "这是一个测试项目",
        "main": "main.js",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1"
        },
        "author": "zc",
        "license": "ISC"
      }
      
      
      Is this OK? (yes) yes
      

      对于目前来说,最有用的文件是package.json,可以用来保存第三方包的依赖信息

      • 建议每个项目的根目录下都有一个package.json文件
      • 建议执行npm install 包名的时候都加上--save这个选项,目的是保存依赖项信息
      • 如果node_modules丢失了也不用担心,我们只需要执行npm install,就会自动把package.json中的dependencies中所有的依赖项都下载回来
  • package.json与package-lock.json

    注意:npm 5以前是不会有package-lock.json这个文件的

    npm 5以后才加入了这个文件

    安装包时,npm都会生成或更新package-lock.json这个文件

    • npm 5以后的版本安装包不需要加--save参数,它会自动保存依赖信息

    • 当你安装包的时候,会自动创建或更新package-lock.json这个文件

    • package-lock.json这个文件会保存node_modules中所有包的信息(版本、下载地址)

      • 这样的话重新npm install的时候速度就会提升
    • 从文件来看,有一个lock称之为锁

      • 这个lock是用来锁定版本的

      • 如果项目依赖了1.1.1版本,重新install会下载最新版本,而不是1.1.1

      • 我们的目的是希望可以锁定1.1.1版本,所以package.json这个文件的另一个作用

        就是锁定版本号,防止自动升级新版

  • npm常用命令

    • npm网站:https://www.npmjs.com

    • npm命令行工具

      • npm版本
      npm --version
      
      • 升级npm(自己升级自己)
      npm install --global npm
      
      • npm init

        npm init -y可以跳过向导,快速生成

      • npm install

        一次性把dependencies中的依赖项全部安装

      • npm install 包名

        只下载

        npm i 包名

      • npm install --save 包名

        下载并保存依赖项(package.json文件中的dependencies)

        npm i -S 包名

      • npm uninstall 包名

        只删除,如果有依赖项会依然保存

        npm un 包名

      • npm uninstall --save 包名

        删除的同时也会把依赖信息也去除

        npm un -S 包名

      • npm help

        查看使用帮助

      • npm 命令 --help

        查看指定命令的使用帮助

        例如忘记了npm uninstall的简写时,可以输入npm uninstall --help查看帮助

  • 解决npm被墙问题

    npm存储包文件的服务器在国外,有时候会很慢,需要解决这个问题

    cnpm:http://npm.taobao.org

    # 在任意目录下执行都可以
    # --global表示安装到全局,而非当前目录
    # --global不能省略,否则不管用
    npm install --global cnpm
    

    把之前的npm替换为cnpm

    举个例子

    # 这里还是走国外的npm服务器,速度比较慢
    npm install jquery
    
    # npm install jquery
    cnpm install jquery
    

    如果不想安装cnpm又想使用淘宝的服务器来下载

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

    但是每次手动这样加参数很麻烦,所以我们可以把这个选项加入配置文件中

    npm config set registry https://registry.npm.taobao.org
    
    # 查看npm配置信息
    npm config list
    

    只要经过了上面命令的配置,则以后所有的npm install都会默认通过淘宝的服务器来下载

  • path路径操作模块

    • path.basename获取一个路径的文件名(默认包含扩展名)
    • path.dirname获取一个路径中的目录部分
    • path.extname获取一个路径中的扩展名部分
    • path.parse把一个路径转为对象
      • root 根路径
      • dir 目录
      • base 包含后缀名的文件名
      • ext 后缀名
      • name 不包含后缀名的文件名
    • path.join需要使用路径拼接时推荐这个方法
    • path.isAbsolute判断一个路径是否是绝对路径
    > path.basename('c:/a/b/c/index.js')
    'index.js'
    > path.basename('c:/a/b/c/index.js', '.js')
    'index'
    > path.basename('c:/a/b/c/index.js', '.html')
    'index.js'
    > path.dirname('c:/a/b/c/index.js')
    'c:/a/b/c'
    > path.extname('c:/a/b/c/index.js')
    '.js'
    > path.extname('c:/a/b/c/index.html')
    '.html'
    > path.isAbsolute('c:/a/b/c/index.html')
    true
    > path.isAbsolute('c/index.html')
    false
    > path.isAbsolute('./c/index.html')
    false
    > path.isAbsolute('/c/index.html')
    true
    > path.parse('c:/a/b/c/index.html')
    {
      root: 'c:/',
      dir: 'c:/a/b/c',
      base: 'index.html',
      ext: '.html',
      name: 'index'
    }
    > path.join('c:/a','b')
    'c:\\a\\b'
    > var str = ''c:a/' + '/b'
    var str = ''c:a/' + '/b'
                ^
    
    Uncaught SyntaxError: Unexpected identifier
    > var str = 'c:a/' + '/b'
    undefined
    > str
    'c:a//b'
    > var str = 'c:a' + 'b'
    undefined
    > str
    'c:ab'
    > path.join('c:/a/', '/b')
    'c:\\a\\b'
    > path.join('c:/a/', '/b', 'c')
    'c:\\a\\b\\c'
    > path.join('c:/a/', '/b', 'c', 'd')
    'c:\\a\\b\\c\\d'
    > path.join('c:/a/', '/b', 'c', 'd', 'e')
    'c:\\a\\b\\c\\d\\e'
    > path.join('c:/a/', '/b', 'c', 'd', 'e', 'f')
    'c:\\a\\b\\c\\d\\e\\f'                                                  
    
  • Node中的其他成员

    在每个模块中,除了requireexports等模块相关API之外,还有两个特殊的成员:

    • __dirname动态获取可以用来获取当前文件模块所属模块的绝对路径
    • __filename动态获取可以用来获取当前文件的绝对路径
    • __dirname__filename是不受执行node命令所属路径影响的

    在文件操作中,使用相对路径是不可靠的,因为在Node中文件操作的路径被设计为执行node命令所处的路径。

    为了解决这个问题,需要把相对路径转变为绝对路径。

    这里我们可以使用__dirname或者__filename来帮我们解决这个问题

    在拼接路径的过程中,为了避免手动拼接带来的一些低级错误,所以推荐多使用:path.join()来辅助拼接

    为了尽量避免这个问题,在文件操作中使用的相对路径统一转换为动态的绝对路径

    补充:模块中的路径标识和这里的路径没关系,不受影响(相对于文件模块)

六、Express

6.1 起步

原生的http在某些方面表现不足以应对我们的开发需求,所以我们需要使用框架来加快开发效率,框架的目的就是提高效率,让我们的代码高度统一。

在Node中,有很多Web开发框架,这里我们以Express为主。

  • 官网:http://expressjs.com
  • 安装:npm install --save express

6.2 修改完代码自动重启

这里使用一个第三方命名工具,nodemon来帮我们解决频繁修改代码重启服务器问题

nodemon是一个基于Node.js开发的一个第三方命令行工具,我们使用的时候需要独立安装

npm install --global nodemon

安装完毕之后,使用

node app.js

# 使用nodemon
nodemon app.js

只要是通过nodemon app.js启动的服务,它会监视你的文件变化,当文件发生变化的时候,自动帮你重启服务器

6.3 基本路由

路由器

  • 请求方法
  • 请求路径
  • 请求处理函数

get:

// 当你以GET方法请求/的时候,执行对应的处理函数
app.get('/', function(req, res) {
    res.send('Hello World!')
})

post:

// 当你以POST方法请求/的时候,执行对应的处理函数
app.post('/', function(req, res) {
    res.send('Got a POST request')
})

6.4 静态服务

app.use(express.static('public'))
app.use(express.static('files'))

app.use('/static', express.static('public'))
app.use('/static', express.static(path.join(__dirname, 'public')))

6.5 在Express中配置使用art-template模板引擎

安装:

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

配置:

app.engine('art', require('express-art-template'))

使用:

app.get('/', function(req, res) {
	// express默认会去项目中的views目录中找index.html
	res.render('index.html', {
		title: 'hello world'
	})
})

如果希望修改默认的views视图渲染目录,可以:

// 注意:第一个参数views千万不要写错
app.set('views', 目录路径)

6.6 在Express中获取表单GET请求体数据

Express内置了一个API,可以通过req.query来获取

req.query

6.7 在Express获取表单POST请求体数据

在Express中没有内置获取表单POST请求体的API,这里我们需要使用一个第三方包:body-parser

安装:

npm install --save body-parser

配置:

var express = require('express')
// 0.引包
var bodyParser = require('body-parser')

var app = express()

// 配置body-parser
// 只要加入这个配置,则在这个req请求对象上会多出来一个属性:body
// 也就是说你可以通过req.body来获取表单POST请求体数据了
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))
//parse application/json
app.use(bodyParser.json())


使用:

app.use(function(req, res) {
    res.setHeader('Content-Type', 'text/plain')
    res.write('you posted:\n')
    res.end(JSON.stringify(req.body, null, 2))
})

6.8 提取路由模块

请求方法请求路径get参数post参数备注
GET/students渲染首页
GET/students/new渲染添加学生页面
POST/studentsname/age/gender/hobbies处理添加学生请求
GET/students/editid渲染编辑
POST/students/editid/name/age/gender/hobbies处理编辑请求
GET/students/deleteid处理删除请求
//router.js路由模块
//职责:
//	处理路由
//	根据不同的请求方法+请求路径设置具体的请求处理函数
//模块职责要单一,不要乱写
//划分模块的目的是为了增强项目代码的可维护性
//提升开发效率

var express = require('express')

// 1.创建一个路由容器
var router = express.Router()

// 2.把路由挂载到router路由容器中
router.get('/students', function (req, res) {
})

router.get('/students/new', function (req, res) {
})

router.post('/students/new', function (req, res) {
})

router.get('/students/edit', function (req, res) {
})

router.post('/students/edit', function (req, res) {
})

router.get('/students/delete', function (req, res) {
})

// 3.把router导出
module.exports = router

6.9 设计操作数据的API文件模块

// student.js文件模块


// 获取所有学生列表
exports.find = function () {
    
}

// 添加保存学生
exports.save = function () {
    
}

// 更新学生
exports.update = function() {
    
}

// 删除学生
exports.delete = function() {
    
}

6.10 自己编写的步骤

  • 处理模板
  • 配置开放静态资源
  • 配置模板引擎
  • 简单路由:/students渲染静态也处理
  • 路由设计
  • 提取路由模块
  • 由于接下来一系列的业务操作都需要处理文件数据,所以要封装student.js
  • 先写好student.js文件结构
    • 查询所有学生列表的API find
    • findById
    • save
    • updateById
    • deleteById
  • 实现具体功能
    • 通过路由收到请求
    • 接收请求中的数据(get、post)
      • req.query
      • req.body
    • 调用数据操作API处理数据
    • 根据操作结果给客户端发送响应
  • 业务功能顺序
    • 列表
    • 添加
    • 编辑
    • 删除
  • find
  • findIndex

七、MongoDB

参考https://www.runoob.com/mongodb/mongodb-tutorial.html

7.1 关系型数据库和非关系型数据库

表就是关系,或者说表与表之间存在关系

  • 所有的关系型数据库都需要通过SQL语言来操作
  • 所有的关系型数据库在操作之前都需要设计表结构
  • 而且数据表还支持约束
    • 唯一的
    • 主键
    • 默认值
    • 非空
  • 非关系型数据库非常灵活
  • 有的非关系型数据库就是key-value对
  • 但是MongoDB是长得最像关系型数据库的非关系型数据库
    • 数据库->数据库
    • 数据表->集合(数组)
    • 表记录->文档对象
  • MongoDB不需要设计表结构
  • 你可以任意地存放数据

7.2 下载与安装

下载地址

  • 下载

  • 安装

  • 配置环境变量

  • cmd输入mongod --version判断是否安装成功

7.3 启动和关闭数据库

启动:

# mongodb默认使用执行mongod命令所处盘符根目录下的/data/db作为自己的数据存储目录
# 所以在第一次执行该命令前先自己手动新建一个/data/db
mongod

如果想要修改默认的数据存储目录,可以:

mongod --dbpath=数据存储目录路径

停止:

在开启服务的控制台,直接Ctrl+C即可停止
或直接关闭开启服务的控制台也可以

7.4 连接数据库

连接:

# 该命令默认连接本机的MongoDB服务
mongo

退出:

# 在连接状态输入exit退出连接
exit

7.5 基本命令

  • show dbs
    • 查看显示所有数据库
  • db
    • 查看当前操作的数据库
  • use 数据库名称
    • 切换到指定的数据库(如果没有会新建)
  • 插入数据
    • db.students.insertOne({“name”: “Jack”})
    • show collections
    • db.students.find()

7.6 在Node中如何操作MongoDB数据库

  • 使用官方的mongodb包来操作:http://github.com/mongodb/node-mongodb-native

  • 使用第三方mongoose来操作MongoDB数据库

    • mongoose基于MongoDB官方的mongodb包再一次做了封装
    • 网址:http://mongoosejs.com
    • 官方指南:http://mongoosejs.com/docs/guide.html
    • 官方API文档:http://mongoosejs.com/docs/api.html
  • MongoDB数据库的基本概念

    • 可以有多个数据库
    • 一个数据库中可以有多个集合
    • 文档结构很灵活,没有任何限制
    • MongoDB非常灵活,不需要像MySQL一样事先创建数据库、表、设计表结构
    • 在这里只需要当你插入数据时指定往哪个数据库的哪个集合插入数据即可,一切都由MongoDB来帮你自动完成建库建表这件事
    {
        qq: {
            users: [
                {name: '张三', age: 15},
                {name: '李四', age: 15},
                {name: '王五', age: 15},
                {name: '张三123', age: 15},
                {name: '张三321', age: 18}
            ],
            products: [
                
            ],
            ...
        },
        taobao: {
            
        },
        baidu: {
            
        }
    }
    
  • 增加数据

    var admin = new User({
      username: 'zs',
      password: '123456',
      email: 'admin@admin.com'
    })
    
    admin.save(function (err, ret) {
      if (err) {
        console.log('保存失败')
      } else {
        console.log('保存成功')
        console.log(ret)
      }
    })
    
  • 查询数据

    查询所有:

    User.find(function (err, ret) {
      if (err) {
        console.log('查询失败')
      } else {
        console.log(ret)
      }
    })
    

    按条件查询所有:

    User.find({
      username: 'zs'
    }, function (err, ret) {
      if (err) {
        console.log('查询失败')
      } else {
        console.log(ret)
      }
    })
    

    按条件查询单个:

    User.findOne({
      username: 'zs'
    }, function (err, ret) {
      if (err) {
        console.log('查询失败')
      } else {
        console.log(ret)
      }
    })
    
  • 删除数据

    根据条件删除所有:

    User.remove({
      username: 'zs'
    }, function (err, ret) {
      if (err) {
        console.log('删除失败')
      } else {
        console.log('删除成功')
        console.log(ret)
      }
    })
    

    根据条件删除一个:

    Model.findOneAndRemove(conditions, [options], [callback])
    

    根据id删除一个:

    Model.findByIdAndRemove(id, [options], [callback])
    
  • 更新数据

    根据条件更新所有:

    Model.update(conditions, doc, [options], [callback])
    

    根据指定条件更新一个:

    Model.findOneAndUpdate([conditions], [update], [options], [callback])
    

    根据id更新一个:

    User.findByIdAndUpdate('5a001b23d219eb00c8581184', {
      password: '123'
    }, function (err, ret) {
      if (err) {
        console.log('更新失败')
      } else {
        console.log('更新成功')
      }
    })
    

参考链接

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-20 12:24:14  更:2021-10-20 12:25:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:48:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码