uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践

马肤
摘要:uniapp-vue3-wechat是一个基于uniapp和vue3技术开发的仿微信聊天app实例。该实例支持H5、小程序和App端,实现了聊天功能并具备良好的用户体验。通过该实例,开发者可以学习到uniapp和vue3在移动应用开发中的应用,以及如何实现跨平台的开发。

uni-vue3-wchat:基于uni-app+vue3+pinia2高仿微信app聊天模板。

原创基于最新跨端技术uni-app+vue3.x+pinia2+vite4+uv-ui构建三端仿微信app界面聊天实例。实现编辑框多行消息/emoj混合、长按触摸式仿微信语音面板、图片/视频预览、红包/朋友圈等功能。支持编译到H5+小程序端+App端。

uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第1张

整个项目采用vue3 setup语法编码,支持编译到h5+小程序端+APP端。

uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第2张

使用技术

  • 编辑器:HbuilderX 4.0.8
  • 框架技术:Uniapp+Vue3+Pinia2+Vite4.x
  • 组件库:uni-ui+uv-ui
  • 弹窗组件:uv3-popup(uniapp+vue3多端自定义弹框组件)
  • 导航栏+菜单栏:uv3-navbar+uv3-tabbar组件
  • 本地缓存:pinia-plugin-unistorage
  • 编译支持:H5+小程序+APP端

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第3张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第4张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第5张

    uniapp+vue3实现类似微信朋友圈功能。

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第6张

    项目结构

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第7张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第8张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第9张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第10张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第11张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第12张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第13张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第14张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第15张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第16张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第17张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第18张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第19张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第20张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第21张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第22张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第23张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第24张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第25张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第26张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第27张

    入口main.js配置

    /**
     * 入口文件 main.js
    */
    import { createSSRApp } from 'vue'
    import App from './App'
    // 引入pinia状态管理
    import pinia from '@/pinia'
    export function createApp() {
    	const app = createSSRApp(App)
    	app.use(pinia)
    	return {
    		app,
    		pinia
    	}
    }
    

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第28张

    App.vue配置

    采用 vue3 setup 语法开发。

        import { provide } from 'vue'
        import { onLaunch, onShow, onHide, onPageNotFound } from '@dcloudio/uni-app'
        
        onLaunch(() => {
            console.log('App Launch')
            
            uni.hideTabBar()
            loadSystemInfo()
        })
        
        onShow(() => {
            console.log('App Show')
        })
        
        onHide(() => {
            console.log('App Hide')
        })
        
        onPageNotFound((e) => {
            console.warn('Route Error:', `${e.path}`)
        })
        
        // 获取系统设备信息
        const loadSystemInfo = () => {
            uni.getSystemInfo({
                success: (e) => {
                    // 获取手机状态栏高度
                    let statusBar = e.statusBarHeight
                    let customBar
                    
                    // #ifndef MP
                    customBar = statusBar + (e.platform == 'android' ? 50 : 45)
                    // #endif
                    
                    // #ifdef MP-WEIXIN
                    // 获取胶囊按钮的布局位置信息
                    let menu = wx.getMenuButtonBoundingClientRect()
                    // 导航栏高度 = 胶囊下距离 + 胶囊上距离 - 状态栏高度
                    customBar = menu.bottom + menu.top - statusBar
                    // #endif
                    
                    // #ifdef MP-ALIPAY
                    customBar = statusBar + e.titleBarHeight
                    // #endif
                    
                    // 由于globalData在vue3 setup存在兼容性问题,改为provide/inject替代方案
                    provide('globalData', {
                        statusBarH: statusBar,
                        customBarH: customBar,
                        screenWidth: e.screenWidth,
                        screenHeight: e.screenHeight,
                        platform: e.platform
                    })
                }
            })
        }
    
    
        /* #ifndef APP-NVUE */
        @import 'static/fonts/iconfont.css';
        /* #endif */
    
    
        @import 'styles/reset.scss';
        @import 'styles/layout.scss';
    
    

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第29张

    uniapp+vue3自定义navbar+tabbar组件

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第30张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第31张

    
        
        首页
        
             Admin
        
        
            
            
        
    
    

    公共布局模板

    整体项目结构采用顶部导航区域+主体内容区+底部区域。

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第32张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第33张

    
    
        export default {
            /**
             * 解决小程序class、id透传问题
             * manifest.json中配置mergeVirtualHostAttributes: true, 在微信小程序平台不生效,组件外部传入的class没有挂到组件根节点上,在组件中增加options: { virtualHost: true }
             * https://github.com/dcloudio/uni-ui/issues/753
             */
            options: { virtualHost: true }
        }
    
    
    
        const props = defineProps({
            // 是否显示自定义tabbar
            showTabBar: { type: [Boolean, String], default: false },
        })
    
    
        
            
            
            
            
            
                
            
            
            
            
            
            
            
        
    
    

    uni-app+vue3微信九宫格图像组

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第34张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第35张

        import { onMounted, ref, computed, watch, getCurrentInstance } from 'vue'
        
        const props = defineProps({
            // 图像组
            avatar: { type: Array, default: null },
        })
        
        const instance = getCurrentInstance()
        
        const uuid = computed(() => Math.floor(Math.random() * 10000))
        const avatarPainterId = ref('canvasid' + uuid.value)
        
        const createAvatar = () => {
            const ctx = uni.createCanvasContext(avatarPainterId.value, instance)
            // 计算图像在画布上的坐标
            const avatarSize = 12
            const gap = 2
            for(let i = 0, len = props.avatar.length; i  {
                // 输出临时图片
                /* uni.canvasToTempFilePath({
                    canvasId: avatarPainterId.value,
                    success: (res) => {
                        console.log(res.tempFilePath)
                    }
                }) */
            })
        }
        
        onMounted(() => {
            createAvatar()
        })
        
        watch(() => props.avatar, () => {
            createAvatar()
        })
    
    
        
            
                
            
        
        
            
        
    
    
        .uv3__avatarPainter {background-color: #eee; border-radius: 5px; overflow: hidden; padding: 2px; height: 44px; width: 44px;}
        .uv3__avatarPainter-canvas {height: 100%; width: 100%;}
        .uv3__avatarOne {border-radius: 5px; height: 44px; width: 44px;}
    
    

    uni-app+vue3自定义弹出框组件

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第36张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第37张

    v-model        当前组件是否显示
    title          标题(支持富文本div标签、自定义插槽内容)
    content        内容(支持富文本div标签、自定义插槽内容)
    type           弹窗类型(toast | footer | actionsheet | actionsheetPicker | android/ios)
    customStyle    自定义弹窗样式
    icon           toast图标(loading | success | fail | warn | info)
    shade          是否显示遮罩层
    shadeClose     是否点击遮罩时关闭弹窗
    opacity        遮罩层透明度
    round          是否显示圆角
    xclose         是否显示关闭图标
    xposition      关闭图标位置(left | right | top | bottom)
    xcolor         关闭图标颜色
    anim           弹窗动画(scaleIn | fadeIn | footer | fadeInUp | fadeInDown)
    position       弹出位置(top | right | bottom | left)
    follow         长按/右键弹窗(坐标点)
    time           弹窗自动关闭秒数(1、2、3)
    zIndex         弹窗层叠(默认202107)
    btns           弹窗按钮(参数:text|style|disabled|click)
    ------------------------------------------
    ## slot [插槽]
    
    
    ------------------------------------------
    ## emit
    open        打开弹出层时触发(@open="xxx")
    close       关闭弹出层时触发(@close="xxx")
    

    uv3-popup支持函数式+组件式两种调用方式。

        import { onMounted, ref, computed, watch, nextTick, getCurrentInstance } from 'vue'
        
        const props = defineProps({
            ...
        })
        const emit = defineEmits([
            'update:modelValue',
            'open',
            'close'
        ])
        
        const instance = getCurrentInstance()
        
        const opts = ref({
            ...props
        })
        const visible = ref(false)
        const closeAnim = ref(false)
        const stopTimer = ref(null)
        const oIndex = ref(props.zIndex)
        const uuid = computed(() => Math.floor(Math.random() * 10000))
        
        const positionStyle = ref({ position: 'absolute', left: '-999px', top: '-999px' })
        
        const toastIcon = {
            ...
        }
        
        // 打开弹框
        const open = (options) => {
            if(visible.value) return
            opts.value = Object.assign({}, props, options)
            // console.log('-=-=混入参数:', opts.value)
            visible.value = true
            
            // nvue 的各组件在安卓端默认是透明的,如果不设置background-color,可能会导致出现重影的问题
            // #ifdef APP-NVUE
            if(opts.value.customStyle && !opts.value.customStyle['background'] && !opts.value.customStyle['background-color']) {
                opts.value.customStyle['background'] = '#fff'
            }
            // #endif
            
            let _index = ++index
            oIndex.value = _index + parseInt(opts.value.zIndex)
            
            emit('open')
            typeof opts.value.onOpen === 'function' && opts.value.onOpen()
            
            // 长按处理
            if(opts.value.follow) {
                nextTick(() => {
                    let winW = uni.getSystemInfoSync().windowWidth
                    let winH = uni.getSystemInfoSync().windowHeight
                    // console.log('坐标点信息:', opts.value.follow)
                    getDom(uuid.value).then(res => {
                        // console.log('Dom尺寸信息:', res)
                        if(!res) return
                        
                        let pos = getPos(opts.value.follow[0], opts.value.follow[1], res.width+15, res.height+15, winW, winH)
                        positionStyle.value.left = pos[0] + 'px'
                        positionStyle.value.top = pos[1] + 'px'
                    })
                })
            }
            
            if(opts.value.time) {
                if(stopTimer.value) clearTimeout(stopTimer.value)
                stopTimer.value = setTimeout(() => {
                    close()
                }, parseInt(opts.value.time) * 1000)
            }
        }
        
        // 关闭弹框
        const close = () => {
            if(!visible.value) return
            
            closeAnim.value = true
            setTimeout(() => {
                visible.value = false
                closeAnim.value = false
                
                emit('update:modelValue', false)
                emit('close')
                typeof opts.value.onClose === 'function' && opts.value.onClose()
                
                positionStyle.value.left = '-999px'
                positionStyle.value.top = '-999px'
                
                stopTimer.value && clearTimeout(stopTimer.value)
            }, 200)
        }
        
        // 点击遮罩层
        const handleShadeClick = () => {
            if(JSON.parse(opts.value.shadeClose)) {
                close()
            }
        }
        
        // 按钮事件
        const handleBtnClick = (e, index) => {
            let btn = opts.value.btns[index]
            if(!btn?.disabled) {
                console.log('按钮事件类型:', typeof btn.click)
                
                typeof btn.click === 'function' && btn.click(e)
            }
        }
        
        // 获取dom宽高
        const getDom = (id) => {
            return new Promise((resolve, inject) => {
                // uniapp vue3中 uni.createSelectorQuery().in(this) 会报错__route__未定义  https://ask.dcloud.net.cn/question/140192
                uni.createSelectorQuery().in(instance).select('#uapopup-' + id).fields({
                    size: true,
                }, data => {
                    resolve(data)
                }).exec()
            })
        }
        
        // 自适应坐标点
        const getPos = (x, y, ow, oh, winW, winH) => {
            let l = (x + ow) > winW ? x - ow : x
            let t = (y + oh) > winH ? y - oh : y
            return [l, t]
        }
        
        onMounted(() => {
            if(props.modelValue) {
                open()
            }
        })
        watch(() => props.modelValue, (val) => {
            // console.log(val)
            if(val) {
                open()
            }else {
                close()
            }
        })
        
        defineExpose({
            open,
            close
        })
    
    

    uni-app+vue3聊天功能

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第38张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第39张

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第40张

    目前该插件已经免费发布到插件市场,欢迎去下载使用。

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第41张

    https://ext.dcloud.net.cn/plugin?id=13275

    uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第42张

    
        
            
            
                
                
                
                
                    
                    
                
            
            
            
            
                
                未识别到文字
                
                
                    取消
                    发送原语音
                    
                
            
            
            
            
                
            
            
            {{voiceTypeMap[voiceType]}}
            
            
        
    
    

    目前该项目已经同步到工房,如果有需要,欢迎自行去拍哈~

    https://gf.bilibili.com/item/detail/1105801011

    好了,综上就是uniapp+vue3跨端聊天实例的一些分享,希望大家能喜欢!

    最后附上几个最新实战项目

    • flutter3-winchat基于flutter3.x+bitsdojo_window桌面端仿微信

      https://blog.csdn.net/yanxinyun1990/article/details/136410049

    • flutter3_douyin基于flutter3.19仿抖音短视频/直播

      https://blog.csdn.net/yanxinyun1990/article/details/136996521

    • flutter3_macos基于flutter3.x+window_manager桌面端仿macOS系统

      https://blog.csdn.net/yanxinyun1990/article/details/137697164

      uniapp-vue3-wechat,基于uniapp+vue3仿微信app聊天实例(H5+小程序+App端),uniapp-vue3仿微信聊天实例,跨平台H5、小程序与App端的实践 第43张


0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码