一、介绍
运用UniApp+Vue+Vuex+swiper+uniPop等技术开发的仿微信原生App聊天室|仿微信聊天界面实例项目uniapp-chatroom,实现了发送图文消息、表情(gif图),图片预览、地图位置、长按菜单、红包/钱包、仿微信朋友圈等功能。
二、测试效果
H5 + 小程序 + App端测试效果如下,实测多端效果均为一致。(后续大图统一展示App端)

二、技术选型
- 编辑器:HBuilder X
- 技术框架:uni-app + vue
- 状态管理:Vuex
- iconfont图标:阿里字体图标库
- 自定义导航栏 + 底部Tabbar
- 弹窗组件:uniPop(基于uni-app封装模态弹窗)
- 测试环境:H5端 + 小程序 + App端(三端均兼容)
- 高德地图:vue-amap















◆ 顶部导航栏headerBar
顶部导航栏采用的是自定义模式,具体可参看这篇文章:uni-app自定义导航栏按钮|uniapp仿微信顶部导航条
在pages.json里面配置globalStyle,将navigationStyle设为custom时,原生顶部导航栏不显示,这时就能自定义导航栏
"globalStyle": {"navigationStyle": "custom"}
◆ 引入公共样式/组件及全局弹窗
- import Vue from 'vue'
- import App from './App'
-
- // >>>引入css
- import './assets/fonts/iconfont.css'
- import './assets/css/reset.css'
- import './assets/css/layout.css'
-
- // >>>引入状态管理
- import store from './store'
- Vue.prototype.$store = store
- // >>>引入公共组件
- import headerBar from './components/header/header.vue'
- import tabBar from './components/tabbar/tabbar.vue'
- import popupWindow from './components/popupWindow.vue'
- Vue.component('header-bar', headerBar)
- Vue.component('tab-bar', tabBar)
- Vue.component('popup-window', popupWindow)
- // >>>引入uniPop弹窗组件
- import uniPop from './components/uniPop/uniPop.vue'
- Vue.component('uni-pop', uniPop)
- Vue.config.productionTip = false
- App.mpType = 'app'
- const app = new Vue({
- ...App
- })
- app.$mount()
◆ Vuex + uniapp登录验证
- import Vue from 'vue'
- import Vuex from 'vuex'
- Vue.use(Vuex)
- export default new Vuex.Store({
- state: {
- user: uni.getStorageSync('user'),
- token: uni.getStorageSync('token'),
- },
- mutations: {
- // 存储token
- SET_TOKEN(state, data) {
- state.token = data
- uni.setStorageSync('token', data)
- },
- // 存储用户名
- SET_USER(state, data) {
- state.user = data
- uni.setStorageSync('user', data)
- },
- ...
- },
- })
- <script>
- import { mapState, mapMutations } from 'vuex'
- import util from '../../utils/util.js'
-
- export default {
- data() {
- return {
- formObj: {},
- }
- },
- computed: {
- ...mapState(['user', 'token'])
- },
- mounted() {
- // 判断是否有登录
- if(this.user){
- uni.redirectTo({url: '/pages/index/index'})
- }
- },
- methods: {
- // 提交表单
- handleSubmit(e) {
- ...
- }
- }
- }
- </script>
◆ 仿微信朋友圈透明导航栏
通过onPageScroll函数实现自定义导航上下滑动自动调整导航栏的透明度,滑动到距离顶部200 效果如下图二

- /**
- * @tpl 朋友圈模板
- */
-
- <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">
- ...
- </view>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- data() {
- return {
- headerBarBackground: 'transparent'
- }
- },
- onPageScroll : function(e) {
- // console.log("滚动距离为:" + e.scrollTop);
- this.headerBarBackground = 'rgba(65,168,99,'+e.scrollTop / 200+')'
- },
- methods: {
- ...
- }
- }
- </script>
-
- <style scoped>
-
- </style>
◆ uniapp实现聊天页面滚动至底部
在h5端将聊天页面滚动到底部很好实现,小程序中通过设置scroll-view属性scroll-into-view的值也能实现,可是在uni-app里面怎么将聊天信息滚动至底部呢?

