Vue3.0聊天室|vue3+vant3仿微信聊天实例|vue3.x仿微信app界面
一、项目简介
基于Vue3.0+Vant3.x+Vuex4.x+Vue-router4+V3Popup等技术开发实现的仿微信手机App聊天实例项目Vue3-Chatroom。实现了发送图文表情消息/gif图、图片/视频预览、网址查看、下拉刷新功能、红包/朋友圈等功能。
二、技术选型
- 编辑器:VScode/Sublime
- 使用技术:Vue3.x+Vuex4.x+Vue-Router4
- UI组件库:Vant-UI3.x (有赞移动端Vue3组件库)
- 弹层组件:V3Popup(基于vue3.0封装自定义弹出层组件)
- iconfont图标:阿里字体图标库
- 自定义顶部导航栏+底部tabBar
◆ 项目结构
◆ Vue3自定义顶部Navbar+底部Tabbar
项目中顶部导航条和底部tabbar组件均是在之前vue2版的基础上开发的vue3版。
大家如果感兴趣,可以去看看之前的一篇分享文章。
https://www.cnblogs.com/xiaoyan2017/p/13791980.html
◆ Vue3自定义弹层组件
项目中使用到的弹框场景,均是最新开发的vue3.0自定义弹框组件v3popup来实现的。
v3popup 一款汇集多种弹框类型及动画效果的vue3.x自定义弹框组件。开发设计灵感来源于之前的vue2版,并在功能及效果上保持一致性。
如果大家对具体的实现感兴趣的话,可以去看看之前的这篇文章。
https://www.cnblogs.com/xiaoyan2017/p/14210820.html
◆ vue.config.js配置
/**
* Vue3基础配置文件
*/ const path = require('path') module.exports = {
// 基本路径
// publicPath: '/', // 输出文件目录
// outputDir: 'dist', // assetsDir: '', // 环境配置
devServer: {
// host: 'localhost',
// port: 8080,
// 是否开启https
https: false,
// 编译完是否打开网页
open: false, // 代理配置
// proxy: {
// '^/api': {
// target: '<url>',
// ws: true,
// changeOrigin: true
// },
// '^/foo': {
// target: '<other_url>'
// }
// }
}, // webpack配置
chainWebpack: config => {
// 配置路径别名
config.resolve.alias
.set('@', path.join(__dirname, 'src'))
.set('@assets', path.join(__dirname, 'src/assets'))
.set('@components', path.join(__dirname, 'src/components'))
.set('@views', path.join(__dirname, 'src/views'))
}
}
◆ Vue3.0主入口页面
在main.js中配置一些状态管理、地址路由,引入一些js和公共组件。
import { createApp } from 'vue'
import App from './App.vue' // 引入vuex和地址路由
import store from './store'
import router from './router' // 引入js
import '@assets/js/fontSize' // 引入公共组件
import Plugins from './plugins' const app = createApp(App) app.use(store)
app.use(router)
app.use(Plugins) app.mount('#app')
◆ Vuex + 表单登录验证
vue3中状态管理及表单验证操作。
import { createStore } from 'vuex' export default createStore({
state: {
user: localStorage.getItem('user') || null,
token: localStorage.getItem('token') || null
},
mutations: {
SET_USER(state, data) {
localStorage.setItem('user', data)
state.user = data
},
SET_TOKEN(state, data) {
localStorage.setItem('token', data)
state.token = data
},
LOGOUT(state) {
localStorage.removeItem('user')
localStorage.removeItem('token')
state.user = null
state.token = null
}
},
getters: {},
actions: {}
})
<script>
import { reactive, inject, getCurrentInstance } from 'vue'
export default {
components: {},
setup() {
const { ctx } = getCurrentInstance() const v3popup = inject('v3popup')
const utils = inject('utils')
const formObj = reactive({}) // ... const handleSubmit = () => {
if(!formObj.tel){
Snackbar('手机号不能为空!')
}else if(!utils.checkTel(formObj.tel)){
Snackbar('手机号格式不正确!')
}else if(!formObj.pwd){
Snackbar('密码不能为空!')
}else{
ctx.$store.commit('SET_TOKEN', utils.setToken());
ctx.$store.commit('SET_USER', formObj.tel); // ...
}
} return {
formObj,
handleSubmit
}
}
}
</script>
◆ 仿微信朋友圈透明导航实现
vue3通过在onMounted中监听scroll事件来控制顶部导航透明显示。
<!-- //朋友圈模板 -->
<template>
<div>
<header-bar :bgcolor="headerBg" transparent zIndex="1010">
<template #backIco><i class="iconfont icon-arrL"></i></template>
<template v-slot:right><div @click="isShowPublish=true"><i class="iconfont icon-tianjia"></i></div></template>
</header-bar> <div class="vui__scrollview flex1" ref="scrollview">
...
</div>
</div>
</template> <script>
import { onMounted, onBeforeUnmount, ref, reactive, toRefs, inject } from 'vue'
import { ImagePreview } from 'vant' export default {
components: {},
setup() {
const scrollview = ref(null) const data = reactive({
headerBg: 'transparent',
// ...
}) onMounted(() => {
scrollview.value.addEventListener('scroll', handleScroll)
}) onBeforeUnmount(() => {
scrollview.value.removeEventListener('scroll', handleScroll)
}) // 页面滚动处理
const handleScroll = (e) => {
if(e.target.scrollTop > 160) {
data.headerBg = 'linear-gradient(to right, #00d2ee, #00e077)'
}else {
data.headerBg = 'transparent';
}
} // ... return {
...toRefs(data),
scrollview, // ...
}
}
}
</script>
◆ Vue3聊天代码片段
vue3中实现聊天功能实现,其中编辑器支持图文插入,并且单独抽离了一个Editor.vue组件。
/**
* @Desc Vue3.0仿微信聊天实例
* @Time andy by 2021-01
* @About Q:282310962 wx:xy190310
*/
<script>
import { onMounted, onUnmounted, ref, reactive, toRefs, nextTick, inject } from 'vue'
import { useRouter } from 'vue-router'
import Editor from './editor.vue'
import { ImagePreview } from 'vant' // ... export default {
components: {
Editor
},
setup() {
const scrollview = ref(null)
const editorRef = ref(null)
const pickImageRef = ref(null)
const pickVideoRef = ref(null)
const playerRef = ref(null) const router = useRouter() const v3popup = inject('v3popup') const data = reactive({
editorText: '', isShowFootBar: false,
showFootBarIndex: 0, // 表情列表
emojList: emoJSON, // 消息记录
msgList: msgJSON, // 链接预览
isShowLinkView: false,
linkView: '', // ...
}) onMounted(() => {
nextTick(() => {
imgLoaded(scrollview)
})
}) onUnmounted(() => {
window.removeEventListener('popstate', handlePopStateClosed, false)
})
// 监听地址打开
const handlePopStateOpen = () => {
if(window.history && window.history.pushState) {
history.pushState(null, null, document.URL)
window.addEventListener('popstate', handlePopStateClosed, false)
}
}
// 监听地址关闭(手机回退按钮事件)
const handlePopStateClosed = () => {
// console.log('监听关闭视频事件!')
data.isShowLinkView = false
data.isShowVideoPlayer = false
} /**
* 滚动条到底部
* @param ref 容器ref
*/
const scrollBottom = (ref) => {
let viewport = ref.value
if(viewport) {
viewport.scrollTop = viewport.scrollHeight
}
} // 点击聊天消息区域
const handleMsgPanelClicked = () => {
if(!data.isShowFootBar) return
data.isShowFootBar = false
} /**
* 表情|选择区切换
* @param index 切换索引
*/
const handleEmojChooseView = (index) => {
data.isShowFootBar = true
data.showFootBarIndex = index nextTick(() => { imgLoaded(scrollview) })
} /**
* 表情Tab切换
* @param index 索引index
*/
const handleEmojTab = (index) => {
let emojLs = data.emojList
for(var i = 0, len = emojLs.length; i < len; i++) {
emojLs[i].selected = false
}
emojLs[index].selected = true
data.emojList = emojLs
} /* ---------- { 编辑器|表情模块 } ---------- */
// 点击编辑器
const handleEditorClick = () => {
// console.log('点击编辑器')
data.isShowFootBar = false
} // 编辑器获取焦点
const handleEditorFocus = () => {
// console.log('编辑器获取焦点')
} // 编辑器失去焦点
const handleEditorBlur = () => {
// console.log('编辑器失去焦点')
} // 判断编辑器是否为空
const isEmpty = (html) => {
html = html.replace(/<br[\s/]{0,2}>/ig, "\r\n")
html = html.replace(/<[^img].*?>/ig, "")
html = html.replace(/ /ig, "")
return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == ""
}
// 匹配转换聊天消息中链接
const transferHTML = (html) => {
let reg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g
return html.replace(reg, "<a href='$1$2'>$1$2</a>")
} // ... /* ---------- { 选择功能模块 } ---------- */
// 选择图片
const handleChooseImage = () => {
let msgLs = data.msgList
let len = msgLs.length
// 消息队列
let arrLS = {
// ...
} let file = pickImageRef.value.files[0]
if(!file) return
let size = Math.floor(file.size / 1024)
if(size > 2*1024) {
v3popup({content: '请选择2MB以内的图片!'})
return false
}
var reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function() {
let img = this.result // ...
}
} // 预览图片
const handleImgPreview = (src) => {
ImagePreview({
images: [
src
],
showIndex: false,
showIndicators: true,
closeable: true,
});
} /* ---------- { 视频功能模块 } ---------- */
// 播放视频
const handleVideoPlayed = (item) => {
data.isShowVideoPlayer = true
data.videoList = item nextTick(() => {
playerRef.value.play()
}) // 监听手机回退按钮事件
handlePopStateOpen()
} // 抖一抖
const handleShakeWin = () => {
let ntbox = document.querySelector('.vui__container')
ntbox.classList.add('shake')
setTimeout(() => {
ntbox.classList.remove('shake')
}, 1000);
} // ... return {
...toRefs(data), scrollview,
editorRef,
pickImageRef,
pickVideoRef,
playerRef, handleMsgPanelClicked,
handleMsgClicked, // ...
}
}
}
</script>
okey,以上就是基于vue3开发仿微信界面聊天室的介绍。希望大家能喜欢~~
最后附上一个Electron+Vue聊天实例
https://www.cnblogs.com/xiaoyan2017/p/12169391.html
Vue3.0聊天室|vue3+vant3仿微信聊天实例|vue3.x仿微信app界面的更多相关文章
- Websocket直播间聊天室教程 - GoEasy快速实现聊天室
最近两年直播那个火啊,真的是无法形容!经常有朋友问起,我想实现一个直播间聊天或者我想开发一个聊天室, 要如何开始呢? 今天小编就手把手的教你用GoEasy做一个聊天室,当然也可以用于直播间内的互动.全 ...
- Vue3.0工程创建 && setup、ref、reactive函数 && Vue3.0响应式实现原理
1 # 一.创建Vue3.0工程 2 # 1.使用vue-cli创建 3 # 官方文档: https://cli.vuejs.org/zh/guide/creating-a-project.html# ...
- 基于nodejs+webSocket的聊天室(实现:加入聊天室、退出聊天室、在线人数、在线列表、发送信息、接收信息)
1 安装 socket.io模块 npm install "socket.io": "latest" 2 app.js相关 ws = require('soc ...
- ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(二) 实现聊天室连接
上一篇已经简单介绍了layim WebUI即时通讯组件和获取数据的后台方法.现在要讨论的是SingalR的内容,之前都是直接贴代码.那么在贴代码之前先分析一下业务模型,顺便简单讲一下SingalR里的 ...
- Netty学习笔记(六) 简单的聊天室功能之WebSocket客户端开发实例
在之前的Netty相关学习笔记中,学习了如何去实现聊天室的服务段,这里我们来实现聊天室的客户端,聊天室的客户端使用的是Html5和WebSocket实现,下面我们继续学习. 创建客户端 接着第五个笔记 ...
- Vue3实战系列:Vue3.0 + Vant3.0 搭建种子项目
最近在用 Vue3 写一个开源的商城项目,开源后让大家也可以用现成的 Vue3 大型商城项目源码来练练手,目前处于开发阶段,过程中用到了 Vant3.0,于是就整理了这篇文章来讲一下如何使用 Vue3 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。
上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。
前言 上一篇讲解了如何自定义右键菜单,都是前端的内容,本篇内容就一个:查询.聊天历史纪录查询,在之前介绍查找好友的那篇博客里已经提到过 Elasticsearch,今天它又要上场了.对于Elastic ...
- 利用Node.js的Net模块实现一个命令行多人聊天室
1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...
- 使用WebRTC搭建前端视频聊天室——信令篇
博客原文地址 建议看这篇之前先看一下使用WebRTC搭建前端视频聊天室——入门篇 如果需要搭建实例的话可以参照SkyRTC-demo:github地址 其中使用了两个库:SkyRTC(github地址 ...
随机推荐
- 第14.4节 使用IE浏览器获取网站访问的http信息
上节<第14.3节 使用google浏览器获取网站访问的http信息>中介绍了使用Google浏览器怎么获取网站访问的http相关报文信息,本节介绍IE浏览器中怎么获取相关信息.以上节为基 ...
- 从零开始的pickle反序列化学习
前言 在XCTF高校战疫之中,我看到了一道pickle反序列化的题目,但因为太菜了花了好久才做出来,最近正好在学flask,直接配合pickle学一下. 找了半天终于找到一个大佬,这里就结合大佬的文章 ...
- Scrum 冲刺第七天
一.每日站立式会议 1.会议内容 1)进行每日工作汇报 张博愉: 昨天已完成的工作:与林梓琦同学完成发帖模块的交接 今日工作计划:完善发帖模块的点赞.上传图片功能 工作中遇到的困难:Mybatis的一 ...
- starsWidth 和endWidth ie不兼容方案
if (typeof String.prototype.startsWith != 'function') { String.prototype.startsWith = function (pref ...
- 题解-The Number of Good Intervals
题面 The Number of Good Intervals 给定 \(n\) 和 \(a_i(1\le i\le n)\),\(m\) 和 \(b_j(1\le j\le m)\),求对于每个 \ ...
- hiveSQL和MySQL区别
1.hive支持按行分割,按字段分割,如按','分割: lateral view explode(split( , ',')) 2.hive不支持等值连接,即不支持where a.id = b.id的 ...
- JS怎么把for循环出来的东西放到一个数组里
var students=[ {name: "vehicleTravelLicenseCopyBack", id: "a1"}, {name: "ve ...
- idea的下载与安装
1.下载idea.到idea的官网选择你需要下载的,你最喜欢的版本https://www.jetbrains.com/idea/download/ 2.下载jdk.进入Oracle官网,鼠标指在Dow ...
- Java中instanceof注意的地方
instanceof只能用于对象的判断,不能用于基本类型的判断,以下代码会编译不通过 'A' instanceof Character instanceof特有的规则:若左操作数是null,结果就直接 ...
- 属于同一网段的ip是不是就在同一个局域网?
参考文章链接: https://zhidao.baidu.com/question/350887200.html?qbl=relate_question_0&word=%D4%DA%D2%BB ...