文章目录
前言一、直接使用二、步骤1.需要的东西2.后端代码引入一些初始化视图函数首页聊天退出登录前段代码indexchat用户连接、断开连接发送信息总结前言
我是一个大一的学生,参加学校工作室的考核,学习了一点flask的相关知识,这个聊天室只有两个页面,前段用的也是简单的js原生代码进行的一些dom操作
一、直接使用
想直接跑的可以自取
/cgynb/a-flask-project/tree/chat
首先你需要配置一个虚拟环境,并且激活,不会的话,可以百度谷歌必应[doge]
然后安装第三方库
pip install -r package.txt
在命令行输入
python app.py
二、步骤
1.需要的东西
materialize网页框架flaskflask-socketio2.后端代码
引入
引入flask的一些东西,然后引入flask-socketio的SocketIO
from flask import Flask, render_template, request, session, redirect, url_forfrom flask_socketio import SocketIOapp = Flask(__name__)app.config['SECRET_KEY'] = 'jjj'socketio = SocketIO()socketio.init_app(app)
一些初始化
设置秘钥,然后给SocketIO绑定app
app = Flask(__name__)app.config['SECRET_KEY'] = 'jjj'socketio = SocketIO()socketio.init_app(app)
视图函数
三个视图函数,首页,聊天,退出
首页
如果是get访问的话,判断会话中是否有’username’,如果有重定向到聊天界面,如果没有,则渲染首页
用post访问的话,获取表单,设置会话,然后重定向到聊天界面
@app.route('/', methods=['GET', 'POST'])def index():if request.method == 'GET':if 'username' in session:return redirect(url_for('chat'))return render_template('index.html')else:username = request.form.get('username')session['username'] = usernamereturn redirect(url_for('chat'))
聊天
判断会话中是否有’username’,如果与渲染聊天界面,并传入username,如果没有,重定向到首页
@app.route('/chat/')def chat():if 'username' in session:username = session['username']return render_template('chat.html', username=username)else:return redirect(url_for('index'))
退出登录
退出登录,就是删除会话
@app.route('/logout/')def logout():if 'username' in session:session.clear()return redirect(url_for('index'))
前段代码
页面效果不是重点,可以看看materialize的文档,简单看看就可以做到初步上手了,也可以到置顶的github仓库下载
主要是js的代码,即对于socketio的使用
index
这边的用的计时器方法的目的是,让用户输入昵称,如果不输入,按钮是不可点击的,所以每0.3秒判断一次
让按钮不可点击,是通过materialize的一个类disabled来控制的,所以添加或者删除类即可
let inp = document.querySelector('#icon_prefix');let btn = document.querySelector('#submit');setInterval(function () {if(inp.value){btn.classList.remove('disabled');}else{if(!btn.classList.contains('disabled')){btn.classList.add('disabled');}}}, 300);
chat
这边从用户连接,发送信息来讲
用户连接、断开连接
let socket= io();socket.connect(location.protocol + '//' + document.domain + ':' + location.port);
取消连接,即关闭浏览器等,不用再来定义,如果想进行操作触发,可以用socket.disconnect()绑定事件
那么服务器怎么知道客户端连接上了呢?
所以在python代码中 我们要写监听函数
# 连接@socketio.on('connect')def handle_connect():username = session.get('username')print('*' * 20, f'{username} connect', '*' * 20)socketio.emit('connect info', f'{username} connect')
这三行代码,1.从会话中得到昵称,2.打印连接信息,3.发送一个字符串到’connect info’,这个在前段会被接收,然后在页面上显示,之后会有提及
# 断开连接@socketio.on('disconnect')def handle_disconnect():username = session.get('username')print('*' * 20, f'{username} disconnect', '*' * 20)socketio.emit('connect info', f'{username} disconnect')
断开连接跟连接是基本一致的
在前端的接收连接信息的监听函数如下,参数data就是传入的那个字符串,然后传建一个div元素,命名为connectInfo,在这个div中插入msg这段html,最后在聊天的区域(命名为messageBox)加入connectInfo
// 连接的信息socket.on('connect info', function (data) {console.log(data)let connectInfo = document.createElement('div')connectInfo.className = 'row'let msg = `<div class="col s4 offset-s4"><div class="connect-info grey lighten-4 center" ><span class="black-text">${data}</span></div></div>`connectInfo.innerHTML = msgmessageBox.appendChild(connectInfo)})
这样在前端的效果就是
发送信息
给发送按钮绑定点击事件,获取到输入框中的信息,获取用户名,然后删除输入框的信息,最后用socket.emit()发送json数据(数据中有用户昵称,信息内容)到服务器,如果获取到输入框的信息是空,则弹出框
// 发送消息sendMsgBtn.onclick = function () {let msg = inp.valuelet user = document.querySelector('#username').innerHTMLinp.value = ''if(msg){socket.emit('send msg', {user: user,message: msg})}else {alert('消息不能为空')}}
这边有一个优化使用的操作,就是给回车按键绑定点击事件
// 回车发送消息inp.addEventListener("keyup", function(event) {event.preventDefault();if (event.keyCode === 13) {sendMsgBtn.click();}});
服务器接收发送的消息,data就是前端发送过来的json数据,然后使用socket.emit()发送到前段
@socketio.on('send msg')def handle_message(data):print('sendMsg' + str(data))socketio.emit('send msg', data)
前段接收服务器发送来的信息
插入聊天信息操作跟上面接收连接信息是基本一致的,这里面有加一个判断,即信息是否是自己发送的
// 接受消息socket.on('send msg', function (data) {console.log(data)let msg = nulllet msgbox = document.createElement('div')msgbox.className = 'row'if (data.user === document.querySelector('#username').innerHTML) {msg = `<div class="col right"><div class="tag teal z-depth-3" ><span class="white-text">${data.message}</span></div></div>`} else {msg = `<div class="col"><div class="tag z-depth-3"><span class="teal-text"><b>${data.user}</b>: ${data.message}</span></div></div>`}msgbox.innerHTML = msgmessageBox.appendChild(msgbox)})