uni-app通过判断聊天内容高度和scroll-view高度的大小设置滚动距离
- <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>
- ...
- </view>
- </scroll-view>
- export default {
- data() {
- return {
- scrollTop: 0,
- ...
- }
- },
- mounted() {
- this.scrollToBottom()
- },
- updated() {
- this.scrollToBottom()
- },
- methods: {
- // 滚动至聊天底部
- scrollToBottom(t) {
- let that = this
- let query = uni.createSelectorQuery()
- query.select('#scrollview').boundingClientRect()
- query.select('#msglistview').boundingClientRect()
- query.exec((res) => {
- // console.log(res)
- if(res[1].height > res[0].height){
- that.scrollTop = res[1].height - res[0].height
- }
- })
- },
- ...
- }
- }
◆ uniapp聊天代码片段
- <script>
- const emotionJson = require('./mock-emotion.js')
- const messageJson = require('./mock-chat.js')
-
- export default {
- data() {
- return {
- scrollTop: 0,
-
- showFootToolbar: false,
- showEmotionChoose: false,
-
- editorText: '',
- editorLastCursor: null,
-
- // 表情json
- emotionList: emotionJson,
-
- // 消息记录
- messageList: messageJson,
-
- // 预览图片临时数组
- previewImgArray: [],
- }
- },
- mounted() {
- this.scrollToBottom()
- },
- updated() {
- this.scrollToBottom()
- },
- methods: {
- // 滚动至聊天底部
- scrollToBottom(t) {
- let that = this
- let query = uni.createSelectorQuery()
- query.select('#scrollview').boundingClientRect()
- query.select('#msglistview').boundingClientRect()
- query.exec((res) => {
- // console.log(res)
- if(res[1].height > res[0].height){
- that.scrollTop = res[1].height - res[0].height
- }
- })
- },
-
- // 点击聊天消息区域
- msgPanelTaped() {
- if(!this.showFootToolbar) return
- this.showFootToolbar = false
- },
-
- // 表情、选择区切换
- swtEmotionChooseView(bool) {
- this.showFootToolbar = true
- this.showEmotionChoose = bool
- },
-
- ...
-
- // 点击表情
- handleEmotionTaped(emoj) {
- if(emoj == 'del') return
- // 在光标处插入表情
- let startStr = this.editorText.substr(0, this.editorLastCursor)
- let endStr = this.editorText.substr(this.editorLastCursor)
- this.editorText = startStr + `${emoj}` + endStr
- },
-
-
- // >>> 【选择区功能模块】------------------------------------------
- // 选择图片
- handleLaunchImage() {
- let that = this
- let msglist = this.messageList
- let len = msglist.length
- // 消息队列
- let data = {
- id: `msg${++len}`,
- msgtype: 5,
- isme: true,
- avator: '/static/uimg/u__chat_img1.jpg',
- author: 'King',
- msg: '',
- imgsrc: '',
- videosrc: ''
- }
-
- uni.chooseImage({
- count: 1,
- sourceType: ['album'],
- success: function(res){
- // console.log(res)
- // console.log(res.tempFilePaths)
- data.imgsrc = res.tempFilePaths.toString()
- msglist = msglist.concat(data)
- that.messageList = msglist
- }
- })
- },
-
- ...
-
- // 位置
- handleChooseLocation() {
- let that = this
- let msglist = this.messageList
- let len = msglist.length
- // 消息队列
- let data = {
- id: `msg${++len}`,
- msgtype: 8,
- isme: true,
- avator: '/static/uimg/u__chat_img1.jpg',
- author: 'King',
- msg: '',
- imgsrc: '',
- videosrc: ''
- }
-
- uni.chooseLocation({
- success: (res) => {
- console.log(res)
- // 插入消息
- data.msg = {
- name: res.name,
- address: res.address,
- latitude: res.latitude,
- longitude: res.longitude
- }
- msglist = msglist.concat(data)
- that.messageList = msglist
- }
- })
- },
-
- }
- }
- </script>
以上就是基于uniapp开发仿微信聊天室的介绍,希望大家能喜欢????~~
◆ 最后附上基于uni-app开发的自定义导航栏及Modal对话框
uniapp自定义导航栏:https://www.cnblogs.com/xiaoyan2017/p/11531238.html
uniapp模态弹窗组件:https://www.cnblogs.com/xiaoyan2017/p/11589149.html