node20180927
1. fs读文件、写文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 1 fs读文件 var fs = require('fs') fs.readFile('./20180926 demo/a.text', function (err, data) { if (err) { console.log(err); } else { console.log(data.toString()); } }) // 写文件 fs.writeFile('./20180926 demo/b.text', 'this is node.js', function (err) { if (err) { console.log(err); } else { console.log('文件写入成功'); } })
2.最简 http
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
let http = require('http') let server = http.createServer() server.on('request', function (req, res) { console.log('请求路径', req.url); // res.write('123'); // write 发送数据 以 end 结尾 // res.end('455'); // 直接 end 就可以了 if (req.url === '/') { // 原生 http 只能这样判断不同的请求 res.end('index') // res.end(333) // end值 必须是二进制或者字符串 } else { res.end('404 no found') } }) server.listen('3333', function () { console.log('服务器创建成功,可通过http://localhost:3333来访问'); })
3. 核心模块 如 os 操作系统模块 不常用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
let os = require('os') // 操作系统模块 不常用 console.log(os.cpus()); console.log(os.totalmem());
4. exports require 简单应用
a.js
let foo = 'abcdefg' console.log('aaaa'); exports.foo2 = 'hello' // 导出给其他文件用,默认是一个空对象 exports.add = function (x, y) { return x + y }
test.js
console.log('引入a文件'); // require('./a.js') let res = require('./a') // 可以省略后缀名 ./ 不可省略 // 引进来是一个对象 console.log(res.foo2); console.log(res.add(10, 20)); // require('path') ./省略会识别为 核心模块,如path /* * node 没有全局作用域,只有模块作用域,即 当前文件test.js无法访问其他文件a.js的变量数据 * * */
5.content-type http读html 图片
// nodejs.org /* * ip 地址用来定位计算机 * 端口号用来定位具体的应用程序(所有需要联网的都需要端口号) * 所有联网的应用程序都会占用一个端口号 * 端口号范围 0 ~ 65536 * * */ let http= require('http') let fs= require('fs') let server = http.createServer() /* * 服务器默认发送 utf8编码 * 浏览器默认根据中文操作系统来识别 ,默认为 gbk * * Content-type: text/plains 普通文本 * text/html html * image/jpeg 图片 * tool.oschina.net 查所有的 content-type * */ server.on('request',function (req, res) { console.log('请求我的客户端的地址是:', req.socket.remoteAddress, req.socket.remotePort) // res.setHeader('Content-Type','text/html;charset=utf-8') // res.end('<a href="">中国</a>') // 读html的内容 fs.readFile('./index.html', function (err, data) { // 读图片 // fs.readFile('./resource/ab2.jpg', function (err, data) { if (err) { res.setHeader('Content-Type', 'text/plain; charset=utf-8') res.end('文件读取失败,请稍后重试!') } else { res.setHeader('Content-Type', 'text/html; charset=utf-8') // res.setHeader('Content-Type', 'image/jpeg') res.end(data) } }) // }) server.listen(3333,function () { console.log('server is running'); })
6.使用 readFile() 实现 类似apache的www目录访问
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var http = require('http') var fs = require('fs') var server = http.createServer() var wwwDir = 'D:/Movie/www' server.on('request', function (req, res) { var url = req.url // 访问路径 访问的资源 // / index.html // /a.txt wwwDir + /a.txt // /apple/login.html wwwDir + /apple/login.html // /img/ab1.jpg wwwDir + /img/ab1.jpg var filePath = '/index.html' if (url !== '/') { filePath = url } fs.readFile(wwwDir + filePath, function (err, data) { // 通过读文件 readFile 渲染对应资源 if (err) { return res.end('404 Not Found.') } res.end(data) }) }) // 3. 绑定端口号,启动服务 server.listen(3000, function () { console.log('running...') })
7.js代码风格 webstorm已支持 javascript standard style 分号问题, ( [ ` 以这三个开头的代码前面加 ; 其他代码不用加分号
;(function(){...})()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * js 代码风格 * https://standardjs.com/readme-zhcn.html * webstorm 2017版支持 javascript standard style * 设置 Editor | Code style | JavaScript and click Set from Predefined Style – Standard and the style will replace your current scheme. * 按格式化 ctrl+alt+l 会自动删除分号,把"" 换为 '' * 当代码以 ( [ ` 开头时,要在前面加;号 * */ // ( 开头 ;(function () { console.log('444') })() // [ 开头 ;['a','b'].forEach((val)=>{ console.log(val) }) // ` 开头 ;`abc`.toString() // `` 这里类似 <pre></pre> let foo = ` 12345 床前明月光 456 ` console.log(foo)
8.
/* * 客户端渲染不利于 seo * 服务端渲染可以被爬虫抓取到, * 京东商品列表是服务端渲染,seo优化,产品才能被搜到, * 商品评论列表是客户端渲染,不刷新,体验好 * * */
9.代码风格
代码块适当加空行,容易阅读 常量 MAX_MONEY = 10 var person = null; 定义变量为null for(xxx){ if(y===2){ continue; } process(y) } // continue 可换成if判断 for(xxx){ if(y!==2){ process(y) } } 【所有的var语句都提前到包含这段逻辑的函数的顶部执行】 function doSomething() { var result = 10 + value; var value = 10; return result; } 真正的执行顺序: function doSomething() { var result; var value; // var 先执行 result = 10 + value; value = 10; return result; } // 2 function doSomethingWithItems(items) { for (var i=0, len=items.length; i < len; i++) { doSomething(items[i]); } } 真正的执行顺序: function doSomethingWithItems(items) { var i, len; // var 先执行 for (i=0, len=items.length; i < len; i++) { doSomething(items[i]); } } 建议总是将局部变量的定义作为函数内第一条语句。 使用 instanceof // 检测日期 if (value instanceof Date) { console.log(value.getFullYear()); } // 检测正则表达式 if (value instanceof RegExp) { if (value.test(anotherValue)) { console.log("Matches"); } }
10 module.exports 和 exports
exports = module.exports // 最终使用 // 导出多个成员 exports.xxx = xxx exports.yyy = yyy // 导出多个成员也可以 module.exports = {} // 导出单个成员 module.exports= xxx // 也可以不管 exports
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 在 Node 中,每个模块内部都有一个自己的 module 对象 * 该 module 对象中,有一个成员叫:exports 也是一个对象 * * var module = { * exports:{ * ... * } * } * * return module.exports * * * 默认在代码的最后有一句: return module.exports * 所以,直接给 module.exports对象赋值后,require引起来可得到该数据 * module.exports.test='123' * node 模块中,有如下定义 * var exports = module.exports * 两者相等 exports 是 module.exports的一个引用 * exports.foo='bar' * 等价于 * module.exports.foo='bar' * * */ // 导出多个(必须在对象中) /*exports.foo2 = 'hello' // 导出给其他文件用,默认是一个空对象 exports.add = function (x, y) { return x + y }*/ /* * let obj = require('xx.js') * obj.foo2 * obj.add(3,4) * * * */ // 方式 二 module.exports = { add: function (x, y) { return x + 2*y }, str: 'abc' } /* * let obj = require('xx.js') * obj.add(3,4) * obj.str * * */ // 方式 三 // 只导出一个 /* * 如果 exports=function(x,y){return x+3*y} 则导出失败 * 已经把 exports重新赋值了,exports不等于 module.exports了 * */ module.exports=function(x,y){ return x+3*y } /* * let add = require('xx.js') * add(3,4) * * */ var obj = {} var obj1 = obj; obj1.foo='123' console.log(obj.foo) // 123 obj1={} // 重新赋值了,跟 obj 没关系 了 obj1.foo='test' console.log(obj.foo) // 123 // 最终使用 // 导出多个成员 exports.xxx = xxx exports.yyy = yyy // 导出多个成员也可以 module.exports = {} // 导出单个成员 module.exports= xxx // 也可以不管 exports
11 require() npm 细节
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * main.js * require('./a') * require('./b') // 优先从缓存中加载 代码只执行一次,但module.exports 会多次调用 * * * a.js * console.log('a') * require('./b') * * * b.js * console.log('b') * module.exports.test='abc' * * node main.js b.js 只加载一次,只输出一次console.log('b') 但b.js 中的 test会执行两次 * */ /* * npm i art-template * require('art-template') // 直接require 安装的包名 * 实际加载的是 node_modules/art-template/package.json 里面的 main 属性 * 如果没有 package.json 或者 main属性,则默认加载 index.js * 如果以上都没有,则会往上一级目录查找 * node_modules 一般放在项目根目录,供所有子目录文件加载使用 * */ // npm i -S 包名 // npm un -S 包名 删除 // npm i --global cnpm 安装淘宝的 cnpm 以后用 cnpm 代替 npm 方法一 // npm config set registry https://registry.npm.taobao.org 方法二 // npm config list // 查看淘宝镜像配置信息
12 express 静态资源拖管 app.use('/public', express.static('public'))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 公开访问public 目录 1 app.use('/public', express.static('public')) // app.use('/a',express.static('public')) // 可以搞个别名a指向public /a/logo.png // http://localhost:3333/public/logo.png 地址栏可访问public 目录下的所有数据 // 公开访问public 目录 2 // 不常用 // app.use(express.static('public')) // http://localhost:3333/logo.png 地址栏可访问public 目录下的所有数据
13. mongodb 基础
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
mongodb.com 下载数据库v3.6.7,安装 custom-> 安装在d 盘,取消勾选左侧的Install MongoDB Copmpass”选项,其他默认 可视化工具 robo 3T 文档 https://mongoosejs.com/ mongoose是mongoDB的一个对象模型工具,封装了mongoDB对文档的一些增删改查等常用方法,让nodejs操作mongoDB数据库变得更加容易。 关系型数据库 mySQL 非关系型数据库 MongoDB 不需要设计表结构 数据表- 集合(数组) 表记录- 文档对象
14. mongodb 纯数据库操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
环境变量 path: D:\MongoDB\bin; mongod --version mongod 数据默认存储目录 当前根目录/data/db 【需要手动创建文件夹,在c盘/d盘执行就是 c:/data /db d:/data/db】 启动数据库 mongod 省略环境变量的配置则要进入到对应目录再执行 mongod 连接数据库 mongo 退出 exit 查看数据库 show dbs 切换 use 查看 db 集合 show collections (对应mysql中的表) 插入 db.students.insertOne({"name":"Jack"}) 查找 db.students.find()
15.mongodb 基本概念
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
基本概念
mongodb数据库, qq集合(数据表),baidu集合(数据表),一个集合有多个文档(表记录) users文档,products文档
{
qq:{
users:[{},{}],
products:[{}]
},
baidu:{
}
}
16.mongodb 增删查改 有很多个函数可以用 save() deleteOne() find() updateOne
/* * 文档 https://mongoosejs.com/ * * * */ const mongoose = require('mongoose') mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true }) // 文档结构(表结构) let userSchema = new mongoose.Schema({ username: { type: String, required: true }, email: { type: String, }, gender:{ type:Number, enum:[0,1], // 枚举 default:0 } }) // 模型 最终集合名称为 users const User = mongoose.model('User', userSchema) // 增 /*let user = new User({ username:'jia', email:'jia@qq.com' }) user.save(function (err,res) { if(err){ console.log(err) } console.log(res) })*/ // 查 User.find(function (err, res) { if (err) { console.log(err + '11') } console.log(res) }) // 查条件 /*User.findOne({username:'kang'}, function (err, res) { if (err) { console.log(err) } console.log(res) })*/ // findOne 返回对象 find 返回数组对象 // 删除 remove 改成 deleteOne deleteMany /*User.deleteMany({_id:'5bbeab08393ed015589a044a'},function (err, res) { if(err){ console.log(err) } console.log('删除成功') console.log(res) })*/ // 有好多种删除 /*User.findByIdAndRemove('5bbdb56c29c8f01684091b28',function (err) { if(err){ console.log(err) } console.log('删除成功') })*/ // 更新 /*User.updateOne({username:'kang'},{email:'什么都可以@ee.com'},function (err, res) { if(err){ console.log(err) } console.log('更新成功') })*/
17. path.join 的使用
let path = require('path') console.log(path.join('c:a/b/', '/c')) // path.join 路径拼接,防出错 console.log(path.join('c:a/b/', 'c')) // 两者一致 console.log(__filename) // 文件路径 e:/node0823/test.js console.log(__dirname) // 目录 e:/node0823 /* * D:\businessCenter windows 目录是反斜杠 \ mac 是 斜杠 / * */ /* * 涉及到文件操作的,path.join(__dirname,'xx') 防路径出错 * */ let fs = require('fs') // let path2='./a.txt'; // 相对于执行node命令所处的终端路径 会出错,使用 let path2 = path.join(__dirname,'a.txt') fs.readFile(path2,'utf8',function (err, res) { if(err){ console.log(err) } console.log(res) })
18. express-session
/* * express-session * npm i express-session * 该插件会为 req 请求对象 添加一个成员: req.session 默认是个对象 * 默认session 数据 是内存存储的,服务器一旦重启就会丢失,生产环境会把 sessioin持久化存储 * 生产环境时,使用插件把 session保存到数据库中, * * */ var session = require('express-session') app.use(session({ secret: 'kang', // 配置加密字符串,它会在原有加密基础之上和这个字符串拼起来去加密,增加安全性 resave: false, saveUninitialized: false // 无论你是否使用 Session ,我都默认直接给你分配一把钥匙 })) // 添加 session 数据 // req.session.user=user // 保存用户数据到 session // 获取 session 数据 // req.session.user
// session 在后端直接渲染页面时,用得到,前后端分离可能用不到它
19 express app.use() 中间件 错误统一处理
let express = require('express') let app = express() let fs = require('fs') /* * 没路径的中间件会执行 要 next() 执行下一个中间件 * */ /*app.use(function (req, res, next) { res.send('中国人') console.log(1) next() }) app.use(function (req, res, next) { console.log(2) })*/ /* * 以路径 /x 开头的 要 next() 执行下一个中间件 * * */ app.use('/ad',function (req, res, next) { console.log(req.url) res.send('end') // res.render('404.html') // 渲染404错误页面 }) app.get('/',function (req, res, next) { fs.readFile('dfdfdf',function (err, res) { if(err) { return next(err) // 传递错误 } }) }) app.get('/login',function (req, res, next) { // ... user.findOne({username:'xx'},function (err, res) { if(err){ return next(err) // 返回 next(err) } }) }) /* * 错误统一处理, * */ app.use(function (err, req, res, next) { res.status(500).send(err.message) }) app.listen(3000, function () { console.log('app is running ') })
commander 命令行参数
var program = require('commander'); // 获取命令行参数 var colors=require('colors') program .version('0.1.0') .option('-f, --folder <string>', 'add folder') .parse(process.argv); // 原生获取命令行参数 process.argv // node xx.js -f guild console.log('folder',program.folder); // guild console.log('abc'.red); // 红色字体