使用Node运行JS代码
- 使用命令行敲击命令
- 使用node.exe运行(找到文件件,node xxx.js即可)
退出正在运行程序:ctrl+C两次
浏览器中的js是否可以读写到电脑上的文件:不可以,否则很危险,浏览器端的js最高只能访问到当前的浏览器
Node.js不是浏览器端的js:服务器端的js,可以独立于浏览器运行
使用内置模块fs读取txt文件内容
遇到问题,运行时console的中文在命令板上都是乱码
解决方案:将txt的内容重新使用utf-8的格式打开。就是格式需要统一,fs解析的格式和文本的格式需要一致;
路径问题
获取绝对路径
__dirname:文件夹的绝对路径__firename: 文件的绝对路径
const path = require("path");
// 生成路径
const path1 = path.join(__dirname, "./01.txt")
console.log(path1);
使用node开启http服务器
const http = require('http')
const hostname = '127.0.0.1'
const port = 3000
// 开启了服务器
const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/plain')
res.end('Hello')
})
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`)
})
使用第三方模块nodemon
- 可以使用 nodemon xxx.js代替 node xxx.js
- 作用:检测xxx.js是否修改,修改了自动运行(不需要再重启了)
server的req和res
- req:获取浏览器发送的东西,比如req.url;req.method(请求方式);
- res:响应的内容:如果要给浏览器设置通过res即可,比如:
// 状态码
res.statusCode = 200
// 设置响应头
res.setHeader('Content-Type', 'text/plain;charset=utf8')
// 返回响应报文 已经返回了
设置响应头格式
//设置响应头,告诉浏览器内容的格式Content-Type text/plain 普通文本
res.setHeader('Content-Type', 'text/plain;charset=utf8');
//设置响应头,告诉浏览器内容的格式Content-Type text/html html文本
res.setHeader('Content-Type', 'text/html;charset=utf8');
注意:
- 浏览器的嗅探功能
- 服务器不告诉类型浏览器会自动尝试解析,
- 很多时候可以解析出来
- 对于非文本类的文件,读取时,别设置编码格式
- 设置之后解析不出来了
npm 项目初始化
# 自己输入信息,如果没有什么要输入的,比较累赘
npm init
# 自动生成信息
npm init -y
{
名字
"name": "03.npmuse",
版本
"version": "1.0.0",
描述
"description": "",
主要文件
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
关键字
"keywords": [],
作者
"author": "",
开源协议
"license": "ISC"
}
注意:使用npm init -y ,文件夹不能使用中文
文件说明:
-
package.json- 保存项目的基本信息....
- 下载的第三方模块的名字和版本
-
package-lock.json:- 使用
npm下载第三方模块时自动生成的文件 - 保存模块信息
- 模块的下载地址,下次下载速度就会很快
- 使用
-
node_modules- 下载的第三方模块放置的路径
- 不要轻易的删除
- 每个模块(包)的文件夹中,有这个模块的所有信息:版本信息,说明,测试代码,实例代码等等.....
- 如非必要不要去动里面的文件
- 也不需要担心会把你电脑撑坏
cnpm
www.npmmirror.com/?spm=a2c6h.…
npm install -g cnpm --registry=https://registry.npmmirror.com
注意:
- 不会生成
package-lock.json,只有npm才会生成 cnpm i xxx不会把模块信息(包信息)保存到package.json- 完整的命令是
cnpm i xxx --save
- 完整的命令是
express
注意:
express是一个框架- 内部整合了很多第三方的模块
- 下载
express的时候npm或cnpm自动的读取他需要使用的其他模块,并一起下载 - 保证
express一定可以运行
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
三大核心功能:
- 静态资源托管
暴露静态文件:
// 暴露public让外部可以访问
app.use(express.static('public'))
- 路由 express-路由
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.post('/', function (req, res) {
res.send('Got a POST request')
})
app.put('/user', function (req, res) {
res.send('Got a PUT request at /user')
})
app.delete('/user', function (req, res) {
res.send('Got a DELETE request at /user')
})
express.Router的用法:将路由进行拆分
使用页面
const express = require('express')
// 导入路由
const dog = require('./router/dog')
// 创建服务器对象
const app = express()
// 定义端口
const port = 3000
// 注册路由到app中
app.use('/dog',dog)
// 开启监听
app.listen(port,()=>{
console.log(`路由已启动,端口为${port}`);
})
路由页面
// 创建路由
const express = require('express')
// 创建路由
const router = express.Router()
// 通过router注册路由
router.get('/',(req,res)=>{
res.send('11111')
})
router.get('/info',(req,res)=>{
res.send('2222')
})
// 暴露出去
module.exports = router
- 中间件
www.expressjs.com.cn/resources/m…
body-parser:
- 下包:
npm i body-parser
- 导包
`const bodyParser = require('body-parser')`
- 使用
`app.use(bodyParser.urlencoded({ extended: false }))`
实例:
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
const port = 3000
// 解析通过 application/x-www-form-urlencoded 提交的数据
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
// app.use(bodyParser.json())
app.post('/test',(req,res)=>{
console.log(req);
res.send(req.body)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
注意:
-
中间件
body-parser可以理解为express的插件,让express额外增加功能- 中间件,也是
node的第三方模块,只不过必须要和express结合到一起使用 body-parser是一个特殊的第三方模块
-
请求的方法
postman左侧的请求方法一定要和注册路由的方法对应
-
请求的地址
- 自己测试时,建议使用:
localhost或者127.0.0.1 - 上一步没问题了,在测试局域网
ip
- 自己测试时,建议使用:
-
req.body中的属性body对象的属性取决于我们调用接口时,发送的数据
终端工具 cmder
用cmder在多窗口管理这块更加便捷,
URL内置模块
基本结构:
// 导入 http
const http = require('http')
// 导入 fs
const fs = require('fs')
// 导入 path
const path = require('path')
// 端口
const port = 8848
// 创建服务器对象
const server = http.createServer((req, res) => {})
// 开启监听
server.listen(port, () => {
console.log('服务已启动!!')
})
使用:
// 导入 http
const http = require('http')
// 导入 fs
const fs = require('fs')
// 导入 path
const path = require('path')
// 导入 url
const url = require('url')
// 端口
const port = 8848
// 创建服务器对象
const server = http.createServer((req, res) => {
// 获取url
let reqUrl = req.url
// 转码
reqUrl = decodeURI(reqUrl)
// 使用url模块解析参数
const queryObj = url.parse(reqUrl, true)
// 通过上一步获取的对象中的query,点出你要的值
const key = queryObj.query.key
const haha = queryObj.query.haha
// console.log(queryObj)
// console.log(reqUrl)
// 返回地址
res.end(reqUrl)
})
// 开启监听
server.listen(port, () => {
console.log('服务已启动!!')
})
原生获取post提交的数据
// 导入 http
const http = require('http')
// 导入 fs
const fs = require('fs')
// 导入 path
const path = require('path')
const querystring = require('querystring')
// 端口
const port = 8848
// 创建服务器对象
const server = http.createServer((req, res) => {
// 定义保存数据的变量
let str = ''
// data回调函数 数据传输时触发
req.on('data', chunk => {
// console.log(chunk)
str += chunk
})
// end 回调函数 数据传输完毕时触发
req.on('end', () => {
console.log('传递完毕')
console.log('str:', decodeURI(str))
// 解析数据
const sendData = querystring.parse(decodeURI(str))
console.log('解析之后的值:', sendData)
res.end('数据传递完毕')
})
})
// 开启监听
server.listen(port, () => {
console.log('服务已启动!!')
})
express(中间件)获取上传的文件
- 下包
npm i express express-fileupload --save
// 导入 express 第三方模块
const express = require('express')
// 导入 path 内置模块
const path = require('path')
// 导入文件上传模块
const fileUpload = require('express-fileupload')
// 创建服务器对象
const app = express()
// 端口
const port = 3000
// 注册文件上传中间件
app.use(fileUpload())
// 文件上传接口
app.post('/upload', (req, res) => {
// console.log(req.files)
// res.send('success')
// 移动图标
const iconFile = req.files.icon
// 全路径
const fullPath = path.join(__dirname, `./uploads/${iconFile.name}`)
// 移动
iconFile.mv(fullPath, err => {
if (err) {
return res.send('服务器内部错误')
}
res.send('文件上传成功')
})
})
// 开启监听
app.listen(port, () => console.log(`示例程序已启动,端口为 ${port}!`))
默认上传的文件外部是无法访问的,咱们需要通过静态资源暴露出去哦
//一:
// 提供静态资源访问功能 把uploads文件夹暴露出去让大伙访问
// 使用类似于这样的地址访问 http://IP地址:3000/0.gif 直接访问到uploads文件夹里的内容
app.use(express.static('uploads'))
二 如果希望访问时增加路径名,可以添加第一个参数
// 参数1 自己起的文件夹名
// 就可以用类似于这样的方式访问了http://IP地址:3000/uploads/0.gif
app.use('/uploads', express.static('uploads'))
// 就可以用类似于这样的方式访问了http://IP地址:3000/static/0.gif
app.use('/static', express.static('uploads'))
node设置cors解决跨域
- 原生
// 导入 express
const express = require('express')
// 定义端口
const port = 8848
// 创建服务器对象
const app = express()
// 随机数
app.get('/randomNum', (req, res) => {
// 返回
res.send(Math.ceil(Math.random() * 100))
})
// 开启监听
app.listen(port, () => {
console.log(`服务已启动:端口为${port}`)
})
- express
// 导入 express
const express = require('express')
//导入cors
const cors = require('cors')
//使用cors
app.use(cors())
// 定义端口
const port = 8848
// 创建服务器对象
const app = express()
// 开启监听
app.listen(port, () => {
console.log(`服务已启动:端口为${port}`)
})
使用步骤:
- 下包
cnpm i cors --save
- 导包
const cors = require('cors')
- 用包
app.use(cors())
node设置JSONP解决跨域
- 服务器端原生实现JSONP
主要干两件事:
- 接收
callback的参数 - 返回一个
函数的调用给浏览器
- 接收
// 返回一个对象
// 浏览器端必须通过get请求 参数名callback提交一个函数名
// 返回一个函数的调用回去,并且传递一个 对象 作为参数
app.get('/randomFood', (req, res) => {
// get请求参数获取 callback 比如 doSomething
const { callback } = req.query
// 返回一个 函数调用 函数名({name:"jack",age:18,skill:"jump"})
// 返回的是doSomething({name:"西兰花炒蛋",color:"又黄又绿",price:10})
res.send(`${callback}({name:"西兰花炒蛋",color:"又黄又绿",price:10})`)
})
- express实现JSONP
// express的jsonp方法来简化编码
// get提交 callback
// 返回一个函数的调用,有参数
app.get('/randomFoodPro', (req, res) => {
res.jsonp({
name: '',
color: '',
price: 20
})
})
- 其他,jquery实现JSONP jQuery在线文档
// JSONP
$('.jsonp').click(function () {
$.ajax({
url: 'http://IP地址:端口号/search',
type: 'get',
// 设置使用JSONP请求
dataType: 'jsonp',
success(backData) {
console.log(backData)
},
})
})
注意:
- jQuery的
JSONP只需要设置dataType为jsonp即可 - 本质还是通过
script标签发送了一个跨域请求,携带了callback去服务器jQuery的JSONP和ajax有没有关系?- 没有
mySQL简单学习
建表语句
CREATE TABLE `user` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL COMMENT '用户名',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='用户表';
新增语句
insert into 表名(字段名,字段名2) values(值,值2);
删除语句
-- 删除
delete from 表名
-- 带条件的删除
delete from 表名 where 条件
修改语句
-- 改一个
update 表名 set 字段 = 新值;
-- 改多个
update 表名 set 字段 = 新值 ,字段2 = 新值2;
-- 带条件修改
update 表名 set 字段 = 新值 ,字段2 = 新值2 where 条件
查询语句
-- 查询指定字段
select 字段 from 表名;
-- 查询所有字段
select * from 表名;
-- 带条件查询所有字段
select * from 表名 where 条件;
注释
-- 注释
/*
多行注释
*/
通配符-->模糊查询
%为通配符,一般搭配 like 关键字使用。
- 查询所有
字段以关键字开头的数据
select * from 表名 where 字段 like '关键字%';
-- 查询user表中name以j开头的所有数据
select *from student where name like 'j%';
- 查询所有
字段以关键字结尾的数据
select * from 表名 where 字段 like '%关键字';
-- 查询student表中name以y结尾的所有数据
select *from student where name like '%y';
- 查询所有
字段包含关键字的数据
select * from 表名 where 字段 like '%关键字%';
-- 查询student表中name中包含o的所有数据
select *from student where name like '%o%';
并且条件
- 使用and关键字
-- 查询student表中name为jack,并且age为20的数据
select *from student where name='jack' and age='20'
或者条件
- 使用or关键字
-- 找到student表中age小于10,或者age大于100的数据
select *from student where age < 10 or age > 100;
连表查询
- 很多时候同一个页面的数据是从多张表取出
- 例如:如果想展示所有用户的信息以及它下的订单商品,就需要找到两张表的数据联合起来。
select 字段 from 表1 inner join 表2 on 对应关系
-- 找到customer和horder双表结合的结果,只把customer中的cId字段和horder表中custormId字段相等的记录组合在一起
select *from customer inner join horder on customer.cId = horder.custormId
分页查询
- 有时候某张表里有大量数据,而我们只需要查中间的某几条,因此可以用下面的分页查询语句
select * from 表名 limit 第几条开始,查几条;
-- 查询student表里第10条到第20条数据(一共查出来10条)
select * from student limit 10,10;
代码使用mysql
- 下包 :npm i mysql --save
- 官方用例
//导包
var mysql = require('mysql');
//创建数据库
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
//连接数据库
connection.connect();
//执行sql语句
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
//链接断开
connection.end();
注意:
- 增删改查的操作,方法都是一样的,不同的是
SQL - 增删改返回的是
受影响的行数 - 查询返回的是
数据,无论有没有都是数组
knex模块
更简单的操纵数据库 npm - knex
- 下包:npm i knex mysql --save
- 使用
const knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
}
});
- 调用
//具体看官网语法
knex('表名').select().where()
.then(res=>{})
node.js的模块化
commonjs官网 规定了模块的导入语法
const xx = require('xxx')
模块的暴露语法
module.exports=基本数据类型
module.exports=复杂数据类型
实现express中间件
基础模板
// 导入express
const express = require('express')
// 创建服务器对象
const app = express()
// 设置端口
const port = 4399
// 开启监听
app.listen(port, () => {
console.log(`中间件测试demo已启动,端口为${port}`)
})
-
中间件就是一个回调函数
-
参数有3个
req:请求res:响应next:下一个中间件(回调函数)
-
中间件共享同一个请求对象和响应对象
app.use((req, res, next) => {
console.log(' 回调函数1 执行啦!!')
req.secret = '我有一个小秘密,就不告诉你 嘿!'
req.body = {
name: 'jack',
age: 18
}
req.files = {
icon: '班长的图片'
}
// 直接阻断后续执行
return res.send({
msg: '小老弟,怎么回事',
message: '天天GHS'
})
// 通过CORS设置所有的来源都允许跨域访问
// res.setHeader('Access-Control-Allow-Origin', '*')
// 中间件如果不响应请求,或者不执行next
next()
})
app.use((req, res, next) => {
console.log(' 回调函数2 执行啦!!')
req.message = '我是一条小青龙,小青龙'
// 中间件如果不响应请求,或者不执行next
next()
})
// 注册路由
app.get('/list', (req, res) => {
console.log('req.secret', req.secret)
console.log('req.message', req.message)
console.log(req.body)
console.log(req.files)
res.send({
data: ['西瓜', '南瓜', '冬瓜', '北瓜'],
msg: '获取成功'
})
})
// 开启监听
app.listen(port, () => {
console.log(`中间件测试demo已启动,端口为${port}`)
})
第三方的中间件内部就是req中添加了属性
比如req.body,req.files
- 中间件就是回调函数
- 共享
- req
- res
- 通过next去到下一个回调函数(中间件)
- req.setHeader
- res.send
- 动态的为
req添加属性- body-parser就是为
req加了body express-fileupload就是为req加了files
- body-parser就是为
实现一个cors中间件
// 暴露一个回调函数即可
module.exports = (req, res, next) => {
console.log('设置了允许的 header')
// 设置允许的头
// 通过CORS设置所有的来源都允许跨域访问
res.setHeader('Access-Control-Allow-Origin', '*')
// 继续向后执行
next()
}
使用页面
const cors = require('./cors')//为具体路径
app.use(cors)
验证码的刷新功能在html怎么调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<img src="http://127.0.0.1:8848/user/captcha" alt="" />
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script>
$(function () {
$('img').click(function () {
console.log('你点了我!!')
// img的src如果两次设置的一样,认为图片没有更改
// 直接使用缓存中的
// 解决方案,让浏览器认为他变了
// 末尾添加随机数或者时间戳,让两次的地址不同
// 通过?进行分割
// $(this).attr('src', 'http://127.0.0.1:8848/user/captcha')
// 从1970年年初至今的毫秒数
// 时间戳 两次点击肯定不同,并且只会越来越大
// console.log(Date.now())
// $(this).attr(
// 'src',
// `http://127.0.0.1:8848/user/captcha?${Date.now()}`
// )
// 随机数 两次随机相同的概率非常低
$(this).attr(
'src',
`http://127.0.0.1:8848/user/captcha?${Math.random()}`
)
})
})
</script>
</body>
</html>