├── .gitignore ├── README.md ├── note └── git开发流程.txt ├── routes ├── index.js ├── user.js └── article.js ├── views ├── common │ ├── footer.ejs │ └── header.ejs ├── article │ ├── info.ejs │ ├── add.ejs │ └── edit.ejs ├── index.ejs └── user │ ├── login.ejs │ └── register.ejs ├── db └── index.js ├── package.json ├── controller ├── index.js ├── user.js └── article.js ├── app.js └── docs └── blog.sql /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 这是非常厉害的博客项目 2 | # 前端22期真牛逼! 3 | -------------------------------------------------------------------------------- /note/git开发流程.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/blog22/HEAD/note/git开发流程.txt -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router() 3 | const ctrl = require('../controller/index') 4 | 5 | router.get('/', ctrl.getIndexHandler) 6 | 7 | module.exports = router -------------------------------------------------------------------------------- /views/common/footer.ejs: -------------------------------------------------------------------------------- 1 |
2 | 我的github首页 © https://github.com/TianchengLee 3 |
4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /db/index.js: -------------------------------------------------------------------------------- 1 | const mysql = require('mysql') 2 | 3 | const conn = mysql.createConnection({ 4 | host: 'localhost', 5 | user: 'root', 6 | password: 'root', 7 | database: 'blog', 8 | // 开启多条语句执行的功能 9 | multipleStatements: true 10 | }) 11 | 12 | module.exports = conn -------------------------------------------------------------------------------- /routes/user.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router() 3 | const ctrl = require('../controller/user') 4 | 5 | router.get('/register', ctrl.getRegisterHandler) 6 | 7 | router.post('/register', ctrl.postRegisterHandler) 8 | 9 | router.get('/login', ctrl.getLoginHandler) 10 | 11 | router.get('/login/reauth', ctrl.getLoginHandler) 12 | 13 | router.post('/login', ctrl.postLoginHandler) 14 | 15 | router.get('/logout', ctrl.getLogoutHandler) 16 | 17 | module.exports = router -------------------------------------------------------------------------------- /routes/article.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router() 3 | const ctrl = require('../controller/article') 4 | 5 | router.get('/article/add', ctrl.getArticleAddHandler) 6 | 7 | router.post('/article/add', ctrl.postArticleAddHandler) 8 | 9 | router.get('/article/info/:id', ctrl.getArticleInfoHandler) 10 | 11 | router.get('/article/edit/:id', ctrl.getArticleEditHandler) 12 | 13 | router.post('/article/edit/:id', ctrl.postArticleEditHandler) 14 | 15 | module.exports = router -------------------------------------------------------------------------------- /views/article/info.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../common/header.ejs') %> 2 | 3 | 4 |
5 |

6 | <%= articleInfo.title %> 7 | <% if (isLogin && userInfo.id === articleInfo.author_id) { %> 8 | 编辑 9 | <% } %> 10 |

11 |
12 | 13 |
14 | 15 | <%- articleInfo.content%> 16 | 17 |
18 |
19 | 20 | <%- include('../common/footer.ejs') %> -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "heima_blog", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcryptjs": "^2.4.3", 14 | "body-parser": "^1.18.3", 15 | "bootstrap": "^3.3.7", 16 | "ejs": "^2.6.1", 17 | "express": "^4.16.3", 18 | "express-session": "^1.15.6", 19 | "jquery": "^3.3.1", 20 | "marked": "^0.5.2", 21 | "mditor": "^1.3.3", 22 | "moment": "^2.22.2", 23 | "mysql": "^2.15.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./common/header.ejs') %> 2 | 3 | 4 |
5 | 6 |

文章列表

7 | 8 |
9 | <% articleInfos.forEach(item => { %> 10 | 11 | <%= item.title %> 12 | 14 | 作者昵称: 15 | <%= item.nickname %> 16 | 17 | <% }) %> 18 |
19 | 20 | 34 |
35 | 36 | <%- include('./common/footer.ejs') %> -------------------------------------------------------------------------------- /controller/index.js: -------------------------------------------------------------------------------- 1 | const conn = require('../db') 2 | 3 | module.exports = { 4 | // 约定大于配置 5 | getIndexHandler(req, res) { 6 | 7 | // 每页显示多少条数据 8 | // MD5 9 | const pageSize = 5 10 | // 当前是多少页 11 | const currentPage = Number(req.query.page) || 1 12 | console.log(currentPage) 13 | 14 | const sql = `select a.id, a.title, a.ctime, u.nickname 15 | from articles as a 16 | left join users as u 17 | on a.author_id = u.id 18 | order by a.ctime desc 19 | limit ?, ${pageSize}; 20 | select count(*) as count from articles` 21 | // (currentPage - 1) * pageSize 22 | // 0, 3 23 | // 3, 3 24 | // 6, 3 25 | // ... 26 | 27 | conn.query(sql, (currentPage - 1) * pageSize, (err, result) => { 28 | if (err) return res.send(err.message) 29 | // 以前的result 就是现在的result[0] 30 | // count(*)查询的结果就是现在的 result[1] 31 | // 所有的数据总条数 32 | const totalCount = result[1][0].count 33 | // 算出总页数 向上取整 34 | const totalPage = Math.ceil(totalCount / pageSize) 35 | // console.log(result) 36 | res.render('index', { 37 | userInfo: req.session.userInfo, 38 | isLogin: req.session.isLogin, 39 | articleInfos: result[0], 40 | totalPage, 41 | currentPage 42 | }) 43 | }) 44 | 45 | } 46 | } 47 | 48 | // Require.js / Sea.js 49 | // 高内聚 能在自己内部完成的功能一定不要干扰外部 50 | // 低耦合 尽可能的降低模块之间的耦合度 -------------------------------------------------------------------------------- /views/article/add.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../common/header.ejs') %> 2 | 3 | 4 | 5 | 6 | 7 |
8 |

发表文章页

9 |
10 |
11 |
12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 |
20 | 21 |
22 | 23 |
24 |
25 |
26 | 27 | 66 | 67 | <%- include('../common/footer.ejs') %> -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const bodyParser = require('body-parser') 3 | const fs = require('fs') 4 | const path = require('path') 5 | const session = require('express-session') 6 | 7 | // app.use() : 注册中间件 8 | // app.set() : 设置一些配置的 例如 views 设置模板存放目录 view engine 设置默认的模板引擎 9 | // app.get / post / delete / option / head / put 监听不同请求方式的方法 10 | // app.get('/') app.post('/') 11 | // res.render() : 渲染, 必须设置好模板引擎后才可以使用 12 | // res.send() : 响应数据(对象数组字符串, 不能是number) 如果传入数组字符串, express内部执行了JSON.stringfy() 将对象序列化为字符串 13 | // res.status() : 改变响应的状态码 14 | // res.redirect() : 重定向 15 | 16 | const app = express() 17 | 18 | // 例如body-parser 就是在处理请求之前帮我们把 用户提交的表单信息 封装好了 19 | // 中间件的作用就是在处理请求之前 做一些封装操作 20 | // express-session帮我们做的事情就是 通过sessionID取出对应的session 21 | app.use(session({ 22 | secret: 'keyboard cat', 23 | resave: false, 24 | saveUninitialized: true, 25 | // 如果不设置过期时间 默认 关闭浏览器即过期, 无法存储有效的cookie 26 | cookie: { maxAge: 1000 * 60 * 60 * 24 * 30 } 27 | })) 28 | 29 | app.use(bodyParser.urlencoded({ extended: false })) 30 | 31 | // 静态资源托管 32 | app.use('/node_modules', express.static('./node_modules')) 33 | 34 | // 设置模板引擎 35 | app.set('view engine', 'ejs') 36 | 37 | // 设置模板存放路径 如果不设置 默认就在views目录 38 | // app.set('views', './views') 39 | 40 | // 注册路由 41 | // const indexRouter = require('./routes/index') 42 | // app.use(indexRouter) 43 | 44 | // app.use(require('./routes/index')) 45 | // app.use(require('./routes/user')) 46 | 47 | // 使用fs模块读取routes目录下所有的文件名 48 | fs.readdir('./routes', (err, files) => { 49 | if (err) return console.log(err.message) 50 | files.forEach(filename => { 51 | // 相对路径引入 52 | // console.log('./routes/' + filename) 53 | // app.use(require('./routes/' + filename)) 54 | 55 | // 绝对路径引入 56 | // let 和 const 都有块级作用域 57 | const filePath = path.join(__dirname, './routes/' + filename) 58 | // console.log(filePath) 59 | app.use(require(filePath)) 60 | }) 61 | }) 62 | 63 | // 循环10次 就有10个单独的作用域 并不会对a重新赋值 每次循环都是一个新的a 64 | // for (let i = 0; i < 10; i++) { 65 | // const a = 10 66 | // } 67 | 68 | app.listen(80, () => { 69 | console.log('http://127.0.0.1'); 70 | }) -------------------------------------------------------------------------------- /views/user/login.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 25 | 26 | 27 | 28 |
29 |

登录页面

30 |
31 | 32 |
33 | 34 |
35 | 37 |
38 | 39 |
40 | 去注册 41 |
42 | 43 |
44 | 45 |
46 |
47 | 48 | 49 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /views/user/register.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 25 | 26 | 27 | 28 |
29 |

注册页面

30 |
31 | 32 |
33 | 34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 | 42 |
43 | 44 |
45 |
46 | 47 | 48 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /views/article/edit.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../common/header.ejs') %> 2 | 3 | 4 | 5 | 6 | 7 |
8 |

编辑文章页

9 |
10 |
11 | 12 |
13 | 14 | 15 |
16 | 17 |
18 | 19 | 22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 | 69 | 70 | <%- include('../common/footer.ejs') %> -------------------------------------------------------------------------------- /controller/user.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment') 2 | const conn = require('../db') 3 | const bcrypt = require('bcryptjs') 4 | 5 | 6 | module.exports = { 7 | getRegisterHandler(req, res) { 8 | res.render('./user/register', {}) 9 | }, 10 | postRegisterHandler(req, res) { 11 | // console.log(req.body) 12 | let userInfo = req.body 13 | // 1. 表单校验 14 | if (!userInfo.username || !userInfo.nickname || !userInfo.password) return res.status(400).send({ status: 400, msg: '请输入正确的表单信息!' }) 15 | 16 | // 2. 查重 判断用户名是否已经存在 连接数据库查询 17 | const chachongSql = 'select count(*) as count from users where username = ?' 18 | conn.query(chachongSql, userInfo.username, (err, result) => { 19 | if (err) return res.status(500).send({ status: 500, msg: '查重失败!请重试!' }) 20 | // result[0].count // 为0表示没有重复, 可以用 21 | if (result[0].count !== 0) return res.status(400).send({ status: 400, msg: '用户名重复!请重试!' }) 22 | 23 | // 能到此处 说明可以注册 24 | // 添加ctime字段 25 | userInfo.ctime = moment().format('YYYY-MM-DD HH:mm:ss') 26 | 27 | const salt = bcrypt.genSaltSync(10) 28 | // 对密码进行加密 29 | const hash = bcrypt.hashSync(userInfo.password, salt) 30 | // console.log(hash) 31 | userInfo.password = hash 32 | 33 | // console.log(userInfo) 34 | // 执行注册的sql语句 使用MySQL模块 注意insert into xxx set 35 | const registerSql = 'insert into users set ?' 36 | conn.query(registerSql, userInfo, (err, result) => { 37 | if (err) return res.status(500).send({ status: 500, msg: '注册失败!请重试!' }) 38 | // 让浏览器跳到登录页 39 | // 302重定向 40 | // res.redirect('/login') 41 | res.send({ status: 200, msg: '注册成功!' }) 42 | }) 43 | }) 44 | }, 45 | getLoginHandler(req, res) { 46 | res.render('./user/login', {}) 47 | }, 48 | postLoginHandler(req, res) { 49 | // console.log(req.body) 50 | // 1. 直接去数据库执行查询语句 条件 username和password 51 | const loginSql = 'select * from users where username = ?' 52 | conn.query(loginSql, req.body.username, (err, result) => { 53 | // 如果查询出错 或者没有查询到结果 就提示登录失败 54 | if (err || result.length === 0) return res.status(400).send({ status: 400, msg: '登录失败!请重试!' }) 55 | // 使用bcrypt进行校验 56 | if (!bcrypt.compareSync(req.body.password, result[0].password)) return res.status(400).send({ status: 400, msg: '登录失败!请重试!' }) 57 | // 登录成功 58 | // 将用户信息存储在session中 59 | req.session.userInfo = result[0] 60 | // 记录登录状态 61 | req.session.isLogin = true 62 | res.send({ status: 200, msg: '登录成功!' }) 63 | }) 64 | }, 65 | getLogoutHandler(req, res) { 66 | req.session.destroy((err) => { 67 | // cannot access session here 68 | // 在这里不能访问session了 已经销毁完成了 69 | res.send({status: 200, msg: '退出登录成功!'}) 70 | }) 71 | } 72 | } -------------------------------------------------------------------------------- /views/common/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Document 12 | 13 | 14 | 15 | 65 | 66 | -------------------------------------------------------------------------------- /controller/article.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment') 2 | const conn = require('../db') 3 | const marked = require('marked') 4 | 5 | const mditor = require('mditor') 6 | const parser = new mditor.Parser() 7 | 8 | 9 | module.exports = { 10 | getArticleAddHandler(req, res) { 11 | // 未登录用户的拦截操作 12 | // 每一次请求都是独立的 13 | if (!req.session.isLogin) return res.redirect('/') 14 | 15 | res.render('article/add', { 16 | isLogin: req.session.isLogin, 17 | userInfo: req.session.userInfo 18 | }) 19 | }, 20 | postArticleAddHandler(req, res) { 21 | // 没有登录或者身份信息已经失效 22 | if (!req.session.isLogin) return res.status(401).send({ status: 401, msg: '身份信息已过期!请登陆后重试!' }) 23 | 24 | // req.body 是引用数据类型 对象 25 | // 将req.body的地址值赋值给articleInfo变量 26 | // req.body和articleInfo同时指向同一个对象 27 | // 往articleInfo上添加ctime属性等于给req.body上添加ctime属性 28 | const articleInfo = req.body 29 | articleInfo.ctime = moment().format('YYYY-MM-DD HH:mm:ss') 30 | articleInfo.author_id = req.session.userInfo.id 31 | conn.query('insert into articles set ?', articleInfo, (err, result) => { 32 | if (err || result.affectedRows != 1) return res.status(500).send({ status: 500, msg: '文章发表失败!请重试!' + err.message }) 33 | // 还需要将刚插入数据库的那条数据ID也一起返回 34 | res.send({ status: 200, msg: '文章发表成功!', articleId: result.insertId }) 35 | }) 36 | }, 37 | getArticleInfoHandler(req, res) { 38 | const articleId = parseInt(req.params.id) 39 | 40 | // 根据ID查询数据库 获取文章详情 41 | conn.query('select * from articles where id = ?', articleId, (err, result) => { 42 | if (err || result.length !== 1) return res.redirect('/') 43 | // console.log(err) 44 | // render和send的是使用时机 45 | // 当用户使用get请求访问服务器并且需要看到页面时 应该用render渲染 46 | // 当用户使用ajax请求访问服务器 并且需要获取数据时 应该用send返回数据 47 | // res.send(result) 48 | // result[0].content = marked(result[0].content) 49 | result[0].content = parser.parse(result[0].content) 50 | res.render('article/info', { 51 | isLogin: req.session.isLogin, 52 | userInfo: req.session.userInfo, 53 | articleInfo: result[0] 54 | }) 55 | }) 56 | }, 57 | getArticleEditHandler(req, res) { 58 | // 如果只做登录校验是不严谨的 59 | // 应该加上作者的校验 60 | if (!req.session.isLogin) return res.redirect('/') 61 | // 文章ID 62 | const articleId = parseInt(req.params.id) 63 | // 根据文章ID查询数据库 获取文章详情信息 64 | conn.query('select * from articles where id = ?', articleId, (err, result) => { 65 | if (err || result.length !== 1) return res.redirect('/') 66 | // 权限的控制: 如果当前登录的用户ID和作者ID不匹配 也不能渲染 67 | if (req.session.userInfo.id != result[0].author_id) return res.redirect('/') 68 | // 文章详情获取到了 69 | res.render('article/edit', { 70 | isLogin: req.session.isLogin, 71 | userInfo: req.session.userInfo, 72 | articleInfo: result[0] 73 | }) 74 | }) 75 | 76 | }, 77 | postArticleEditHandler(req, res) { 78 | // console.log(req.body) 79 | // console.log(req.params) 80 | // 更新文章的时间 81 | req.body.ctime = moment().format('YYYY-MM-DD HH:mm:ss') 82 | conn.query('update articles set ? where id = ?', [req.body, req.params.id], (err, result) => { 83 | if (err || result.affectedRows !== 1) return res.status(500).send({status: 500, msg:'文章修改失败,请重试!'}) 84 | 85 | res.send({status: 200, msg: '文章修改成功!'}) 86 | }) 87 | } 88 | } -------------------------------------------------------------------------------- /docs/blog.sql: -------------------------------------------------------------------------------- 1 | # Host: localhost (Version: 5.5.53) 2 | # Date: 2018-12-19 09:51:20 3 | # Generator: MySQL-Front 5.3 (Build 4.234) 4 | 5 | /*!40101 SET NAMES utf8 */; 6 | 7 | # 8 | # Database "blog" 9 | # 10 | 11 | CREATE DATABASE IF NOT EXISTS `blog` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */; 12 | USE `blog`; 13 | 14 | # 15 | # Structure for table "articles" 16 | # 17 | 18 | DROP TABLE IF EXISTS `articles`; 19 | CREATE TABLE `articles` ( 20 | `id` int(11) NOT NULL AUTO_INCREMENT, 21 | `title` varchar(255) NOT NULL DEFAULT '', 22 | `content` text NOT NULL, 23 | `ctime` varchar(255) NOT NULL DEFAULT '', 24 | `author_id` int(11) NOT NULL DEFAULT '0', 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; 27 | 28 | # 29 | # Data for table "articles" 30 | # 31 | 32 | /*!40000 ALTER TABLE `articles` DISABLE KEYS */; 33 | INSERT INTO `articles` VALUES (1,'谢俊向坐我旁边?','# 呵呵!\r\n','2018-12-17 10:49:22',1),(2,'谢俊真牛逼!','吴聪也牛逼!','2018-12-17 10:57:42',1),(3,'谢俊儿真牛逼!!!','吴聪儿真牛!!','2018-12-17 10:59:21',1),(4,'哈哈哈','啊啊啊','2018-12-17 11:13:58',1),(5,'谢俊废了吴聪牛了邰姐妈咪了!',' ## node day01 ##\r\n\r\n### node的简介 ###\r\n\r\n- 前后端分离:\r\n\r\n\t前端负责写页面, 和发送ajax请求获取数据, 通过模板引擎进行渲染\r\n\t\r\n\t后端负责写接口, 提供数据\r\n\r\n- node环境的JavaScript\r\n\r\n\t不同于浏览器中js, 不存在DOM和BOM的概念\r\n\r\n\t以前所说的js的组成: ECMAScript + BOM + DOM, 其实是指在浏览器中JS的组成\r\n\r\n\t\tdocument.getElementById() // DOM中的方法\r\n\t\tvar arr = []\r\n\t\tarr.sort() // ECMAScript中规范的方法\r\n\r\n\t共同点: 只要是js, 都会遵循ECMAScrit规范\r\n\r\n\tnode环境的js组成: ECMAScript + 全局成员 + 内置模块 + 第三方模块\r\n\r\n\tnpm: node package manager (node包管理器)\r\n\r\n- 使用node运行js\r\n\r\n\t打开终端(Windows控制台) , cmd\r\n\r\n### ES6新语法 ###\r\n\r\n1. let关键字\r\n\r\n\t由于JS历史遗留问题, 声明变量一直使用var关键字, 特点就是有变量声明提升, 没有块级作用域\r\n\r\n\tlet关键字的出现就是为了解决上述两个问题, 特点如下:\r\n\r\n\ta. let声明变量必须声明后才可以使用, 如果在声明之前使用变量会直接报错: xxx is not defined\r\n\r\n\tb. let声明变量不赋值, 默认值也是undefined\r\n\r\n\tc. let声明的变量有块级作用域, 如果在if/while/for等有大括号的代码中声明变量, 出了这个大括号就无法访问了\r\n\r\n\td. let和const都无法重复声明变量, 一旦变量被声明就不可再次声明\r\n\r\n2. const关键字\r\n\r\n\t不同于let的是, const用于声明常量, 一旦被声明必须立即赋值, 并且永远不可修改\r\n\r\n\ta. const声明的常量必须立即赋值\r\n\r\n\tb. 不可被再次修改\r\n\r\n\tc. 其他地方同let\r\n\r\n3. 解构赋值\r\n\r\n\t作用: 将对象的属性提取出来存在变量中, 例如, 将userInfo对象的name和age属性提取出来放到name和age变量中存储:\r\n\r\n\t\tlet userInfo = {\r\n\t\t\tname: \'谢俊\',\r\n\t\t\tage: 30,\r\n\t\t\tgender: \'男\',\r\n\t\t\tsayHi: function() {\r\n\t\t\t\tconsole.log(\'大家好我是\' + this.name)\r\n\t\t\t}\r\n\t\t}\r\n\t\t// 以前的做法:\r\n\t\t// let name = userInfo.name\r\n\t\t// let userAge = userInfo.age\r\n\t\t// let sayHi = userInfo.sayHi\r\n\t\t// sayHi()\r\n\t\t// ES6解构赋值的做法:\r\n\t\tlet { name, age: userAge, sayHi } = userInfo\r\n\t\t// 以上代码只是将用户信息的属性值提取出来存到变量中了, 如果修改变量name或userAge, 不会影响userInfo中的数据, 因为这是基本数据类型, 传递数据都是值传递\r\n\r\n4. 箭头函数\r\n\r\n\t作用: 为了解决函数内部this指向的问题, 箭头函数的特点就是, 函数内部的this永远指向函数外部的this\r\n\r\n\t语法:\r\n\r\n\t\t// 小括号里面写形参列表\r\n\t\t// 大括号里面写函数体\r\n\t\t() => {}\r\n\r\n\t简便写法:\r\n\r\n\ta. 如果形参列表只有一个参数, 可以省略小括号, 注意: 如果一个参数都没有或者两个以上的参数必须加上小括号`()`\r\n\r\n\tb. 如果函数体中只有一行代码, 那么右侧的大括号`{}`可以省略, 并且还需要去掉return关键字, 默认会把这一行代码执行的结果返回出去\r\n\r\n5. 添加对象属性或方法的简便写法\r\n\r\n\t作用: 把和对象属性同名的变量快速的添加到对象中\r\n\r\n\t以前的写法\r\n\r\n\t\tlet name = \'谢俊\'\r\n\t\tlet age = 30\r\n\t\t\r\n\t\tlet obj = {\r\n\t\t name: name,\r\n\t\t age: age\r\n\t\t}\r\n\r\n\tES6的写法:\r\n\r\n\t\tlet name = \'谢俊\'\r\n\t\tlet age = 30\r\n\t\tlet fn = function () {\r\n\t\t console.log(\'我是fn\')\r\n\t\t}\r\n\t\t\r\n\t\tlet obj = {\r\n\t\t name,\r\n\t\t age,\r\n\t\t fn,\r\n\t\t sayHi() {\r\n\t\t \r\n\t\t }\r\n\t\t}\r\n\r\n\r\n### fs模块 ###\r\n\r\nfs模块属于核心模块, 只要安装了node环境就会携带, 使用方法先导入该模块:\r\n\r\n\tconst fs = require(\'fs\')\r\n\r\n1. 读取文件\r\n\r\n\t\tfs.readFile()\r\n\r\n\t参数1: 路径 path, 可以是相对路径\r\n\r\n\t参数2: 可选值 编码\r\n\r\n\t参数3: 读取完成的回调函数, 该回调函数中有两个参数, 第一个是错误信息err, 第二个是读取的数据data, 如果没有指定编码, data是Buffer类型的数据, 可以通过toString转为字符串\r\n\r\n2. 写入文件\r\n\r\n\t\tfs.writeFile()\r\n\r\n\t参数1: 路径\r\n\r\n\t参数2: 要写入的数据, 类型可以是string或buffer\r\n\r\n\t参数3: 可选值 编码 默认utf-8\r\n\r\n\t参数4: 回调函数, 该回调函数只有一个参数错误信息err\r\n\r\n\t**注意: 如果要写入的文件不存在, 会创建文件后写入**\r\n\r\n3. 追加文件\r\n\r\n\t\tfs.appendFile()\r\n\r\n\t参数1: 路径\r\n\r\n\t参数2: 要追加的数据, 类型可以是string或buffer\r\n\r\n\t参数3: 可选值 编码 默认utf-8\r\n\r\n\t参数4: 回调函数, 该回调函数只有一个参数错误信息err\r\n\r\n\t**注意: 如果要追加的文件不存在, 会创建文件后追加**\r\n\r\n\r\n4. 复制文件\r\n\r\n\t\tfs.copyFile()\r\n\r\n\t参数1: 源路径\r\n\r\n\t参数2: 目标路径\r\n\r\n\t参数3: 可选值 flags 无视掉\r\n\r\n\t参数4: 回调函数, 该回调函数只有一个参数错误信息err\r\n \r\n \r\n \r\n \r\n ','2018-12-17 15:42:14',1),(6,'这是谢俊废了毕生精力写出来的文章','## node day01 ##\r\n\r\n### node的简介 ###\r\n\r\n- 前后端分离:\r\n\r\n\t前端负责写页面, 和发送ajax请求获取数据, 通过模板引擎进行渲染\r\n\t\r\n\t后端负责写接口, 提供数据\r\n\r\n- node环境的JavaScript\r\n\r\n\t不同于浏览器中js, 不存在DOM和BOM的概念\r\n\r\n\t以前所说的js的组成: ECMAScript + BOM + DOM, 其实是指在浏览器中JS的组成\r\n\r\n\t\tdocument.getElementById() // DOM中的方法\r\n\t\tvar arr = []\r\n\t\tarr.sort() // ECMAScript中规范的方法\r\n\r\n\t共同点: 只要是js, 都会遵循ECMAScrit规范\r\n\r\n\tnode环境的js组成: ECMAScript + 全局成员 + 内置模块 + 第三方模块\r\n\r\n\tnpm: node package manager (node包管理器)\r\n\r\n- 使用node运行js\r\n\r\n\t打开终端(Windows控制台) , cmd\r\n\r\n### ES6新语法 ###\r\n\r\n1. let关键字\r\n\r\n\t由于JS历史遗留问题, 声明变量一直使用var关键字, 特点就是有变量声明提升, 没有块级作用域\r\n\r\n\tlet关键字的出现就是为了解决上述两个问题, 特点如下:\r\n\r\n\ta. let声明变量必须声明后才可以使用, 如果在声明之前使用变量会直接报错: xxx is not defined\r\n\r\n\tb. let声明变量不赋值, 默认值也是undefined\r\n\r\n\tc. let声明的变量有块级作用域, 如果在if/while/for等有大括号的代码中声明变量, 出了这个大括号就无法访问了\r\n\r\n\td. let和const都无法重复声明变量, 一旦变量被声明就不可再次声明\r\n\r\n2. const关键字\r\n\r\n\t不同于let的是, const用于声明常量, 一旦被声明必须立即赋值, 并且永远不可修改\r\n\r\n\ta. const声明的常量必须立即赋值\r\n\r\n\tb. 不可被再次修改\r\n\r\n\tc. 其他地方同let\r\n\r\n3. 解构赋值\r\n\r\n\t作用: 将对象的属性提取出来存在变量中, 例如, 将userInfo对象的name和age属性提取出来放到name和age变量中存储:\r\n\r\n\t\tlet userInfo = {\r\n\t\t\tname: \'谢俊\',\r\n\t\t\tage: 30,\r\n\t\t\tgender: \'男\',\r\n\t\t\tsayHi: function() {\r\n\t\t\t\tconsole.log(\'大家好我是\' + this.name)\r\n\t\t\t}\r\n\t\t}\r\n\t\t// 以前的做法:\r\n\t\t// let name = userInfo.name\r\n\t\t// let userAge = userInfo.age\r\n\t\t// let sayHi = userInfo.sayHi\r\n\t\t// sayHi()\r\n\t\t// ES6解构赋值的做法:\r\n\t\tlet { name, age: userAge, sayHi } = userInfo\r\n\t\t// 以上代码只是将用户信息的属性值提取出来存到变量中了, 如果修改变量name或userAge, 不会影响userInfo中的数据, 因为这是基本数据类型, 传递数据都是值传递\r\n\r\n4. 箭头函数\r\n\r\n\t作用: 为了解决函数内部this指向的问题, 箭头函数的特点就是, 函数内部的this永远指向函数外部的this\r\n\r\n\t语法:\r\n\r\n\t\t// 小括号里面写形参列表\r\n\t\t// 大括号里面写函数体\r\n\t\t() => {}\r\n\r\n\t简便写法:\r\n\r\n\ta. 如果形参列表只有一个参数, 可以省略小括号, 注意: 如果一个参数都没有或者两个以上的参数必须加上小括号`()`\r\n\r\n\tb. 如果函数体中只有一行代码, 那么右侧的大括号`{}`可以省略, 并且还需要去掉return关键字, 默认会把这一行代码执行的结果返回出去\r\n\r\n5. 添加对象属性或方法的简便写法\r\n\r\n\t作用: 把和对象属性同名的变量快速的添加到对象中\r\n\r\n\t以前的写法\r\n\r\n\t\tlet name = \'谢俊\'\r\n\t\tlet age = 30\r\n\t\t\r\n\t\tlet obj = {\r\n\t\t name: name,\r\n\t\t age: age\r\n\t\t}\r\n\r\n\tES6的写法:\r\n\r\n\t\tlet name = \'谢俊\'\r\n\t\tlet age = 30\r\n\t\tlet fn = function () {\r\n\t\t console.log(\'我是fn\')\r\n\t\t}\r\n\t\t\r\n\t\tlet obj = {\r\n\t\t name,\r\n\t\t age,\r\n\t\t fn,\r\n\t\t sayHi() {\r\n\t\t \r\n\t\t }\r\n\t\t}\r\n\r\n\r\n### fs模块 ###\r\n\r\nfs模块属于核心模块, 只要安装了node环境就会携带, 使用方法先导入该模块:\r\n\r\n\tconst fs = require(\'fs\')\r\n\r\n1. 读取文件\r\n\r\n\t\tfs.readFile()\r\n\r\n\t参数1: 路径 path, 可以是相对路径\r\n\r\n\t参数2: 可选值 编码\r\n\r\n\t参数3: 读取完成的回调函数, 该回调函数中有两个参数, 第一个是错误信息err, 第二个是读取的数据data, 如果没有指定编码, data是Buffer类型的数据, 可以通过toString转为字符串\r\n\r\n2. 写入文件\r\n\r\n\t\tfs.writeFile()\r\n\r\n\t参数1: 路径\r\n\r\n\t参数2: 要写入的数据, 类型可以是string或buffer\r\n\r\n\t参数3: 可选值 编码 默认utf-8\r\n\r\n\t参数4: 回调函数, 该回调函数只有一个参数错误信息err\r\n\r\n\t**注意: 如果要写入的文件不存在, 会创建文件后写入**\r\n\r\n3. 追加文件\r\n\r\n\t\tfs.appendFile()\r\n\r\n\t参数1: 路径\r\n\r\n\t参数2: 要追加的数据, 类型可以是string或buffer\r\n\r\n\t参数3: 可选值 编码 默认utf-8\r\n\r\n\t参数4: 回调函数, 该回调函数只有一个参数错误信息err\r\n\r\n\t**注意: 如果要追加的文件不存在, 会创建文件后追加**\r\n\r\n\r\n4. 复制文件\r\n\r\n\t\tfs.copyFile()\r\n\r\n\t参数1: 源路径\r\n\r\n\t参数2: 目标路径\r\n\r\n\t参数3: 可选值 flags 无视掉\r\n\r\n\t参数4: 回调函数, 该回调函数只有一个参数错误信息err\r\n ','2018-12-17 14:53:40',1),(7,'邰姐说','喜欢妈咪海松','2018-12-17 16:36:27',3); 34 | /*!40000 ALTER TABLE `articles` ENABLE KEYS */; 35 | 36 | # 37 | # Structure for table "users" 38 | # 39 | 40 | DROP TABLE IF EXISTS `users`; 41 | CREATE TABLE `users` ( 42 | `id` int(11) NOT NULL AUTO_INCREMENT, 43 | `username` varchar(255) NOT NULL DEFAULT '', 44 | `password` varchar(255) NOT NULL DEFAULT '', 45 | `nickname` varchar(255) NOT NULL DEFAULT '', 46 | `ctime` varchar(255) NOT NULL DEFAULT '', 47 | `isdel` tinyint(3) NOT NULL DEFAULT '0', 48 | PRIMARY KEY (`id`) 49 | ) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; 50 | 51 | # 52 | # Data for table "users" 53 | # 54 | 55 | /*!40000 ALTER TABLE `users` DISABLE KEYS */; 56 | INSERT INTO `users` VALUES (1,'xiejun','123','渣渣俊','2018-12-14 16:12:06',0),(2,'xiejun2','123','渣渣俊2','2018-12-14 16:13:49',0),(3,'taijie','123','妈咪','2018-12-14 16:14:43',0),(4,'huabanxie','123','滑板鞋','2018-12-14 16:15:14',0),(5,'xiejun222','123','俊222','2018-12-14 16:43:07',0),(6,'xxx','xxx','xxx','2018-12-16 09:52:28',0),(7,'taijie2','123','邰姐海松妈咪','2018-12-17 16:53:51',0),(8,'taijie3','123','邰姐海松妈咪','2018-12-17 16:54:04',0),(9,'taijie4','$2a$10$aYlYmZlVW0dbdPcV3oc6Uebjsknk/puNOValz58RuAwSUGyA8nZ7G','邰姐海松妈咪','2018-12-17 16:55:06',0),(10,'taijie5','$2a$10$zDnuCkJ3xWHGMdow66mZYe6TabCygq9HbR85TSfpn7n1k8OSIQWrG','邰姐5','2018-12-17 16:59:02',0),(11,'taijie6','$2a$10$zDnuCkJ3xWHGMdow66mZYe6TabCygq9HbR85TSfpn7n1k8OSIQWrG','邰姐6','2018-12-17 16:59:47',0),(12,'taijie7','$2a$10$nZHvfrlBj8OsMs7.8jocxuYR3x1hJUZHEsHR17A7SzrzLbrKlE0Nm','邰姐6','2018-12-17 17:00:45',0),(13,'taijie8','$2a$10$Q97MVBEaVzXxGY5cfs9ubem3Myc9NwFD5RM6MfF.qklDHDicxlrYm','邰姐6','2018-12-17 17:00:55',0); 57 | /*!40000 ALTER TABLE `users` ENABLE KEYS */; 58 | --------------------------------------------------------------------------------