一、nodejs运行
nodejs是执行js代码的环境,执行方式有两种:
(1)在nodejs中直接执行代码(类似于在浏览器控制台执行写js代码并执行)
(2)使用nodejs执行js文件:新建js文件,书写规范的js代码,通过命令行的node命令执行这个文件。
执行的文件有两种方式:
当前命令行不在文件所在文件夹下,此时需要将文件的绝对路径 - 不常用
当前命令行在文件所在的文件夹下,此时使用文件的相对路径即可 - 常用
二、简单的命令
打开命令行窗口的方式:
win+r
地址栏输入cmd
shift+鼠标右击
vscode中ctrl+反引号
开始菜单中输入cmd,点击命令提示符或打开。最万能是选择以管理员身份运行
盘符: # 进入某个盘符
cd 目录 # 进入某个目录 - cd /
cd .. # 回到上一级目录 - 一样
dir # 查看当前文件夹中的文件和文件夹 - ls
tree # 查看当前文件夹中的所有文件和文件夹包括子文件夹及其文件,树状结构
cls # 清屏 - clear
ipconfig # 查看当前电脑的网管信息 - ifconfig
systeminfo # 查看当前电脑的配置信息
md 文件夹名 # 新建文件夹 - mkdir make directory
rd 文件夹名 # 删除文件夹 - rm -rf 文件夹 remove directory
type nul> 文件名 # 新建文件 - touch 文件名
echo 内容 > 文件名 # 给文件中写入内容
ren 文件名 新的文件名 # 将文件重命名
del 文件名 # 删除一个文件 - rm -rf 文件名
三、模块化开发
前端的模块化开发规范共有以下几种:
IIFE(Immediately Invoked Function Expression)立即调用函数表达式
通过自调用函数模拟模块化,解决了全局变量污染问题。
例如:c文件依赖a、b文件
//a.js文件
(function(){
var name="张三"
window.moduleA={
name
}
})()
//b.js文件
(function(){
var name="李四"
window.moduleB={
name
}
})()
//c.js文件
(function(moduleA,moduleB){
var name="王五"
console.log(moduleA,moduleB)
console.log(name)
})(moduleA,moduleB)
//最后在创建的html文档中需要导入这三个文件:
<script src="./a.js"></script>
<script src="./b.js"></script>
<script src="./c.js"></script>
AMD(Asynchronous Module Definition)异步模块定义
由于这个规范不是原生js支持的,所以要先引入第三方库文件(RequireJS)才能实现。解决了多个js文件之间的依赖关系问题。也遗留了一个问题:js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间。
例:c文件依赖b文件,b文件依赖a文件
//a.js文件
define(function () {
var a = 1
return { a }
});
define函数用来定义模块,被别的模块导入。
其中define的参数1表示当前模块的名称,别的模块导入当前模块的时候使用这个名称代表当前模块
//b.js文件
define(['./a.js'], function (moduleA) {
var b = "李四"
return { b, moduleA }
})
define函数在定义模块的同时也可以依赖别的模块
//c.js文件
require(['./b.js'],function(moduleB){
console.log(moduleB)
})
require函数作为最终的处理函数,参数1是依赖的模块,参数2是对所有逻辑的处理。
//最后在html中运行,首先引入require.js,然后引入c.js即可
<script src="./require.js"></script>
<script src="./c.js"></script>
CMD(Common Module Definition)通用模块定义
同样不是原生js支持的,所以需要先引入第三方库文件(SeaJS)才能实现。他解决的问题跟AMD是一样的,但他的文件加载时机跟AMD是不一样的,AMD是所有依赖的文件提前加载,CMD是什么需要什么时候加载。
//a.js文件
define(function( exports, module){
var a = 1
// exports.a = a 等同于以下
module.exports={
a
}
})
回调函数中的require是一个函数,用来引入别的模块,exports和module用来导出,其中exports就是module.exports。
//b.js文件
define(function (require, exports, module) {
let moduleA = require('./a.js')
var b =2
module.exports = {
moduleA,
b
}
})
require导入别的模块时,使用模块名称导入
//c.js文件
seajs.use('./b.js',function(module){
console.log(module)
})
seajs.use方法表示要使用哪个模块,module是给使用的模块起的别名。
//最后在html中先导入sea.js,然后按照依赖顺序导入其他文件
<script src="./sea.js"></script>
<script src="./c.js"></script>
ES6的模块化规范
原生js支持,导出用export关键字,导入用import关键字。但必须在服务器环境中才能用,且html使用必须添加:type="module"属性。
//导出语法:
1. export 数据的定义
2. export default 数据
//导入语法:
1.import {解构} from '文件'
2.import * as 对象 from '文件'
3.import 对象 form '文件'
4.import 对象, {解构} from '文件'
CommonJS规范
使用commonjs规范导入导出模块:
//导入
require(被导入的模块)
//导出
module.exports = {数据}
module.exports.键 = 值
exports.键 = 值
//a.js文件
let a = 10
// 数据a就被导出了 - 这种导出方式只能导出一个数据
// module.exports = a
// 对象被导出了 - 通常要导出多个数据就使用这种导出方式
// module.exports = {a}
// 导出了一个对象 - 这种导出方式可以在多个地方导出数据
// module.exports.a = a
//为了让导出变的更简单,commonjs规范中,在每个模块中定义了一个变量exports,并将module.exports赋值给了exports,导出时可以使用exports:
// exports.a = a
exports = {a}
注意:使用exports导出的时候,千万不能直接给exports赋值,因为导出功能是由module.exports提供的,如果直接给exports赋值,就将exports的内存空间换成了另外一个数据空间了,将失去导出功能。
//b.js文件
let data = require('./a.js')
//导入的就是导出的数据,导出数据就接收到数据,导出对象就接收到对象。
注意:导入的文件是自定义的,那路径中的./是不能被省略的。导入文件的后缀可以省略,因为nodejs中能被导入的只能是js文件。
在nodejs中能被导入的模块分3种:
(1)自定义模块 - 文件路径中的./不能省略
(2)内置模块 - 只需要导入模块名称,不需要路径,因为默认会在系统中找这个文件
(3)第三方模块 - 别人写好的js文件,我们需要导入使用,所以必须提前下载好才能被导入使
四、内置模块
fs
fs(file system)模块提供了用于与文件进行交互相关方法。
const fs = require('fs')
// 写入数据(覆盖)
fs.writeFile(文件路径,待写入的数据,err => {}) // 异步写入文件
fs.writeFileSync(文件路径,待写入的数据) // 同步写入文件
// 读取文件中数据
fs.readFile(文件路径, 'utf-8’,(err,data) => {}) // 异步读取文件
fs.readFileSync(文件路径, 'utf-8’) // 同步读取文件
// 第二个参数是可选项,如果不加的话,默认读取出来的buffer(用16进制来描述2进制数据流的格式)数据,需要通过buffer.toString()才能转成字符串
// 判断文件是否存在
let ret = fs.existsSync(path)
// 获取文件信息(异步)
fs.stat(文件,(err,stats) => {
stats.isDirectory() // 是否是目录
stats.isFile() // 是否为文件
stats.size // 文件大小(以字节为单位)
})
// 给文件中追加内容
fs.appendFile(文件路径,待写入的数据,err => {}) // 异步追加
fs.appendFileSync(文件路径,待写入的数据) // 同步追加
// 删除文件(异步)
fs.unlink(文件路径,err => {})
// 文件重命名
fs.renameSync(旧的文件路径, 新的文件路径)
os
os(operation system)模块提供了与操作系统相关的实用方法和属性。
const os = require('os')
// 换行符
os.EOL //根据操作系统生成对应的换行符 window \r\n,linux下面 \n
// cpu相关信息
os.cpus()
// 总内存大小 (单位 字节)
os.totalmem()
// 空余内存大小 (单位 字节)
os.freemem()
path
path模块用于处理文件和目录(文件夹)的路径。
const path = require('path')
// 获取路径最后一部内容,一般用它来获取文件名称
path.basename('c:/a/b/c/d.html') // d.html
// 获取目录名,路径最后分隔符部分被忽略
path.dirname('c:/a/b/c/d.html') // c:/a/b/c
// 获取路径中文件扩展名(后缀)
path.extname('c:/a/b/c/d.html') // .html
// 给定的路径连接在一起
path.join('/a', 'b', 'c') // /a/b/c
url
URL字符串是结构化的字符串,包含多个含义不同的组成部分。 解析字符串后返回的 URL 对象,每个属性对应字符串的各个组成部分。
const url = require('url')
//完整的urL网址 = 协议://用户名: 密码@主机名(ip地址或域名):端口号(第几号文件夹)/路径/文件名称? 数据(键 值&键值)# 铺点
let href = "http://xiaoming:123456@localhost:80/project/src/userinfo.html?id=5&cat=8#top";
// 解析网址,返回Url对象
// 参2 如果为true 则 query获取得到的为对象形式
url.parse(href,true)
//以一种 Web 浏览器解析超链接的方式把一个目标 URL 解析成相对于一个基础 URL。
console.log(url.resolve('https://lynnn.cn/foo','/bar'))
//https://lynnn.cn/bar
console.log(url.resolve('https://lynnn.cn/foo/','/bar'))
//https://lynnn.cn/bar
console.log(url.resolve('https://lynnn.cn/foo/bar','./one'))
//https://lynnn.cn/foo/one
console.log(url.resolve('https://lynnn.cn/foo/bar','../bar'))
//https://lynnn.cn/bar
console.log(url.resolve('https://lynnn.cn/foo/bar/one/two','.../three'))
//https://lynnn.cn/foo/bar/one/.../three'
querystring
用于解析和格式化 URL 查询字符串(URL地址的get形式传参)的实用工具。
const querystring = require('querystring')
// query字符串转为对象
querystring.parse('foo=bar&abc=xyz')
querystring.decode('foo=bar&abc=xyz')
// 对象转为query字符串
querystring.stringify({ foo: 'bar',abc: 'xyz'})
querystring.encode({ foo: 'bar',abc: 'xyz'})
http
http介绍
nodejs可以通过代码创建web服务器,让js可以是前端语言,也可以是后端语言。
http模块就是nodejs封装在内部专门用于创建服务器的。
创建服务器
// 导入http模块
const http = require('http')
// 创建web服务对象实例,并处理请求
const server = http.createServer(function(request, response) {
//request:请求
//response:响应
response.end('this is my server!')
})
server.listen(8080, () => { // 这里的第二个参数回调函数可以省略
console.log('服务已启动')
})
//简写
require('http').createServer((req, res) => {
// 处理响应
}).listen(端口号,()=>{console.log('server is running at http://localhost:端口号')})
通常在访问服务器的时候,默认会有一个网站图标的请求,要求服务器提供网站图标。
请求对象:通过请求对象req,可以获取请求的相关信息,例如:请求的客户端ip、请求方式、请求路径
require('http').createServer((req, res) => {
// 获取客户端请求ip
req.connection.remoteAddress
// 获取请求路径
req.url // 不包含协议、域名、端口号的路径
}).listen(端口号,()=>{console.log('server is running at http://localhost:端口号')})
响应对象:响应对象可以给客户端响应内容,结束响应、响应状态码、状态描述、响应头等信息
require('http').createServer((req, res) => {
// 设置响应内容
res.write()
// 结束响应
res.end(字符串内容/buffer)
}).listen(端口号,()=>{console.log('server is running at http://localhost:端口号')})
//注意:每次响应一定要结束响应,否则客户端的请求会一直转,请求不到内容。响应结束后就不允许再响应内容了。
静态资源服务器
假设我们已经写好了一套静态页面,但是需要让别人访问,就需要提供一个服务器,且别人来访问的时候还要能访问到对应的静态页面。这种服务器被称之为静态资源服务器,目的是只为了提供访问静态资源。
const path = require('path')
let fs = require('fs')
require('http').createServer((req, res) => {
// 处理响应
// 通过请求路径获取到对应的文件路径
let filePath = path.join(__dirname, 'public', path.basename(req.url))
let ret = fs.existsSync(filePath) // 判断文件路径是否存在
// 判断文件路径是否是一个文件
fs.stat(filePath,(err,stats) => {
if(stats.isFile()){
// 读取文件并响应
res.end(fs.readFileSync(filePath))
}else{
res.end('路径错误') // 结束响应,避免客户端一直转
}
})
}).listen(端口号,()=>{console.log('server is running at http://localhost:端口号')})