Node.js 是一个开源与跨平台的 JavaScript 运行时环境。 它是一个可用于几乎任何项目的流行工具!
Node.js 在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核)。 这使 Node.js 表现得非常出色。
Node.js 应用程序运行于单个进程中,无需为每个请求创建新的线程。 Node.js 在其标准库中提供了一组异步的 I/O 原生功能(用以防止 JavaScript 代码被阻塞),并且 Node.js 中的库通常是使用非阻塞的范式编写的(从而使阻塞行为成为例外而不是规范)。
当 Node.js 执行 I/O 操作时(例如从网络读取、访问数据库或文件系统),Node.js 会在响应返回时恢复操作,而不是阻塞线程并浪费 CPU 循环等待。
这使 Node.js 可以在一台服务器上处理数千个并发连接,而无需引入管理线程并发的负担(这可能是重大 bug 的来源)。
Node.js 具有独特的优势,因为为浏览器编写 JavaScript 的数百万前端开发者现在除了客户端代码之外还可以编写服务器端代码,而无需学习完全不同的语言。
在 Node.js 中,可以毫无问题地使用新的 ECMAScript 标准,因为不必等待所有用户更新其浏览器,你可以通过更改 Node.js 版本来决定要使用的 ECMAScript 版本,并且还可以通过运行带有标志的 Node.js 来启用特定的实验中的特性。
学习 Node.js 不是学习一种新的语言,而是一门技术
node 利用 JavaScript 语言作为基础,并提供了一些模块,开发者使用JavaScript 调用这些模块中的方法,就可以实现例如读写文件、操作数据库等功能
比如 unity3d 这门技术利用了早已经诞生的 c# 语言作为开发语言…
npm 的简单结构有助于 Node.js 生态系统的激增,现在 npm 仓库托管了超过 1,000,000 个可以自由使用的开源库包。
官网下载:https://nodejs.org/zh-cn/download/
根据自己的电脑型号选择安装包下载
下载后双击安装程序
然后根据以下截图一直按下一步操作就行了
安装过程:
安装完成:
注意:安装完成后,桌面上并没有什么快捷方式,因为Node仅仅是一个JS的执行环境,我们可以通过Windows PowerShell进行验证
输入命令:
node -v
当出现安装的版本时,就说明安装成功了
当我们安装成功后我们要经行全局变量的配置
Dom: 操作页面中的元素
Bom: 操作浏览器
首先,所有前面学习过的 ECMAScript 语法在Node中都可以使用,包括ES6的语法
编写一个文件名为 hello.js的文件,编写内容
let a= 10
console.log(a)
打开终端,输入命令
// node 文件名.js
node hello.js
在此注意,如果你的文件名比较长,你害怕写错,可以先输入 node
然后输入空格,输入h+tab会自动补全文件名,敲击回车键后,就可以执行 hello.js 中的代码了
如果不喜欢在终端中打开,我们还可以在命令窗口打开
通过上面代码的编写和执行,我们总结如下几点 :
npm 中文文档
由于我们每次输入都要执行一次命令来刷新程序,会导致代码运行特别麻烦,所以我们需要一个自动刷新浏览器和运行的工具
而在node.js中有一个非常厉害的工具叫npm,他是一个包管理工具
NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。
Nodejs自身提供了基本的模块,但是开发实际应用过程中仅仅依靠这些基本模块则还需要较多的工作。幸运的是,Nodejs库和框架为我们提供了帮助,让我们减少工作量。但是成百上千的库或者框架管理起来又很麻烦,有了NPM,可以很快的找到特定服务要使用的包,进行下载、安装以及管理已经安装的包。
我们可以从它的官网上 https://www.npmjs.com/ 搜索你所需要安装的工具包,里面会有他的安装命令和方法,例如搜索jquery:
找到node,就可以看到他的安装命令
我们把命令输入到终端中,就可以安装上了
当我们安装完毕之后,目录下会出现一个 node_modules文件夹,这个文件夹里放着我们所安装的所有安装包,打开会看到你会看到刚刚安装的jquery文件夹。
而我们正需要就是nodemon工具
Nodemon是一种帮助开发基于node.js的应用程序的工具,方法是在检测到目录中的文件更改时自动重新启动节点应用程序。
Nodemon不会对你的代码产生额外的更改,它只是node命令的替代品。因为当你修改源文件后,如果你用的是原来的node 则必须手动重启 你的更改才会有效。但是如果用的是nodemon,则你不需要手动操作,它会检测你的代码改动自动重启。
nodemon支持局部的和全局的配置文件。它们通常被命名为nodemon.js.可以位于当前的工作文件夹内,也可以位于你的home文件夹内(项目依赖)。一个配置文件可以被–config
命令来指定。
全局安装:
npm install/i -g nodemon //加上 -sava/ -S,下载依赖信息
局部安装
npm install/i nodemon
运行命令:
nodemon 文件名.js
安装好之后我们可以使用 nodemon 来运行命令
当我们不需要继续运行文件时,我们可以 Ctrl + C 来终止运行
当我们不需要这个软件时,我们也可以使用命令来卸载它
卸载也有两种卸载方式,一种卸载全局安装的,一种卸载局部安装的
卸载全局
npm uninstall -g nodemon //加上--save / 删除包括依赖信息
卸载局部
npm uninstall nodemon
启动nodemon时出错 无法加载文件C:\Users\gxf\AppData\Roaming\npm\nodemon.ps1,因为在此系统上禁止运行脚本
解决方案:
以前学习过,console 是 window 的全局对象,但是在 node 中,global 才是全局对象
Node中全局对象下有以下方法,可以在任何地方使用,global可以省略
新建一个 global.js 文件,编写下面代码
global.setTimeout(() => {
console.log('timeout')
}, 2000);
运行 global.js 文件,进行测试
证明,上面的这些API确实是全局对象 global 中的
JavaScript的局限性
CommonJS规范
作用:操作文件的路径,为文件操作服务
引入模板 :
const path = require('path')
常用的几个函数:
path.join(第一个路径,第二个路径) : 拼接路径
导入模块
var path = require("path");
basename() 获取文件名+后缀
path.basename("/笔记大全/伸缩布局代码/align-content.html")
//第二个参数,去掉获取的文件名中的相同部分
path.basename("E:/笔记大全/伸缩布局代码/align-content.html","html")
dirname() 获取目录
path.dirname("/笔记大全/伸缩布局代码/align-content.html")
extname() 获取文件的扩展名(尾缀名)
path.extname("/笔记大全/伸缩布局代码/align-content.html")
join() 合并路径
var p1 = "E:/笔记大全";
var p2 = "/伸缩布局代码";
console.log(path.join(p1,p2));
parse() 把路径转换为一个对象
解析对象的路径为组成其的片段:
root
: 根路径。dir
: 从根路径开始的文件夹路径。base
: 文件名 + 扩展名name
: 文件名ext
: 文件扩展名 path.parse("E:/笔记大全/伸缩布局代码/align-content.html","html")
{
root:'E:/',
dir:'E:/笔记大全/伸缩布局代码',
base:'align-content.html',
ext:'.html',
name:'align-content'
}
format() 把一个路径对象转换成一个路径字符串
var obj = {
root:'E:/',
dir:'E:/笔记大全/伸缩布局代码',
base:'align-content.html',
ext:'.html',
name:'align-content'
}
console.log(path.format(obj));
delimiter 环境变量的分隔符,可以跨平台 windows下是; 其它平台 :
relative 接受 2 个路径作为参数
require('path').relative('/Users/joe', '/Users/joe/test.txt') //'test.txt'
require('path').relative('/Users/joe', '/Users/joe/something/test.txt') //'something/test.txt'
作用:
处理客户端请求过来的URL
代码步骤:
在这中间处理客户端请求过来的URL
导入模块var url=requre(“url”)
parse()把字符串的路径传换成对象
var uri = "http://www.baidu.com:8080/images/1.jpgversion=1.0&time=1123#abcd";
console.log(url.parse(uri));
format() 把路径对象转换成字符串
var obj = {
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.baidu.com:8080',
port: '8080',
hostname: 'www.baidu.com',
hash: '#abcd',
search: '?version=1.0&time=1123',
query: 'version=1.0&time=1123',
pathname: '/images/1.jpg',
path: '/images/1.jpg?version=1.0&time=1123',
href: 'http://www.baidu.com:8080/images/1.jpg?version=1.0&time=1123#abcd' };
var str = url.format(obj);
console.log(str);
作用:处理客户端通过get/post
请求传递过来的参数
使用关键点:
get
请求时 querystring 一般是配合 url 核心模块一起使用的get/post
请求最终都需要调用 querystring.parse方法,将请求传递过来的键值对字符串转成js对象,方便操作
注意:
导入模块 var querystring = require(“querystring”);
parse() 把参数字符串解析成对象
var obj = querystring.parse("version=1.0&time=123");
console.log(obj);
stringify() 把一个对象转换成一个字符串
escape() url进行编码
unescape() url进行解码
前提:以后的所有静态资源(html,css,js,图片等)都是放在服务端的,如果浏览器需要这些html,css,js,图片等资源,则需要先将其读取到node.exe的内容中,然后再返回给浏览器
作用:
代码步骤:
导入 fs 核心模块
const fs = require("fs");
使用相应的方法来写入文件、读取文件等操作
注意点:
作用:
代码步骤:
引入http 模块
// 引入 http 模块
const http = require("http");
作用:全局共享的,不需要导入模块即可以使用
常用的属性:
__dirname : 文件所在的文件夹路径
__filename : 文件所在的路径
require() : 导入需要的模块
module : 自定义模块时用到
exports : 自定义模块时用到
在我们不算长的js代码编写经历中,可能体会到或者体会不到,js开发有如下弊端
在实际的发展中,js模块化大体有如下几种规范
node.js中使用的就是 commonjs 模块化规范
那么到底如何做到模块化开发呢?
Node使用CommonJS规范 ,它有四个重要的环境变量:module、exports、require、global。实际使用时,module变量代表当前模块,exports是module的属性,表示对外输出的接口,加载某个模块,实际上是加载该模块的module.exports属性。用require加载模块(同步)。
Node为每隔模块提供了一个exports变量,指向module.exports,这等同于每个模块头部有这样的一行代码:
var exports = module.exports
exports只是module.exports的一个引用,指向module.exports对象所在的地址
注意:
const a_module=require('./a.js')
也可以定义成员的时候就直接向外暴漏
exports.b=20
也可以定义函数,并向外暴漏
function add(a,b){
return a+b
}
exports.add=add
模块外部如下调用
const a_module=require('./a')
console.log(a_module.add(5,6));
如果模块内成员较多,也可以在定义成员后,一次性向外暴漏所有需要的成员
a.js
module.exports.a=10
module.exports.b=20
module.exports.add=(a,b)=>a+b
b.js
const a_module=require('./a')
console.log(a_module.a);
console.log(a_module.b);
console.log(a_module.add(4,5));
a.js
function sum(a, b) {
return a + b
}
function mul(a, b) {
return a * b
}
let salary=1000
// exports.sum=sum //exorts={sum:sum}
// exports.mul=mul // exorts={sum:sum,mul:mul}
// module.exports 是根本,exports只是它的一个别名
// 改造
// module.exports.sum=sum
// module.exports.mul=mul
// 继续改造
module.exports = {
sum, // 使用函数sum的名字作为对象中的属性,使用函数sum作为属性的值 =>sum:sum
mul,
salary // 使用变量salary的名字作为属性名称,使用变量salary 的值作为属性的值 salary:salary
}
b.js
//a={ sum: [Function: sum], mul: [Function: mul],salary:1000 }
// const a=require('./a')
// console.log(a)
// 使用解构赋值
let { sum, mul,salary } = require('./a')
console.log(sum(4, 5))
console.log(mul(4, 5))
console.log(salary)
总结:
exports.name=name
module.exports.name=name
1、exports是module.exports的别名(地址引用关系),导出对象最终以module.exports为准
上面案例用到了 exports.属性=属性值 的方式进行模块成员导出
还可以使用 module.exports.属性=属性值 的方式进行模块成员导出
下面证明这个结论
比如,在m.js 中编写如下代码
let name='李白'
let age=20
exports.name=name
module.exports.age=age
在 n.js 中编写下面代码
const m=require('./m.js')
console.log(m)
输出结果
{ name: '李白', age: 20 }
可见,exports 与 module.exports 确实是一个地址,也就说最后修改的都是 module.exports
exports只能使用语法来向外暴露内部变量,module.exports既可以通过语法,也可以直接赋值一个对象
let name='李白'
let age=20
exports={
name:name,
age:age
}
const a_module=require('./a')
console.log(a_module);
输出结果为 {}
如果使用 module.exports
let name='李白'
let age=20
module.exports={
name:name,
age:age
}
const a_module=require('./a')
console.log(a_module);
输出结果如下
{ name: '李白', age: 20 }
上面的
module.exports={
name:name,
age:age
}
可以简写成
module.exports={
name,
age
}
也就是说,如果属性名称与值的名称一致,可以省略值
Node使用CommonJS规范 ,它有四个重要的环境变量:module、exports、require、global。实际使用时,module变量代表当前模块,exports是module的属性,表示对外输出的接口,加载某个模块,实际上是加载该模块的module.exports属性。用require加载模块(同步)。
Node为每隔模块提供了一个exports变量,指向module.exports,这等同于每个模块头部有这样的一行代码:
var exports = module.exports
exports只是module.exports的一个引用,指向module.exports对象所在的地址
在ES6模块化中,使用 import 引入模块,通过 export导出模块,但需要babel编译为浏览器可以识别的代码。
1.export与export default均可用于导出常量/函数/文件/模块等;
2.在一个文件或模块中,export/import可以有多个,export default只有一个;
3.通过export方式导出,在导入时需要加{},export default不需要;
4.export能导出变量/表达式,export default不可以。
CommonJS模块输出是一个值的拷贝,ES6模块输出是值的引用。
CommonJS模块是运行时加载,ES6模块是编译时输出接口。
CommonJS模块无论require多少次,都只会在第一次加载时运行一次,然后保存到缓存中,下次在require,只会去从缓存取。
module.exports与exports ,是CommonJS的规范,被使用于Node.js中。
export与export default ,是ES6规范,被使用于React或Vue中。
Polyfill : 解决浏览器对API的兼容问题的。
Babel : Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码。
// CommonJS 模块
// 引入 http 模块
const http = require("http");
// ES6 模块
// 引入 http 模块
import http from 'http'
// CommonJS 模块
//引入 blog.js 模块
const blog_module = require("./src/router/blog");
// ES6 模块
//引入 blog.js 模块
import { handlerBlog } from './src/router/blogs.js';
在此注意,引入自定义模块时,CommonJS 模块可以自定义方法名,而 ES6 模块引入时,需要使用{}语法,变量名 只能是暴漏出来那个的方法名,并且引入时不光要写文件名,还必须把文件后缀名写上,引入模块不能不能和原生的模块一起引入,会发生冲突
// CommonJS 模块
// 暴漏 handlerBlog 方法
module.exports={
handlerBlog
}
// ES6 模块
// 暴漏 handlerBlog 方法
export{
handlerBlog
}
ES6 每个值都要用return 去返回,CommonJS 可以只返回一次
const handlerBlog=(req)=>{
// 使用 URL 模块对 req.url 进行封装
let myUrl = new URL(req.url, "http://127.0.0.1:3000/");
let method = req.method;
let pathname = myUrl.pathname;
// console.log(pathname);
let msgResult = null;
if (pathname == "/api/blog/list" && method == "GET") {
msgResult = { msg: "博客列表" };
} else if (pathname == "/api/blog/detail" && method == "GET") {
msgResult = { msg: "博客详情" };
} else if (pathname == "/api/blog/new" && method == "POST") {
msgResult = { msg: "新增博客" };
} else if (pathname == "/api/blog/update" && method == "POST") {
msgResult = { msg: "更新博客" };
} else if (pathname == "/api/blog/del" && method == "POST") {
msgResult = { msg: "删除博客" };
}
return msgResult;
}
// 暴漏 handlerBlog 方法
module.exports={
handlerBlog
}
const handlerBlog = (req)=>{
// 使用 URL 模块对 req.url 进行封装
let myUrl = new URL(req.url,"http://127.0.0.1:3000/");
let method = req.method;
let pathname = myUrl.pathname;
// console.log(pathname);
let msgResult = null;
if(pathname == "/api/blog/list" && method == "GET") {
return msgResult = {msg : "博客列表"}
}else if(pathname == "/api/blog/detail" && method == "GET"){
return msgResult = {msg : "博客详情"}
}else if(pathname == "/api/blog/new" && method == "POST"){
return msgResult = {msg : "新增博客"}
}else if(pathname == "/api/blog/update" && method == "POST"){
return msgResult = {msg : "更新博客"}
}else if(pathname == "/api/blog/del" && method == "POST"){
return msgResult = {msg : "删除博客"}
}else{
return msgResult = {msg : "sorry,地址错误"};
}
}
// 暴漏 handlerBlog 方法
export{
handlerBlog
}
在使用ES6模块的时候,在项目的package.json文件中,指定type字段为module
一旦设置了以后,该目录里面的 JS 脚本,就被解释用 ES6 模块。
如果没有type字段,或者type字段为commonjs,则.js脚本会被解释成 CommonJS 模块。
http://naotu.baidu.com/file/f03f6830a9a0de7bafa2a987cc065e46?token=35d035cc963f2d82
Node运行环境提供的API. 因为这些API都是以模块化的方式进行开发的, 所以我们又称Node运行环境提 供的API为系统模块
在前面,我们学了很多JS的API,如 querySelector、getElementById、offsetLeft 等,这些都是浏览器 提供的跟Dom或者Bom相关的功能,只不过这些API都是没有任何关系的分散的。
Node 中,也提供了很多的API,但是将这些API根据烈性存放在不同的模块中,如文件模块中就包含了 很多能够操作磁盘文件的API
所以,我们可以总结如下:
Node.js中文手册
var fs=require('fs')
// 同步读取
var res = fs.readFileSync('./a.txt','utf8')
console.log(res)
使用回调函数
const fs = require('fs')
fs.readFile('a.txt','utf8',(err,data)=>{
console.log(err)
console.log(data)
})
所以一般在处理读取的文件之前,先判断err 的值
const fs = require('fs')
fs.readFile('m1.js', 'utf8', (err, data) => {
if (err) throw err;
console.log(data)
})
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this
,arguments
,super
或new.target
。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
箭头函数可以把function函数给省略掉,然后再参数和主体之间加一个 胖箭头=>
就行了
// 箭头函数是对匿名函数的应用
var f1 = (a,b)=>{
console.log(a+b)
}
f1(5,6)
//如果只有一个参数,小括号也可以省略掉
var f2=a=>{
console.log(a);
}
f2(10)
//如果函数体只有一行代码,可以把花括号去掉
var f3=a=>console.log(a);
f3(20)
语法:
fs.writeFile(file, data[, options], callback)
var fs=require('fs')
//同步的
// 写入文件
fs.writeFileSync('a.txt','今天是美好的一天','utf8')
var fs=require('fs')
//异步的
// 写入文件
fs.writeFile('a.txt','每一天都是美好的一天','utf8',err=>{
console.log('文件保存成功');
})
默认情况下,此 API 会替换文件的内容(如果文件已经存在)。
可以通过指定标志来修改默认的行为:
fs.writeFile('a.txt','今天是美好的一天', { flag: 'a+' }, err => {})
可能会使用的标志有:
r+
打开文件用于读写。w+
打开文件用于读写,将流定位到文件的开头。如果文件不存在则创建文件。a
打开文件用于写入,将流定位到文件的末尾。如果文件不存在则创建文件。a+
打开文件用于读写,将流定位到文件的末尾。如果文件不存在则创建文件。(可以在 http://nodejs.cn/api/fs.html#fs_file_system_flags 中查看更多标志)
将内容追加到文件末尾的便捷方法是 fs.appendFile()
(及其对应的 fs.appendFileSync()
):
var fs=require('fs')
fs.appendFileSync('a.txt','今天是美好的一天','utf8')
所有这些方法都是在将全部内容写入文件之后才会将控制权返回给程序(在异步的版本中,这意味着执行回调)。
在这种情况下,更好的选择是使用流写入文件的内容。
相对于使用其他的数据处理方法,流基本上提供了两个主要优点:
使用 fs.access()
检查文件夹是否存在以及 Node.js 是否具有访问权限。
使用 fs.mkdir()
或 fs.mkdirSync()
可以创建新的文件夹。
使用 fs.readdir()
或 fs.readdirSync()
可以读取目录的内容。
使用 fs.rename()
或 fs.renameSync()
可以重命名文件夹。 第一个参数是当前的路径,第二个参数是新的路径
使用 fs.rmdir()
或 fs.rmdirSync()
可以删除文件夹。
删除包含内容的文件夹可能会更复杂。
在这种情况下,最好安装 fs-extra
模块,该模块非常受欢迎且维护良好。 它是 fs
模块的直接替代品,在其之上提供了更多的功能。
使用以下命令安装
npm install fs-extra
先引入 fs 模板
const fs = require('fs')
这样就可以访问其所有的方法
fs.access()
: 检查文件是否存在,以及 Node.js 是否有权限访问。fs.appendFile()
: 追加数据到文件。如果文件不存在,则创建文件。fs.chmod()
: 更改文件(通过传入的文件名指定)的权限。相关方法:fs.lchmod()
、fs.fchmod()
。fs.chown()
: 更改文件(通过传入的文件名指定)的所有者和群组。相关方法:fs.fchown()
、fs.lchown()
。fs.close()
: 关闭文件描述符。fs.copyFile()
: 拷贝文件。fs.createReadStream()
: 创建可读的文件流。fs.createWriteStream()
: 创建可写的文件流。fs.link()
: 新建指向文件的硬链接。fs.mkdir()
: 新建文件夹。fs.mkdtemp()
: 创建临时目录。fs.open()
: 设置文件模式。fs.readdir()
: 读取目录的内容。fs.readFile()
: 读取文件的内容。相关方法:fs.read()
。fs.readlink()
: 读取符号链接的值。fs.realpath()
: 将相对的文件路径指针(.
、..
)解析为完整的路径。fs.rename()
: 重命名文件或文件夹。fs.rmdir()
: 删除文件夹。fs.stat()
: 返回文件(通过传入的文件名指定)的状态。相关方法:fs.fstat()
、fs.lstat()
。fs.symlink()
: 新建文件的符号链接。fs.truncate()
: 将传递的文件名标识的文件截断为指定的长度。相关方法:fs.ftruncate()
。fs.unlink()
: 删除文件或符号链接。fs.unwatchFile()
: 停止监视文件上的更改。fs.utimes()
: 更改文件(通过传入的文件名指定)的时间戳。相关方法:fs.futimes()
。fs.watchFile()
: 开始监视文件上的更改。相关方法:fs.watch()
。fs.writeFile()
: 将数据写入文件。相关方法:fs.write()
。关于 fs
模块的特殊之处是,所有的方法默认情况下都是异步的,但是通过在前面加上 Sync
也可以同步地工作。
例如:
fs.rename()
fs.renameSync()
fs.write()
fs.writeSync()
试验一下 fs.rename()
方法。 异步的 API 会与回调一起使用:
const fs = require('fs')
fs.rename('before.json', 'after.json', err => {
if (err) {
return console.error(err)
}
//完成
})
同步的 API 则可以这样使用,并使用 try/catch 块来处理错误:
const fs = require('fs')
try {
fs.renameSync('before.json', 'after.json')
//完成
} catch (err) {
console.error(err)
}
此处的主要区别在于,在第二个示例中,脚本的执行会阻塞,直到文件操作成功。
https://www.npmjs.com/
node 官方不可能将项目开发中用到的所有功能都封装成模块,在我们安装 node 的时候提供给我们,事实上,用的最多的是其他开发者开发的一些模块,这些模块叫做第三方模块
别人写好的、具有特定功能的、我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又名包。
第三方模块有两种存在形式:
开发者将开发好的第三方模块,上传到上面网站,其它开发者可以从上面下载
下载方式为命令行方式下载
下面是下载和卸载第三方模块的基本语法
下载:
npm install 模块名称
卸载:
npm unintall package 模块名称
根据模块的作用,分为全局安装和本地安装
例如安装 jquery
npm install jquery
安装完成后,会在当前目录下创建 node_modules 目录
卸载:
npm uninstall jquery
以 nodemon 模块为例
nodemon是一个命令行工具,用以辅助项目开发。
在Node.js中,每次修改文件都要在命令行工具中重新执行该文件,非常繁琐。
npm install nodemon -g
卸载:
npm uninstall nodemon -g
因为 npmjs.com 的服务器在国外,所有有时候下载速度很慢,或者总是断开
解决方案就是更换下载源,最好是国内的下载源
解决方案有两个:
通过安装 nrm 的方式,可以选择和切换下载源
使用步骤:
对于我们国内,建议使用淘宝来下载
在镜像源中,cnpm 和 taobao 其实是一样的,所以选择 taobao 还是 cnpm 都可以
除了将下载地址切换为 cnpm 外,还可以直接安装 cnpm
使用 npm 安装 cnpm,同时将下载源更换为taobao
npm install -g cnpm --registry=https://registry.npm.taobao.org
安装成功后,使用 cnpm 命令安装第三方模块,如
cnpm install mysql
说明:cnpm 只是基于npm 的一个小公举
总结:
或者这两种方式都不用,而是使用安装包的时候指定下载源
npm install mysql --registry=https://registry.npm.taobao.org
上面学习的 npm 是基于node.js 的一个包管理工具,除此之外,还有yarn,现在也非常流行
yarn 是现在非常流行的一个基于node.js的包管理工具,与 npm 可以说是双雄争霸
注意:yarn 与 cnpm 是不同的
yarn安装
除了下载安装包外,还可以从npm 中安装yarn
下面使用 npm 包安装 yarn(虽然yarn 是与npm 竞争关系,但是npm 还是和开放的允许安装 yarn)
npm install yarn -g
执行下面命令,查询yarn命令列表
yarh -h
查询 yarn 版本
yarn -v
新建一个项目,然后打开命令行工具,执行如下命令
yarn add jquery
删除模块
yarn remove jquery
每个项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息。
我们发现,当使用 npm 安装模块时,会创建 node_modules 目录,此目录中存储下载的模块及其依赖的模块
这个目录中的文件存在两个问题
在个项目拷贝给他人时,删除 node_modules,他人再使用 nmp 命令进行恢复安装
这就需要一个文件能够记录,当前项目都使用了哪些模块,这个文件就是 package.json
创建package.json
默认情况下,是没有此文件的,可以使用命令生成此文件
新建项目,然后在此项目下打开命令行工具,运行如下命令
npm init -y
package.json 文件中的内容如下
{
"name": "blog",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
安装mysql文件
npm install mysql
我们会发现 package.json 文件会多出东西
删除node_modules
将项目拷贝给别人时,直接删除 node_modules 目录即可
恢复安装
运行如下命令,即可根据package.json 中的记录恢复安装
npm install
总结:
使用如下命令安装开发依赖包:mysql
npm install mysql
删除 node_modules 目录
使用如下命令恢复项目依赖安装
npm install --production
查看 node_modules 中的文件变化
再次删除 node_modules,然后使用如下命令恢复开发依赖安装
npm install
发现node_modules 中多了很多文件
此文件在第一次使用npm下载模块时就会被创建
作用如下:
关于 package-lock.json 的一个关键细节,那就是它不能被发布。如果你在项目根目录以为的地方找到这个文件,它都会被忽略。
当某人尝试通过 npm install 初始化项目时,下载的依赖包可能和项目初期是不同的,尤其是 package.json 中的版本没有固定,可以更新时,虽然补丁版本或次版本不应该引起重大改变,但还是有概率引入 bug。
package-lock.json 会固化当前安装的每个依赖包的版本,每当 npm install 时,npm 会使用这些确切的版本。
模块加载分为两种情况,一种是加后缀名,一种是不加后缀名
const blog_module = require("./src/router/blog");
const blog_module = require("./src/router/blog.js");
当模块引入没有添加路径,自动默认成是系统模块
const http = require("http");
在对数据库进行操作时,先使用终端安装驱动
npm install mysql
var mysql = require('mysql');
使用以下代码根据你的实际配置修改数据库,用户名,密码及数据库名
test.js 文件代码:
var mysql = require('mysql');
// 连接数据库的配置
var connection = mysql.createConnection({
// 主机名称,一般是本机
host : 'localhost',
// 数据库的端口号,如果不设置,默认是3306
port: 3306,
// 创建数据库时设置用户名
user: 'root',
// 创建数据库时设置的密码
password: 'root',
// 查询的数据库
database : 'test'
});
// 与数据库建立连接
connection.connect();
// 查询数据库
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
执行以下命令:
node test.js
输出结果为:
The solution is: 2
再次要注意两点:
参数 | 描述 |
---|---|
host | 主机地址 (默认:localhost) |
user | 用户名 |
password | 密码 |
port | 端口号 (默认:3306) |
database | 数据库名 |
charset | 连接字符集(默认:‘UTF8_GENERAL_CI’,注意字符集的字母都要大写) |
localAddress | 此IP用于TCP连接(可选) |
socketPath | 连接到unix域路径,当使用 host 和 port 时会被忽略 |
timezone | 时区(默认:‘local’) |
connectTimeout | 连接超时(默认:不限制;单位:毫秒) |
stringifyObjects | 是否序列化对象 |
typeCast | 是否将列值转化为本地JavaScript类型值 (默认:true) |
queryFormat | 自定义query语句格式化方法 |
supportBigNumbers | 数据库支持bigint或decimal类型列时,需要设此option为true (默认:false) |
bigNumberStrings | supportBigNumbers和bigNumberStrings启用 强制bigint或decimal列以JavaScript字符串类型返回(默认:false) |
dateStrings | 强制timestamp,datetime,data类型以字符串类型返回,而不是JavaScript Date类型(默认:false) |
debug | 开启调试(默认:false) |
multipleStatements | 是否许一个query中有多个MySQL语句 (默认:false) |
flags | 用于修改连接标志 |
ssl | 使用ssl参数(与crypto.createCredenitals参数格式一至)或一个包含ssl配置文件名称的字符串,目前只捆绑Amazon RDS的配置文件 |
更多说明可参见:https://github.com/mysqljs/mysql
在进行数据库操作前,你需要在Navicat 中创建好你所需要进行操作的数据库文件,然后进行操作
配置好环境并且连接好你所需要操作的数据库
var mysql = require('mysql');
// 连接数据库的配置
var connection = mysql.createConnection({
// 主机名称,一般是本机
host : 'localhost',
// 数据库的端口号,如果不设置,默认是3306
port: 3306,
// 创建数据库时设置用户名
user: 'root',
// 创建数据库时设置的密码
password: 'root',
// 查询的数据库
database : 'test'
});
// 与数据库建立连接
connection.connect();
基于以上操作完成后,我们进行对数据库的操作
//查询数据
var sql = 'SELECT * FROM nemu';
//查
/**
* query 方法是一个异步方法
* sql:要执行的sql语句
* 回调函数的两个参数
* err:如果执行 sql 语句过程中发生错误,会将错误信息赋值给 err
* result:如果执行 sql 语句成功,会将结果赋值给result
*/
connection.query(sql,function (err, result) {
if(err){
console.log('[SELECT ERROR] - ',err.message);
return;
}
console.log('--------------------------SELECT----------------------------');
console.log(result);
console.log('------------------------------------------------------------\n\n');
});
//增加数据
var addSql = 'INSERT INTO nemu(id,name,age) VALUES(NULL,?,?)';
var addSqlParams = ['独一', 10];
//增
/**
* query 方法是一个异步方法
* sql:要执行的sql语句
* 回调函数的两个参数
* err:如果执行 sql 语句过程中发生错误,会将错误信息赋值给 err
* result:如果执行 sql 语句成功,会将结果赋值给result
*/
connection.query(addSql,addSqlParams,function (err, result) {
if(err){
console.log('[INSERT ERROR] - ',err.message);
return;
}
//console.log('INSERT ID:',result.insertId);
console.log('INSERT ID:',result);
});
//修改数据
var modSql = 'UPDATE nemu SET name = ?,age = ? WHERE id = ?';
var modSqlParams = ['无二', '10',6];
//改
connection.query(modSql,modSqlParams,function (err, result) {
if(err){
console.log('[UPDATE ERROR] - ',err.message);
return;
}
console.log('--------------------------UPDATE----------------------------');
console.log('UPDATE affectedRows',result.affectedRows);
console.log('-----------------------------------------------------------------\n\n');
});
//删除数据
var delSql = 'DELETE FROM nemu where id=6';
//删
connection.query(delSql,function (err, result) {
if(err){
console.log('[DELETE ERROR] - ',err.message);
return;
}
console.log('--------------------------DELETE----------------------------');
console.log('DELETE affectedRows',result.affectedRows);
console.log('-----------------------------------------------------------------\n\n');
});
// 关闭连接
connection.end();