Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >uniapp-vue3-wechat聊天实例|uni-app+pinia2仿微信app

uniapp-vue3-wechat聊天实例|uni-app+pinia2仿微信app

原创
作者头像
andy2018
修改于 2024-05-22 04:07:23
修改于 2024-05-22 04:07:23
6770
举报

Uniapp_Vue3_Chat基于uni-app+vue3+pinia2+uv-ui跨三端(h5+小程序+APP端)仿微信聊天。

uni-vue3-wchat项目采用vue3 setup语法编码,支持编译到H5+小程序+App端

技术栈

  • 编辑器: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端

项目结构目录

main.js配置

代码语言:typescript
AI代码解释
复制
/**
 * 入口文件 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
    }
}

入口模板App.vue采用vue3 setup语法编码。

代码语言:typescript
AI代码解释
复制
<script 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
                })
            }
        })
    }
</script>

<style>
    /* #ifndef APP-NVUE */
    @import 'static/fonts/iconfont.css';
    /* #endif */
</style>
<style lang="scss">
    @import 'styles/reset.scss';
    @import 'styles/layout.scss';
</style>

公共布局模板

项目结构采用顶部导航+主体内容区+底部区域三个模块。

代码语言:typescript
AI代码解释
复制
<!-- 公共布局模板 -->

<!-- #ifdef MP-WEIXIN -->
<script>
    export default {
        /**
         * 解决小程序class、id透传问题
         * manifest.json中配置mergeVirtualHostAttributes: true, 在微信小程序平台不生效,组件外部传入的class没有挂到组件根节点上,在组件中增加options: { virtualHost: true }
         * https://github.com/dcloudio/uni-ui/issues/753
         */
        options: { virtualHost: true }
    }
</script>
<!-- #endif -->

<script setup>
    const props = defineProps({
        // 是否显示自定义tabbar
        showTabBar: { type: [Boolean, String], default: false },
    })
</script>

<template>
    <view class="uv3__container flexbox flex-col flex1">
        <!-- 顶部插槽 -->
        <slot name="header" />
        
        <!-- 内容区 -->
        <view class="uv3__scrollview flex1">
            <slot />
        </view>
        
        <!-- 底部插槽 -->
        <slot name="footer" />
        
        <!-- tabbar栏 -->
        <uv3-tabbar v-if="showTabBar" hideTabBar fixed />
    </view>
</template>

uni-app+vue3实现九宫格图像

代码语言:typescript
AI代码解释
复制
<script setup>
    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 < len; i++) {
            const row = Math.floor(i / 3)
            const col = i % 3
            const x = col * (avatarSize + gap)
            const y = row * (avatarSize + gap)
            
            ctx.drawImage(props.avatar[i], x, y, avatarSize, avatarSize)
        }
        ctx.draw(false, () => {
            // 输出临时图片
            /* uni.canvasToTempFilePath({
                canvasId: avatarPainterId.value,
                success: (res) => {
                    console.log(res.tempFilePath)
                }
            }) */
        })
    }
    
    onMounted(() => {
        createAvatar()
    })
    
    watch(() => props.avatar, () => {
        createAvatar()
    })
</script>

<template>
    <template v-if="avatar.length > 1">
        <view class="uv3__avatarPainter">
            <canvas :canvas-id="avatarPainterId" class="uv3__avatarPainter-canvas"></canvas>
        </view>
    </template>
    <template v-else>
        <image class="uv3__avatarOne" :src="avatar[0]" />
    </template>
</template>

<style lang="scss" scoped>
    .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;}
</style>

uniapp+vue3自定义顶部导航+底部菜单栏

代码语言:typescript
AI代码解释
复制
<uv3-navbar :back="true" title="标题内容" bgcolor="#07c160" color="#fff" fixed zIndex="1010" />

