图片上传功能中,预览功能实现
方法一:FileReader
方法二:createObjectURL
const file = document.querySelector('#file')
const img = document.querySelector('#img')
方法一:
file.onchange = () => {
// 浏览器中的 fs,但是只能操作用户选择的文件
const reader = new FileReader()
// 第二步:
// 当图片读取转换完成,会触发 load 事件
reader.addEventListener("load", function () {
console.log(reader.result)
// 此处得到的是一个 base64 编码之后的内容
// 你可以认为图片文件文本化了
img.src = reader.result
}, false)
// 第一步:
// 开始读文件
reader.readAsDataURL(file.files[0])
}
// 方法二:
// file.onchange = () => {
// // 使用
// const data = URL.createObjectURL(file.files[0])
// img.src = data
// // 最好在使用完毕 data 之后,把它释放掉
// // URL.revokeObjectURL(data)
// }
HTTP缓存
缓存说的是GET请求
- 用node中原生的http模块来创建http服务进行测试
- 观察请求的打印日志
console.log
- Axios 中的错误对象继承自 JavaScript 中的 Error 对象
- console.log 内容和数据类型无关
- 浏览器输出Error对象时候会读取它内部的 stack 属性
- 所以打印的error只能看到文字,但是在代码中能点出方法
- MDN中的描述:通过Error的构造器可以创建一个错误对象。请注意,这是一个对像!
socket.io
- 浏览器服务端都要用到此插件,同时使用才能进行通信
- socket使用socket协议,http使用http协议,完全不同
- socket可是实现群发和单发功能
- 使用socket能很快速实现一个聊天功能,并不复杂。
简单实现
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<div id="app">
<form action="">
<input v-model="nickname" type="text">
<button @click.prevent="handleNickname"></button>
</form>
<!-- 消息列表 -->
<ul id="messages">
<li
v-for="(item, index) in messageList"
:key="index"
>
{{ item }}
</li>
</ul>
<!-- 发送消息的表单 -->
<form action="">
<div style="border: 1px solid #000;">
<input v-model="nickname" type="text">
<button @click.prevent="handleNickname">昵称</button>
</div>
<!-- 广播 -->
<input
v-model="message"
autocomplete="off"
/>
<button
@click.prevent="handleSend"
>广播</button>
<!-- 私聊 -->
<div style="border: 1px solid #000;">
<input v-model="privateMessage" type="text">
<input v-model="privateUser" type="text">
<button @click.prevent="handlePrivateMessage">私聊</button>
</div>
</form>
</div>
<!-- 加载 socket.io 客户端 -->
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js"></script>
<script>
// WebSocket 通过 HTTP 协议建立连接
// 建立连接成功后使用 WebSocket 进行通信
const socket = io()
// 接收服务端消息
// socket.on('hello', data => {
// console.log(data)
// })
socket.on('connect', () => {
})
const app = new Vue({
el: '#app',
data: {
message: '',
messageList: [], // 消息列表
nickname: '',
privateMessage: '',
privateUser: ''
},
created () {
socket.on('message', data => {
// console.log('message => ', data)
this.messageList.push(`${data.nickname}说:${data.message}`)
})
socket.on('chat-count', count => {
this.messageList.push(`当前在线人数:${count}`)
})
socket.on('private-message', data => {
console.log('private-message', data)
this.messageList.push(`${data.nickname} 对你说:${data.message}`)
})
},
methods: {
// 发送消息
handleSend () {
socket.emit('message', this.message)
},
handleNickname () {
socket.emit('nickname', this.nickname)
},
handlePrivateMessage () {
socket.emit('private-message', {
privateUser: this.privateUser,
privateMessage: this.privateMessage
})
}
}
})
</script>
</body>
</html>
// 后台
const express = require('express')
const http = require('http')
const app = express()
// 存储所有的客户端连接 socket
const clients = []
// 创建服务实例
const server = http.createServer(app)
// 在 HTTP 服务中集成 socket.io 用来提供 WebSocket 服务
const io = require('socket.io')(server)
// 通过 app 设置的都是 HTTP 资源请求处理
// 托管 public 目录中的静态资源
app.use(express.static('./public'))
// 通过 io 设置的都是 WebSocket 资源请求处理
io.on('connection', (socket) => {
// clients.push(socket)
console.log('a user connected')
// 当客户端断开连接后触发该事件
// socket.on('disconnect', () => {
// console.log('user disconnected')
// const index = clients.findIndex(c => c.socket === socket)
// if (index !== -1) {
// clients.splice(index, 1)
// }
// })
socket.on('nickname', nickname => {
console.log(nickname)
clients.push({
// 名字: 连接信息
nickname,
socket
})
socket.emit('nickname', '注册成功')
})
socket.emit('chat-count', clients.length)
socket.on('message', data => {
const client = clients.find(c => c.socket === socket)
// console.log(data)
// 广播给所有的聊天室客户端
io.emit('message', {
isPrivate: false,
nickname: client.nickname,
message: data
})
})
socket.on('private-message', data => {
console.log('private-message', data)
// 找到私聊用户,给它发送消息
const privateUser = clients.find(c => c.nickname === data.privateUser)
if (privateUser) {
console.log(privateUser)
privateUser.socket.emit('private-message', {
nickname: clients.find(c => c.socket === socket).nickname,
message: data.privateMessage
})
}
})
})
server.listen(3000, () => {
console.log(`Server is running at http://localhost:3000`)
})
后台管理项目总结:
- 用await 的实现方式让代码看起来可阅读性更好了
- loading 的关闭只用写一次了
el-upload 中上传限制部分代码 ```javascript beforeAvatarUpload (file: any) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < this.limit
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error(`上传头像图片大小不能超过 ${this.limit}MB!`)
}
return isJPG && isLt2M
},
```
- 阿里云上传
- 没什么难点,就是根据文档,进行API编写和调用
- 而且这个接口是后端实现的,前端需要按照后端的规则进行调用
- new FormData()
- FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过XMLHttpRequest.send() 方法发送出去。 —— MDN
- (this.$refs[‘menu-tree’] as Tree) 这中写法
- 在async 中请求没有先后顺序的数据
- const ret = await Promise.all([getAllResources(), getResourceCategories()])