2021已来临,Vue3开发也要步入正轨了。今天为大家带来的是全新开发的Vue3.x实战聊天室项目Vue3_Chatroom,基于vue3+vant3+vuex+vue-router+v3popup
等技术搭建的聊天实例。
vue3chat支持发送图文消息、图片/视频预览、网址链接查看、红包/朋友圈
等功能。
项目中所有的页面及逻辑部分源码均是使用最新的Vue3.0语法
编写。
顶部headerBar和底部tabBar组件,均是自定义组件实现,在原先vue2基础上演变而来。
由于之前有过一篇分享文章,这里就不详细介绍了。
vue3chat中用到的弹框场景,都是最新开发的vue3.0自定义弹框V3Popup组件实现。
v3popup
一款基于vue3.x构建的移动端弹框组件,拥有多种弹框类型及流畅动画效果。
如果感兴趣,可以去看看这篇文章。
vue3.0系列之自定义手机端弹框组件|vue3全局弹层组件v3popup
项目中的一些路径别名alias
配置,避免过多的../../
路径。
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'))
}
}
在main.js页面引入公共组件/样式,路由及vuex状态管理。
import { createApp } from 'vue'
import App from './App.vue'
// 引入vuex和router配置
import store from './store'
import router from './router'
import '@assets/js/fontSize'
// 引入公共组件
import Plugins from './plugins'
const app = createApp(App)
app.use(store)
app.use(router)
app.use(Plugins)
app.mount('#app')
vue3中实现登录/注册表单操作验证。用到了reactive
响应式函数和getCurrentInstance
获取上下文this。
<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>
聊天编辑器部分采用抽离公共组件方式,支持图文混排、光标处插入emoj等功能。
<!-- //Vue3.0可编辑contenteditable功能 -->
<template>
<div
ref="editorRef"
class="editor"
contentEditable="true"
v-html="editorText"
@click="handleClick"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur"
style="user-select:text;-webkit-user-select:text;">
</div>
</template>
是基于div的可编辑属性contenteditable实现。
const handleInput = () => {
emit('update:modelValue', editorRef.value.innerHTML)
data.lastCursor = getLastCursor()
}
// 删除内容
const handleDel = () => {
let range
let sel = window.getSelection()
if(data.lastCursor) {
sel.removeAllRanges()
sel.addRange(data.lastCursor)
}
range = getLastCursor()
range.collapse(false)
document.execCommand('delete')
// 删除表情时禁止输入法
nextTick(() => {
setTimeout(() => { editorRef.value.blur() }, 0);
})
}
// 清空编辑器
const handleClear = () => {
editorRef.value.innerHTML = ''
}
/**
* @Desc vue3图文混排编辑器
* @Time andy by 2021-01
* @About Q:282310962 wx:xy190310
*/
<script>
import { ref, reactive, toRefs, watch, nextTick } from 'vue'
export default {
props: {
modelValue: { type: String, default: '' }
},
setup(props, { emit }) {
const editorRef = ref(null)
const data = reactive({
editorText: props.modelValue,
isChange: true,
lastCursor: null,
})
// ...
// 获取光标最后位置
const getLastCursor = () => {
let sel = window.getSelection()
if(sel && sel.rangeCount > 0) {
return sel.getRangeAt(0)
}
}
// 光标处插入内容 @param html 需要插入的内容
const insertHtmlAtCursor = (html) => {
let sel, range
if(window.getSelection) {
// IE9及其它浏览器
sel = window.getSelection()
// ##注意:判断最后光标位置
if(data.lastCursor) {
sel.removeAllRanges()
sel.addRange(data.lastCursor)
}
if(sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0)
let el = document.createElement('div')
el.appendChild(html)
var frag = document.createDocumentFragment(), node, lastNode
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node)
}
range.insertNode(frag)
if(lastNode) {
range = range.cloneRange()
range.setStartAfter(lastNode)
range.collapse(true)
sel.removeAllRanges()
sel.addRange(range)
}
}
} else if(document.selection && document.selection.type != 'Control') {
// IE < 9
document.selection.createRange().pasteHTML(html)
}
// ...
}
return {
...toRefs(data),
editorRef,
handleInput,
handleDel,
// ...
}
}
}
</script>
好了,基于vue3开发聊天项目,暂时就介绍到这里。后续还会分享一些Vue3.x实战案例。感谢大家的支持! 💪🏻
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。