<uv3-navbar custom bgcolor="linear-gradient(to right, #07c160, #0000ff)" color="#fff" center transparent zIndex="2024">
    <template #back><uni-icons type="close" /></template>
    <template #backText><text>首页</text></template>
    <template #title>
        <image src="/static/logo.jpg" style="height:20px;width:20px;" /> Admin
    </template>
    <template #right>
        <view class="ml-20" @click="handleAdd"><text class="iconfont icon-tianjia"></text></view>
        <view class="ml-20"><text class="iconfont icon-msg"></text></view>
    </template>
</uv3-navbar>

uniapp+vue3聊天功能

目前该增强版输入框已经免费发布到插件市场,有需要的可以去下载使用。

代码语言:typescript
AI代码解释
复制
<!-- 按住说话模板 -->
<view v-if="voicePanelEnable" class="uv3__voicepanel-popup">
    <view class="uv3__voicepanel-body flexbox flex-col">
        <!-- 取消发送+语音转文字 -->
        <view v-if="!voiceToTransfer" class="uv3__voicepanel-transfer">
            <!-- 提示动效 -->
            <view class="animtips flexbox" :class="voiceType == 2 ? 'left' : voiceType == 3 ? 'right' : null"><Waves :lines="[2, 3].includes(voiceType) ? 10 : 20" /></view>
            <!-- 操作项 -->
            <view class="icobtns flexbox">
                <view class="vbtn cancel flexbox flex-col" :class="{'hover': voiceType == 2}" @click="handleVoiceCancel"><text class="vicon uv3-icon uv3-icon-close"></text></view>
                <view class="vbtn word flexbox flex-col" :class="{'hover': voiceType == 3}"><text class="vicon uv3-icon uv3-icon-word"></text></view>
            </view>
        </view>
        
        <!-- 语音转文字 -->
        <view v-if="voiceToTransfer" class="uv3__voicepanel-transfer result fail">
            <!-- 提示动效 -->
            <view class="animtips flexbox"><uni-icons type="info-filled" color="#fff" size="20"></uni-icons><text class="c-fff">未识别到文字</text></view>
            <view class="icobtns flexbox">
                <view class="vbtn cancel flexbox flex-col" @click="handleVoiceCancel"><text class="vicon uv3-icon uv3-icon-chexiao"></text>取消</view>
                <view class="vbtn word flexbox flex-col"><text class="vicon uv3-icon uv3-icon-audio"></text>发送原语音</view>
                <view class="vbtn check flexbox flex-col"><text class="vicon uv3-icon uv3-icon-duigou"></text></view>
            </view>
        </view>
        
        <!-- 背景语音图 -->
        <view class="uv3__voicepanel-cover">
            <image v-if="!voiceToTransfer" src="/static/voice_bg.webp" :webp="true" mode="widthFix" style="width: 100%;" />
        </view>
        <!-- // 提示文字 -->
        <view v-if="!voiceToTransfer" class="uv3__voicepanel-tooltip">{{voiceTypeMap[voiceType]}}</view>
        <!-- 背景图标 -->
        <view v-if="!voiceToTransfer" class="uv3__voicepanel-fixico"><text class="uv3-icon uv3-icon-audio fs-50"></text></view>
    </view>
</view>

代码语言:typescript
AI代码解释
复制
// 触摸事件(开始/更新/结束)
const handleTouchStart = (e) => {
	// console.log(e)
	voiceType.value = 1
	voicePanelEnable.value = true
}
const handleTouchUpdate = (e) => {
	// console.log(e)
	let touches = e.touches[0]
	let swipeY = globalData.screenHeight - 150;
	let swipeX = globalData.screenWidth / 2 + 50;
	if(touches.clientY >= swipeY) {
		voiceType.value = 1 // 松开发送
	}else if(touches.clientY < swipeY && touches.clientX < swipeX) {
		voiceType.value = 2 // 左滑松开取消
	}else if(touches.clientY < swipeY && touches.clientX >= swipeX) {
		voiceType.value = 3 // 右滑语音转文字
	}
}

https://cloud.tencent.com/developer/article/2400555

https://cloud.tencent.com/developer/article/2393406

