系统模块之文件操作(fs)
//文件读取操作
const fs = require('fs');
fs.readFile('文件路径/文件名称',[,'文件编码'],callback) //加中括号的参数为可选参数
//例子
fs.readFile('../css/base.css','utf-8',(err,doc) => {
//如果文件读取错误 参数err的值为错误对象 否则err的值为null
//doc 为文件内容
if(err == null) {
console.log(doc);
}
});
//文件写入操作
const fs = require('fs');
const content = '<h3>正在使用fs.writeFile写入文件内容</h3>'
fs.writeFile('目标写入文件的路径/文件名',content//写入的内容,(err) => { //写入的文件如果不存在则自动创建 如果该文件已存在并且有内容时 会覆盖原先的内容
if(err != null){
console.log(err);
return ;
}
console.log('文件写入成功');
});
//写入的数据必须是字符串 或buffer(二进制数据),对象等数据
//回调函数只有一个err参数
//目录遍历的方法
function readDir(dir) {
fs.readdir(dir,(err,content) => {
content.forEach((value,index) => {
let joinDir = `${dir}/${value}`
fs.stat(joinDir,(err,stats) => {
if (stats.isDirectory()) {
readDir(joinDir)
} else {
fs.readFile(joinDir,(err,content) => {
console.log(content.toString())
})
}
})
})
})
}
readDir('./')
系统模块之path 路径操作
//语法:path.join('路径','路径',.....);
//__dirname 可以获取当前文件的绝对路径
//例子
const path = require('path');
let filePath = path.join('itast','a','b','.css')
console.log(filePath);
Gulp中提供的方法
gulp.src(): 获取任务要处理的文件
gulp.dest(): 输出文件
gulp.task(): 建立gulp任务
gulp.watch():监控文件的变化
//例子
const gulp = require('gulp');
//创建任务
gulp.task('first',()=> {
//获取处理文件
gulp.src('./src/css/index.css')
//传输文件
.pipe(gulp.dest('./dist/css'));
})
//执行任务 在终端输入 gulp first(任务名)
Gulp插件
//gulp-htmlmin :html文件压缩
//gulp-csso: 压缩css
//gulp-babel: javascript语法转化
//gulp-less: less语法转化
//gulp-uglify: 压缩混淆javascript
//gulp-file-include: 公共文件包含
//browsersync: 浏览器实时同步
//https://www.npmjs.com/package/package 插件查询使用的官网
插件使用步骤
例子
1、下载 如 npm install gulp-htmlmin
2、引入 const htmlmin = require('gulp-htmlmin');
3、使用 gulp.task('htmlmin',()=> {
gulp.src('./src/*.html')//选取src文件下所有的html文件
.pipe(htmlmin({ collapseWhitespace: true})) // 压缩html
.pipe(gulp.dest('dist'))
})
模块查找规则
//require('./find.js')
如果模块拥有路径但没有后缀时 如 require('./find')
遵循以下规则:
1、如果拥有完整路径,直接引入模块
2、如果后缀省略,当前文件目录下的同名后缀为js文件夹
3、如果上一步未成功 ,则找当前文件目录下的同名文件夹下的index.js文件
4、如果index.js文件不存在,则找此文件下的package.js文件中的main选项中的入口文件
5、如果指定的入口文件不存在,就会报错
如果模块没有路径且没有后缀时 如 require('find')
1、Node.js会假设它是系统模块
2、先去node_modules的文件夹中
3、首先查找是否有同名且后缀为js的文件
4、再看是否有同名的文件夹
5、如果文件夹存在 ,则看看里面是否有index.js文件
6、否则,就查看该文件夹下的package.json中main选项足确定的入口文件
7、然后就报错
创建web服务器
//引用系统模块
const http = require('http');
//创建服务器
const app = http.createServer();
//当客户端发送请求的时候
app.on('request',(resquent,response) => {
//获取请求方式
console.log(resquent.method);
//响应
response.end('<h1>hi, user</h1>')
})
//监听3000端口
app.listen(3000);
console.log('服务器已启动,监听3000端口。。。。。')
请求报文
app.on('request',(resquest,response) => {
resquest.headers//获取请求报文
resquest.url //获取请求地址
resquest.method //获取请求方法
})
响应报文
app.on('request',(resquest,response) => {
response.writeHeader(StatusCode)//第一个参数设置返回的状态码 第二个参数是一个对象可设置响应头里面的信息 如 { 'content-type': 'text/html;charset=utf8'} 返回的时html文件
})
POST 请求参数
//参数被放置在请求体中进行传输
//获取POST的参数需要使用data事件和end事件
//导入系统模块将参数转换为对象格式
const querystring = require('querystring');
app.on('request',(request, response) => {
let postData = '';
//监听参数传输事件
request.on('data',(Data) = > postData += Data);
//监听参数传输完毕事件
resquest.on('end',() = > {
console.log(querystring.parse(postData);
})
})
路由:就是客户端请求什么,服务端就返回什么
//客户端发来请求的时候
app.on('request',(request,response) => {
//获取客户端的请求路径
let pathName = url.parse(resquest.url).pathname;
if (pathName == '/' || pathName == './index') {
response.end('欢迎来到首页');
} else if (pathName = './list'){
response.end('欢迎来到列表页');
} else {
response.end('抱歉您访问的页面出游了');
}
})
异步函数
1、普通函数加上async 关键字 就成了异步函数
2、异步函数的默认放回值是promise对象
3、在异步函数中内部使用return关键字进行结果返回, 结果会被包裹在promise对象中
4、利用throw抛出错误的信息 throw后面的代码不在执行
5、调用异步函数再链式调用then方法获取异步函数的执行结果
6、调用异步函数再链式调用catch方法获取异步函数的执行的错误信息
7、await只出现在异步函数中 后跟promise对象 暂停异步函数的执行
等待promise对象返回结果后再向下执行
async function fn () {
throw '出错';
return 123;
}
fn.then(function(data) {
console.log(data)
}).catch(function(err){
console.log(err);
})
*****************************
//异步函数的使用
const fs = require('fs');
//利用promisify 对fs.readFile方法进行包装 这样读取的返回结果就是promise对象
const promisify = require('util').promisify;
const readFile = promisify(fs.readFile);
async function run() {
let r1 = await readFile('./1.txt', 'utf-8');
let r2 = await readFile('./2.txt', 'utf-8');
let r3 = await readFile('./3.txt', 'utf-8');
console.log(r1);
console.log(r2);
console.log(r3);
}
run();
MongoDB数据库
基础命令:
1、dbs //查询当前数据库
2、show dbs //查看所有的数据库
3、use music //创建或切换数据库
4、db.dropDatabase() //删除数据库
5、db.createCollection('集合名') //创建集合
6、db.getCollectionNames() //得到当前数据库的所有集合的名字
插入数据
1、db.集合名.insert({name:'nj',age: 45}) //可同时插入多条
2、db.集合名.save({name:'nj',age: 45}) //可同时插入多条
修改数据
db.集合名.update({匹配条件},{更新的值},true,true)
//第二参数表示 true : 找不到匹配的就创建一个新的数据 false : 找不到就放弃
//第三个参数表示 : true : 修改多个匹配的集合的数据 false : 修改第一匹配的集合
删除数据
db.集合名.remove({匹配条件})
查询数据
db.集合名.find({},{_id:0}) //不显示_id 这一列 为1 则显示
1、//连接
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/playground(数据库的名称)')
.then(() => console.log('数据库连接成功'))
.catch((err) => console.log('数据库连接失败', err));
//不需要显式的创建数据库 如果我们使用的数据库不存在 MongoDB 会自动创建
2、//创建集合
(1)、设定集合的规则
const courseSchema = new mongoose.Schema({
name: String,
author:String,
email:String,
age:Number,
isPublished:Boolean,
hobbies: [String]
});
(2)、创建集合并应用规则
const Course = mongoose.model('Course',courseSchema); //返回是一个构造函数
3、//向集合中插入数据
const course = new Course({
name: 'Node.js course',
author: '黑马讲师',
email: 'dfjhh@qq.com'
age:20,
isPublished: true,
hobbies: ['足球','篮球','排球']
});
4、//将数据保存到数据库中
course.save();
//可以直接创建文档并插入到数据库中
Course.create({name:'javascript',author:'的机会就',email: 'dfjhh@qq.com', age:20,,isPublished:true, hobbies: ['足球','篮球','排球']}(err,result) => {
console.log(err);
console.log(result);
})
//create方法也可返回Promise对象
Course.create({name:'javascript',author:'的机会就',email: 'dfjhh@qq.com', age:20,,isPublished:true, hobbies: ['足球','篮球','排球']})
.then((result) => console.log(result))
.catch((err) => console.log(err));
//查询集合中的所有元素
Course.find().then(result => console.log(result));
find()函数参数为查询的条件
1、例如查询年龄的合适的元素
参数为 {age: {$gt:20,$lt:40}} 查询年龄大于20少于40的元素
2、匹配包含
参数为 {hobbies:{$in: ['足球']}} 查询hobbies包含足球的所有元素
3、查询想要字段 只会输出这些字段所对应的内容 字段前面加-表示不想查询 如(-_id)
Course.find().select('name email').then(result => console.log(result));
4、将元素按照年龄字段进行排序
Course.find().sort('age').then(result => console.log(result)); //升序
Course.find().sort('-age').then(result => console.log(result)); //降序
5、跳过前两个元素 只查询两个元素
Course.find().skip(2).limit(2).then(rsult => console.log(result))
//条件查询 查询_id 为60c5b56a3b71821a00da897f 的元素
Course.find({ '_id': '60c5b56a3b71821a00da897f' }).then(result => console.log(result));
//返回一个元素对象 默认集合的第一个元素
Course.findOne();
Course.findOne({name: '黑马讲师'}).then(result => console.log(result));
//删除元素
1、删除单个
Course.findOneAndDelete({}).then(result => console.log(result));//返回删除的文档 删除符合条件的第一个
2、删除多个
Course.deleteMany({}).then(result => console.log(result));
//更新文档
Course.updateOne({查询条件},{更改的值}).then(result => console(result));
//更新多个文档
Course.updateMany({查询条件},{更改的值}).then(result => console(result));
Mongoose验证
require: true //必传字段
minlength:3 //字符串最小长度
maxlength: 5//字符串最大长度
min: 2//数值最小为2
max:100//数值最大为100
enum:['html','css','javascript','node.js']
trim:true//去除字符串两边的空格
validate:自定义验证器
default:默认值
集合关联的代码实现
//作者集合
const User = mongoose.model('User',new mongoose.Schema({
name: { type: String}
}));
//文章集合
const Post = mongoose.model('Post',new mongoose.Schema({
title: {type: string},
//使用ID将文章集合和集合进行关联
author: {type: mongoose.Schema.Types.ObjectID, ref:'User}
}));
//查询
Post.find().populate('author').then(result => console.log(result));
Art-template 模板引擎 为了更加友好的拼接字符串
1、标准语法
{{数据}}
{{a?b:c}}
{{运算表达式}}
2、原始语法
<%= 数据 %>
<%= a?b:c %>
<%= 运算表达式%>
//原文输出 能够解析里面的html标签
1、标准语法
{{@数据}}
2、原始语法
<%- 数据 %>
//循环语法
{{each target}}:
{{$index}} {{$value}}
{{/each}}
<% for(var i=0; i<target.length; i++)
{%> <%= i %> <%= target[i] %> <%}
%>
//子模版语法
{{ include '子模版的路径'}}
<%include('子模版的路径')%>
//模板继承
{{extend '路径'}}
//模板配置
1、向模板中导入变量template.defaults.imports.变量名 = 变量值;
2、设置模板的根目录template.defaults.root = 模板目录;
3、设置模板后缀 template.defaults.extname = '.art';
express框架
const express = require('express');
//创建网站服务器
const app = express();
app.get('/', (resquest, response) => {
response.send('Hello Express');
//send方法会内部检测响应内容的类型
//send方法会自动设置状态码
//send方法自动设置内容的响应类型及编码
})
app.get('/list', (resquest, response) => {
response.send({ name: 'dnjasd', age: 20 })
})
//监听端口
app.listen(3000);
console.log('服务器已启动....');
//中间件
app.get('请求路径','处理函数') //接受并处理get请求
app.post('请求路径','处理函数') //接受并处理post请求
默认情况下 请求从上到下依次匹配中间件 一旦匹配成功终止匹配
可以调用next()方法将请求的控制权交给下一个中间件
app.get('/request', (resquest, response, next) => {
resquest.name = '张三';
next();
})
app.get('/request', (resquest, response) => {
response.send(resquest.name);
})
app.use中间件的用法
匹配所有的请求方式 可以直接传入请求处理函数
app.use((resqust,response,next) => {
console.log(request.url);
next();
})
//第一个参数也可以传入请求地址,不论是什么请求方式
app.use('/admin',(resqust,response,next) => {
console.log(request.url);
next();
})
//错误处理中间的处理及使用方法
app.use((err,resquest,response,next) => {
response.status(500).send(err.message);
})//只能捕获同步代码发生的错误
//当异步代码出错后 将错误信息以参数的形式调用next()方法传递给错误处理中间件
例子
app.get('/',(resquest,response,next) => {
fs.readFile('./55.txt',(err,data) => {
if(err) {
next(err);
}
});
});
//try.catch可以捕获异步函数以及其他同步代码再执行过程中发生的错误 但不能捕获其他类型的错误
app.get('/',async (resquest,response,next) => {
try {
await User.find({name: '张三'})
}catch(ex) {
next(ex);
}
})
//构建模块化路由
//home.js文件代码
const express = require('express');
const home = express.Router();
home.get('./index',(resquest,response) => {
response.send('欢迎来到首页页面');
})
module.exports = home;//导出
//admin.js代码
const express = require('express');
const admin = express.Router();
admin.get('./index',(resquest,response) => {
response.send('欢迎来到管理页面');
})
module.exports = admin;//导出
//app.js 代码
const home = require('./home.js');
const admin = require('./admin.js');
app.use('./home',home);
app.use('./admin',admin);
//获取GET请求的参数
//http://localhost:3000/index?name=zhangsan&age=20
app.get('./index',(resquest,response) => {
response.send(resquest.query); //){'name':'zhangsan','age':20}
})
//获取POST请求的参数 利用第三方包 body-parser
const bodyParser = require('body-parser');
//拦截所有的请求
//extened:false 方法内部使用querystring模块来处理请求参数的格式
//extened:true 方法内部使用第三方模块qs来处理请求参数的格式
app.use(bodyParser.urlencoded({extened:false}));
app.post('./add',(request,response) => {
console.log(resquest.body);
})
模板引擎 express-art-template
//使用
//渲染后缀为art的模板
app.engine('art',require('express-art-template'));
//模板的存放目录
app.set('views',path.join(__dirname,'views'));
//设置默认后缀
app.set('view engine','art');
app.get('/index',(request,response) => {
//渲染模板
response.render('index',{
渲染的内容
})
})
//app.locals对象下的变量在所有模板中都能获取到
Joi javascript对象规则描述语言和验证器
const Joi = require('joi');
const schema = {
username: Joi.string().alphanum().min(3).max(30).required().err(new Error('错误信息')),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
access_token:[Joi.string(),Joi.number()],
birthyear:Joi,number.integer().min(1990).max(2013),
email: Joi.string().email()
}
Joi.validate({username:'abc',birthyear: 1994},schema)
formmidable 解析表单
const formidable = require('formidable');
const form = new formidable.IncomingForm();
form.uploadDir = '/my/dir';
form.keepExtensions = false;
form.parse.(req,(err,fields,files) => {
//fields 存储普通的请求参数
//files 存储上传的文件
})
Config模块
使用步骤
1、npm install config
2、项目的根目录下新建config文件夹
3、在该文件夹下新建default.json、development.json、production.json.
4、require方法导入
5、使用内部提供的get方法获取配置信息
commonJS
const name = {
surname: 'zhang',
sayName(): {
console.log(this.surname)
}
}
const age = {
age: 56
}
//两种导出方法:
module.exports = {
name,
age
}
exports.name = name
exports.age = age
node内置模块
url:
const url = require('url')
1、url.parse(url,bool) //第二参数为true时,将url中的参数解析成对象 放在query属性中
const strUrl = 'http://www.lagou.com/a/b?name=zhangsan&pswd=123456'
const result = url.parse(strUrl)
2、url.format(params) //根据参数对象生成url
const params = {
protocol:'https:',
host:'www.lagou.com',
hash:'#position',
search:'?name=zhangsan%age=27',
pathname:'/a/b'
}
//根据参数对象生成路径
const rs = url.format(params);
console.log(rs)
3、url.resolve()
console.log(url.resolve('https://www.dkfm/mfn/fjkd','../'))
console.log(url.resolve('https://www.dkfm/mfn/fjkd','/a'))
queryString:
const queryString = require('querystring')
1、queryString.parse(str,separtor,eq) //将一个字符串转化为一个对象
str: 字符串
separator(可省):指用于分割str这个字符串的字符或字符串,默认值为"&";
eq(可省):指用于划分键和值的字符或字符串,默认值为"=";
2、queryString.stringify(obj,separator,eq) //stringify这个方法是将一个对象化成一个字符串,与querystring.parse相对。
obj指需要序列化的对象
separator(可省)用于连接键值对的字符或字符串,默认值为"&"
eq(可省)用于连接键和值的字符或字符串,默认值为"="
3、queryString.escape(str) //将传入的字符串进行编码
4、queryString.unescape()//unescape方法可将含有%的字符串进行解码