uni-app聊天室|vue+uniapp仿微信聊天实例|uniapp仿微信App界面
<h3 id="一项目简介">一、介绍</h3><p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif; background-color: rgba(204, 255, 204, 1)">运用UniApp+Vue+Vuex+swiper+uniPop等技术开发的仿微信原生App聊天室|仿微信聊天界面实例项目uniapp-chatroom,实现了发送图文消息、表情(gif图),图片预览、地图位置、长按菜单、红包/钱包、仿微信朋友圈等功能。</span></p>
<h3>二、测试效果</h3>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">H5 + 小程序 + App端测试效果如下,实测多端效果均为一致。(<em>后续大图统一展示App端</em>)<br></span></p>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif"><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010003758483-1629155986.png"></span></p>
<h3 id="三技术栈">二、技术选型</h3>
<ul>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">编辑器:HBuilder X</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">技术框架:uni-app + vue</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">状态管理:Vuex</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">iconfont图标:阿里字体图标库</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">自定义导航栏 + 底部Tabbar</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">弹窗组件:uniPop(基于uni-app封装模态弹窗)</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">测试环境:H5端 + 小程序 + App端(三端均兼容)</span></li>
<li><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">高德地图:vue-amap</span></li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004218438-1400632737.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004303809-489794493.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004349771-120474864.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004402254-429063375.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004425786-511791844.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004514789-174277741.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004554495-65117077.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004606680-627436560.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004649694-1329302841.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004811400-1984924237.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010004951752-1301321460.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010005024855-1157545928.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010005159974-788593951.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010005215710-2038068021.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010005246613-796423085.png"></p>
<p><strong>◆ 顶部导航栏headerBar</strong></p>
<p><span style="font-size: 12px">顶部导航栏采用的是自定义模式,具体可参看这篇文章:uni-app自定义导航栏按钮|uniapp仿微信顶部导航条</span></p>
<p><span style="font-size: 12px">在pages.json里面配置globalStyle,将navigationStyle设为custom时,原生顶部导航栏不显示,这时就能自定义导航栏</span></p>
<p><span style="font-size: 12px"> <span class="cnblogs_code">"globalStyle": {"navigationStyle": "custom"}</span> </span></p>
<p><strong>◆ 引入公共样式/组件及全局弹窗</strong></p>
<div class="cnblogs_code">
<pre>import Vue from 'vue'<span style="color: rgba(0, 0, 0, 1)">
import App from </span>'./App'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> >>>引入css</span>
import './assets/fonts/iconfont.css'<span style="color: rgba(0, 0, 0, 1)">
import </span>'./assets/css/reset.css'<span style="color: rgba(0, 0, 0, 1)">
import </span>'./assets/css/layout.css'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> >>>引入状态管理</span>
import store from './store'<span style="color: rgba(0, 0, 0, 1)">
Vue.prototype.$store </span>=<span style="color: rgba(0, 0, 0, 1)"> store
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> >>>引入公共组件</span>
import headerBar from './components/header/header.vue'<span style="color: rgba(0, 0, 0, 1)">
import tabBar from </span>'./components/tabbar/tabbar.vue'<span style="color: rgba(0, 0, 0, 1)">
import popupWindow from </span>'./components/popupWindow.vue'<span style="color: rgba(0, 0, 0, 1)">
Vue.component(</span>'header-bar'<span style="color: rgba(0, 0, 0, 1)">, headerBar)
Vue.component(</span>'tab-bar'<span style="color: rgba(0, 0, 0, 1)">, tabBar)
Vue.component(</span>'popup-window'<span style="color: rgba(0, 0, 0, 1)">, popupWindow)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> >>>引入uniPop弹窗组件</span>
import uniPop from './components/uniPop/uniPop.vue'<span style="color: rgba(0, 0, 0, 1)">
Vue.component(</span>'uni-pop'<span style="color: rgba(0, 0, 0, 1)">, uniPop)
Vue.config.productionTip </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
App.mpType </span>= 'app'<span style="color: rgba(0, 0, 0, 1)">
const app </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Vue({
...App
})
app.$mount()</span></pre>
</div>
<p><span style="font-size: 18px; font-family: 宋体, "Songti SC"; background-color: rgba(0, 255, 255, 1)">uniapp自定义Navbar+Tabbar组件已经发布到了插件市场,免费下载使用。</span></p>
<p><span style="font-size: 12px">https://ext.dcloud.net.cn/plugin?id=5592</span><br><span style="font-size: 12px">https://ext.dcloud.net.cn/plugin?id=5593</span></p>
<p> </p>
<p><strong>◆ Vuex + uniapp登录验证</strong></p>
<div class="cnblogs_code">
<pre>import Vue from 'vue'<span style="color: rgba(0, 0, 0, 1)">
import Vuex from </span>'vuex'<span style="color: rgba(0, 0, 0, 1)">
Vue.use(Vuex)
export </span><span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Vuex.Store({
state: {
user: uni.getStorageSync(</span>'user'<span style="color: rgba(0, 0, 0, 1)">),
token: uni.getStorageSync(</span>'token'<span style="color: rgba(0, 0, 0, 1)">),
},
mutations: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 存储token</span>
<span style="color: rgba(0, 0, 0, 1)"> SET_TOKEN(state, data) {
state.token </span>=<span style="color: rgba(0, 0, 0, 1)"> data
uni.setStorageSync(</span>'token'<span style="color: rgba(0, 0, 0, 1)">, data)
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 存储用户名</span>
<span style="color: rgba(0, 0, 0, 1)"> SET_USER(state, data) {
state.user </span>=<span style="color: rgba(0, 0, 0, 1)"> data
uni.setStorageSync(</span>'user'<span style="color: rgba(0, 0, 0, 1)">, data)
},
...
},
})</span></pre>
</div>
<div class="cnblogs_code">
<pre><script><span style="color: rgba(0, 0, 0, 1)">
import { mapState, mapMutations } from </span>'vuex'<span style="color: rgba(0, 0, 0, 1)">
import util from </span>'../../utils/util.js'<span style="color: rgba(0, 0, 0, 1)">
export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {
data() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
formObj: {},
}
},
computed: {
...mapState([</span>'user', 'token'<span style="color: rgba(0, 0, 0, 1)">])
},
mounted() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断是否有登录</span>
<span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.user){
uni.redirectTo({url: </span>'/pages/index/index'<span style="color: rgba(0, 0, 0, 1)">})
}
},
methods: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 提交表单</span>
<span style="color: rgba(0, 0, 0, 1)"> handleSubmit(e) {
...
}
}
}
</span></script></pre>
</div>
<p><strong>◆ 仿微信朋友圈透明导航栏</strong></p>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">通过onPageScroll函数实现自定义导航上下滑动自动调整导航栏的透明度,滑动到距离顶部200 效果如下图二</span></p>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif"><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010014210885-1098056404.png"> <img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010014219056-766472638.png"></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* @tpl 朋友圈模板
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<template>
<view class="flexbox flex_col">
<header-bar :isBack="true" title="朋友圈" :bgColor="{background: headerBarBackground}" transparent>
<text slot="back" class="uni_btnIco iconfont icon-arrL"></text>
<text slot="iconfont" class="uni_btnIco iconfont icon-publish mr_5" @tap="handlePublish"></text>
</header-bar>
<view class="uni__scrollview flex1">
<view class="uni-friendZone"><span style="color: rgba(0, 0, 0, 1)">
...
</span></view>
</view>
</view>
</template>
<script><span style="color: rgba(0, 0, 0, 1)">
export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {
data() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
headerBarBackground: </span>'transparent'<span style="color: rgba(0, 0, 0, 1)">
}
},
onPageScroll : </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log("滚动距离为:" + e.scrollTop);</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.headerBarBackground = 'rgba(65,168,99,'+e.scrollTop / 200+')'<span style="color: rgba(0, 0, 0, 1)">
},
methods: {
...
}
}
</span></script>
<style scoped>
</style></pre>
</div>
<p><strong>◆ uniapp实现聊天页面滚动至底部</strong></p>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif">在h5端将聊天页面滚动到底部很好实现,小程序中通过设置scroll-view属性scroll-into-view的值也能实现,可是在uni-app里面怎么将聊天信息滚动至底部呢?</span></p>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif"><img src="https://img2018.cnblogs.com/blog/1289798/201910/1289798-20191010020642218-886677506.png"></span></p>
<p><span style="font-size: 12px; font-family: "comic sans ms", sans-serif; background-color: rgba(230, 229, 228, 1)">uni-app通过判断聊天内容高度和scroll-view高度的大小设置滚动距离</span></p>
<div class="cnblogs_code">
<pre><scroll-view id="scrollview" scroll-y="true" :scroll-top="scrollTop" style="height: 100%;">
<view class="uni-chatMsgCnt" id="msglistview">
<view class="msgitem">xxx</view>
<view class="msgitem">xxx</view>
<view class="msgitem">xxx</view>
<span style="color: rgba(0, 0, 0, 1)"> ...
</span></view>
</scroll-view></pre>
</div>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {
data() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
scrollTop: </span>0<span style="color: rgba(0, 0, 0, 1)">,
...
}
},
mounted() {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.scrollToBottom()
},
updated() {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.scrollToBottom()
},
methods: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 滚动至聊天底部</span>
<span style="color: rgba(0, 0, 0, 1)"> scrollToBottom(t) {
let that </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
let query </span>=<span style="color: rgba(0, 0, 0, 1)"> uni.createSelectorQuery()
query.select(</span>'#scrollview'<span style="color: rgba(0, 0, 0, 1)">).boundingClientRect()
query.select(</span>'#msglistview'<span style="color: rgba(0, 0, 0, 1)">).boundingClientRect()
query.exec((res) </span>=><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(res)</span>
<span style="color: rgba(0, 0, 255, 1)">if</span>(res.height > res.height){
that.scrollTop </span>= res.height - res.height
}
})
},
...
}
}</span></pre>
</div>
<p><strong>◆ uniapp聊天代码片段</strong></p>
<div class="cnblogs_code">
<pre><script><span style="color: rgba(0, 0, 0, 1)">
const emotionJson </span>= require('./mock-emotion.js'<span style="color: rgba(0, 0, 0, 1)">)
const messageJson </span>= require('./mock-chat.js'<span style="color: rgba(0, 0, 0, 1)">)
export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {
data() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
scrollTop: </span>0<span style="color: rgba(0, 0, 0, 1)">,
showFootToolbar: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
showEmotionChoose: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
editorText: </span>''<span style="color: rgba(0, 0, 0, 1)">,
editorLastCursor: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 表情json</span>
<span style="color: rgba(0, 0, 0, 1)"> emotionList: emotionJson,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 消息记录</span>
<span style="color: rgba(0, 0, 0, 1)"> messageList: messageJson,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 预览图片临时数组</span>
<span style="color: rgba(0, 0, 0, 1)"> previewImgArray: [],
}
},
mounted() {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.scrollToBottom()
},
updated() {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.scrollToBottom()
},
methods: {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 滚动至聊天底部</span>
<span style="color: rgba(0, 0, 0, 1)"> scrollToBottom(t) {
let that </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
let query </span>=<span style="color: rgba(0, 0, 0, 1)"> uni.createSelectorQuery()
query.select(</span>'#scrollview'<span style="color: rgba(0, 0, 0, 1)">).boundingClientRect()
query.select(</span>'#msglistview'<span style="color: rgba(0, 0, 0, 1)">).boundingClientRect()
query.exec((res) </span>=><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(res)</span>
<span style="color: rgba(0, 0, 255, 1)">if</span>(res.height > res.height){
that.scrollTop </span>= res.height - res.height
}
})
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击聊天消息区域</span>
<span style="color: rgba(0, 0, 0, 1)"> msgPanelTaped() {
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 255, 1)">this</span>.showFootToolbar) <span style="color: rgba(0, 0, 255, 1)">return</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.showFootToolbar = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 表情、选择区切换</span>
<span style="color: rgba(0, 0, 0, 1)"> swtEmotionChooseView(bool) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.showFootToolbar = <span style="color: rgba(0, 0, 255, 1)">true</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.showEmotionChoose =<span style="color: rgba(0, 0, 0, 1)"> bool
},
...
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击表情</span>
<span style="color: rgba(0, 0, 0, 1)"> handleEmotionTaped(emoj) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(emoj == 'del') <span style="color: rgba(0, 0, 255, 1)">return</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在光标处插入表情</span>
let startStr = <span style="color: rgba(0, 0, 255, 1)">this</span>.editorText.substr(0, <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.editorLastCursor)
let endStr </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.editorText.substr(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.editorLastCursor)
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.editorText = startStr + `${emoj}` +<span style="color: rgba(0, 0, 0, 1)"> endStr
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> >>> 【选择区功能模块】------------------------------------------</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 选择图片</span>
<span style="color: rgba(0, 0, 0, 1)"> handleLaunchImage() {
let that </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
let msglist </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.messageList
let len </span>=<span style="color: rgba(0, 0, 0, 1)"> msglist.length
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 消息队列</span>
let data =<span style="color: rgba(0, 0, 0, 1)"> {
id: `msg${</span>++<span style="color: rgba(0, 0, 0, 1)">len}`,
msgtype: </span>5<span style="color: rgba(0, 0, 0, 1)">,
isme: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
avator: </span>'/static/uimg/u__chat_img1.jpg'<span style="color: rgba(0, 0, 0, 1)">,
author: </span>'King'<span style="color: rgba(0, 0, 0, 1)">,
msg: </span>''<span style="color: rgba(0, 0, 0, 1)">,
imgsrc: </span>''<span style="color: rgba(0, 0, 0, 1)">,
videosrc: </span>''<span style="color: rgba(0, 0, 0, 1)">
}
uni.chooseImage({
count: </span>1<span style="color: rgba(0, 0, 0, 1)">,
sourceType: [</span>'album'<span style="color: rgba(0, 0, 0, 1)">],
success: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(res){
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(res)</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> console.log(res.tempFilePaths)</span>
data.imgsrc =<span style="color: rgba(0, 0, 0, 1)"> res.tempFilePaths.toString()
msglist </span>=<span style="color: rgba(0, 0, 0, 1)"> msglist.concat(data)
that.messageList </span>=<span style="color: rgba(0, 0, 0, 1)"> msglist
}
})
},
...
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 位置</span>
<span style="color: rgba(0, 0, 0, 1)"> handleChooseLocation() {
let that </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
let msglist </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.messageList
let len </span>=<span style="color: rgba(0, 0, 0, 1)"> msglist.length
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 消息队列</span>
let data =<span style="color: rgba(0, 0, 0, 1)"> {
id: `msg${</span>++<span style="color: rgba(0, 0, 0, 1)">len}`,
msgtype: </span>8<span style="color: rgba(0, 0, 0, 1)">,
isme: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
avator: </span>'/static/uimg/u__chat_img1.jpg'<span style="color: rgba(0, 0, 0, 1)">,
author: </span>'King'<span style="color: rgba(0, 0, 0, 1)">,
msg: </span>''<span style="color: rgba(0, 0, 0, 1)">,
imgsrc: </span>''<span style="color: rgba(0, 0, 0, 1)">,
videosrc: </span>''<span style="color: rgba(0, 0, 0, 1)">
}
uni.chooseLocation({
success: (res) </span>=><span style="color: rgba(0, 0, 0, 1)"> {
console.log(res)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 插入消息</span>
data.msg =<span style="color: rgba(0, 0, 0, 1)"> {
name: res.name,
address: res.address,
latitude: res.latitude,
longitude: res.longitude
}
msglist </span>=<span style="color: rgba(0, 0, 0, 1)"> msglist.concat(data)
that.messageList </span>=<span style="color: rgba(0, 0, 0, 1)"> msglist
}
})
},
}
}
</span></script></pre>
</div>
<p><span style="font-size: 12px">以上就是基于uniapp开发仿微信聊天室的介绍,希望大家能喜欢💪💪~~</span></p>
<p><span style="font-size: 12px"><strong>附上几个最新原创研发的实例项目</strong></span></p>
<blockquote>
<p><span style="font-size: 12px">uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈</span></p>
<p><span style="font-size: 12px">uniapp-vue3-oadmin手机后台实例|vite5.x+uniapp多端仿ios管理系统</span></p>
<p><span style="font-size: 12px">uniapp-welive仿微信/抖音直播带货|uni-app+vue3+pinia短视频直播商城</span></p>
<p><span style="font-size: 12px">Vite5+Electron聊天室|electron31跨平台仿微信EXE客户端|vue3聊天程序</span></p>
<p><span style="font-size: 12px">Electron31-Vue3Admin管理系统|vite5+electron+pinia桌面端后台Exe</span></p>
<p><span style="font-size: 12px">Electron32-ViteOS桌面版os系统|vue3+electron+arco客户端OS管理模板</span></p>
</blockquote>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
本文为博主原创文章,未经博主允许不得转载,欢迎大家一起交流 QQ(282310962) wx(xy190310)<br><br>
来源:https://www.cnblogs.com/xiaoyan2017/p/11645467.html
頁:
[1]