Okey,综上就是uniapp+vue3+uni-ui实战开发微信app聊天的一些知识分享,希望对大家有所帮助!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[译]响应式图像
练小习
2017/12/29
2.2K0
响应式布局,你需要知道这些
https://juejin.cn/post/6951575591099301895
前端达人
2021/05/11
1.8K0
web图像的常见应用策略与技巧
文章主要讲述了如何通过修改SVG的src属性来加载不同版本的SVG文件,并介绍了两种回退策略:使用image-set和动态设置src。同时,也介绍了一些关于加载优化的技巧,例如使用data uri和base64编码。在总结中,提到了这些技术的使用场景和注意事项,以帮助读者更好地理解和应用这些技术。
练小习
2017/12/01
1.7K0
前端基础知识概述 -- 移动端开发的屏幕、图像、字体与布局的兼容适配
前端的一大工作内容就是去兼容页面在不同内核的浏览器,不同的设备,不同的分辨率下的行为,使页面的能正常工作在各种各样的宿主环境当中。
Sb_Coco
2019/09/06
3.2K0
响应式图片解决方案
来源:学生做的网站,方便大家学习交流设计与技术 http://www.uidask.com/index.php 网站的平均加载已经到了近 2MB 并在不断地增加中,其中图片占据了绝大多数流量(63%)。可以肯定的是网页已经有了严重的大小问题,而图片就是罪魁祸首。虽然已经有很多种 措施 可以减少网页加载量,但或许更重要的步骤之一是确保响应式图片的加载方案。通过利用响应式图片解决方案,我们可以确保最佳的图片被加载,带宽不会被过大的图片所浪费。因此 W3C 定义了 picture 标签:基于检测客户端设备类型
用户1730674
2018/05/02
1K0
随方逐圆--全面理解CSS媒体查询
在CSS2中,媒体查询只使用于<style>和<link>标签中,以media属性存在;media属性用于为不同的媒介类型规定不同的样式,而真正广泛使用的媒介类型是'screen'、'print'和'all'
江米小枣
2020/06/15
1.3K0
响应式布局的实现
响应式布局指的是同一页面在不同屏幕尺寸或者在不同的设备下有不同的布局,能够在大屏设备以及小屏设备获得更好的浏览体验,简单来说就是页面适应终端而无需为每个终端制作单独的页面。
WindRunnerMax
2020/08/27
2K0
详细的聊一聊如何使用响应式图片,提升网页加载速度
确保图片在所有屏幕尺寸上都能良好显示是一项困难的任务,因为你需要考虑图片的大小、图片的放置位置、显示图片的比例、用户连接的速度等等众多因素。结果是,大多数开发者只会为所有屏幕尺寸使用同一张图片,并让浏览器调整图片的大小以适应屏幕。这是一种不好的做法,因为浏览器仍会下载完整尺寸的图片(通常非常大),即使它只以其一部分尺寸显示。这会浪费用户的带宽,并且会显著减慢页面加载速度(尤其是在较慢的连接下)。
前端达人
2023/08/31
6440
详细的聊一聊如何使用响应式图片,提升网页加载速度
CSS&HTML面经专题——(四)移动端响应式布局
在移动端viewport视口(pc端没有这个概念)就是浏览器显示页面内容的屏幕区域。
玖柒的小窝
2021/10/26
2.5K0
【Web前端】CSS 响应式设计(补充)
随着移动设备的普及,网页设计的焦点逐渐转向了响应式设计。响应式设计不仅要求网页在各种屏幕尺寸上良好展示,还要适应不同设备的特性。
一条晒干的咸鱼
2024/11/19
2660
【Web前端】CSS 响应式设计(补充)
关于移动端适配,你必须要知道的
上面这些问题可能我们在开发中已经知道如何解决,但是问题产生的原理,以及解决方案的原理可能会模糊不清。在解决这些问题的过程中,我们往往会遇到非常多的概念:像素、分辨率、 PPI、 DPI、 DP、 DIP、 DPR、视口等等,你真的能分清这些概念的意义吗?
ConardLi
2019/05/23
2K0
移动端自适应的常见手段
完整高频题库仓库地址:https://github.com/hzfe/awesome-interview
HZFEStudio
2021/10/01
2K0
54个CSS重难点整理,12-24篇,进阶高薪必需要掌握的知识点
本次我把CSS中的重难点整理出来,总共54个核心知识点,供大家复习,希望能帮到大家。这些重难点是进阶高薪必需要掌握的知识点,同时也是面试必问的内容。
艾编程
2022/12/06
1.4K0
54个CSS重难点整理,12-24篇,进阶高薪必需要掌握的知识点
超越媒体查询:使用更新的特性进行响应式设计
除了使用媒体查询和现代CSS布局(例如flexbox和grid)来创建响应式网站之外,我们使用一些比较不太被用或者比较新的特性来制作响应式网站。 在本文中,我们将探讨许多可用的工具(围绕HTML和CSS),从响应图像到相对较新的CSS函数,无论我们是否使用媒体查询,它们都可以正常工作。
前端小智@大迁世界
2020/10/28
4.2K0
静态布局、自适应布局、流式布局、响应式布局、弹性布局等的概念和区别
1、布局特点:不管浏览器尺寸具体是多少,网页布局始终按照最初写代码时的布局来显示。常规的pc的网站都是静态(定宽度)布局的,也就是设置了min-width,这样的话,如果小于这个宽度就会出现滚动条,如果大于这个宽度则内容居中外加背景,这种设计常见与pc端。 2、设计方法:   PC:居中布局,所有样式使用绝对宽度/高度(px),设计一个Layout,在屏幕宽高有调整时,使用横向和竖向的滚动条来查阅被遮掩部分;   移动设备:另外建立移动网站,单独设计一个布局,使用不同的域名如wap.或m.。
何处锦绣不灰堆
2020/05/29
11.2K0
微信小程序布局单位的使用
rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应。官方推荐微信小程序可以用iPhone6 作为视觉稿的标准。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为750 px,则共有个750 物理像素,则750 rpx = 375px = 750 物理像素 例如 : 1rpx = 0.5px = 1物理像素
用户2305175
2018/06/24
3.1K0
vw, vh视窗宽高单位的使用
不过“我看见你”和“我触碰你”是不一样的。正好,机缘巧合,最近又与这两个单位想见。大致琢磨了下,貌似vh这个单位可以实现我以前曾希望实现的的整体高度自适应布局。想到这里,自己不由得小兴奋了下,于是决定抽时间研究研究(虽然最近整iPad忙得屁股尿流~~)。
javascript.shop
2019/09/05
2.6K0
vw, vh视窗宽高单位的使用
布局常用解决方案对比(媒体查询、百分比、rem和vw/vh)
简要介绍:前端开发中,静态网页通常需要适应不同分辨率的设备,常用的自适应解决方案包括媒体查询、百分比、rem和vw/vh等。本文从px单位出发,分析了px在移动端布局中的不足,接着介绍了几种不同的自适应解决方案。
用户8639654
2021/07/26
2.2K0
【学习图片】11.描述性语法
在这个模块中,我们将学习如何为浏览器提供一系列图像选择,以便它可以做出最佳的显示决策。srcset不是在特定断点切换图像源的方法,也不是为了将一张图像换成另一张。这些语法允许浏览器独立地解决一个非常困难的问题:无缝地请求和渲染一个适合用户浏览上下文的图像源,包括视口大小、显示密度、用户偏好、带宽和一些其他因素。
前端小智@大迁世界
2023/03/08
1.2K0
【学习图片】11.描述性语法
网站自适应布局为什么我要抛弃rem,改用vw?
你还在用rem弹性布局吗?在html文件头部放入一大段压缩过的js代码,是不是让你很难受?来了解下vw吧,能让你的代码更纯粹。
李洋博客
2021/06/15
3.6K0
推荐阅读
相关推荐
[译]响应式图像
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档