uniapp模仿微信實現(xiàn)聊天界面的示例代碼
項目演示

前言
我是看B站的視頻一個一個敲的,講的還不錯??梢匀タ纯?a rel="external nofollow" target="_blank">vue+node.js即時通訊聊天室APP開發(fā)前端篇
主界面
chat.vue
<template>
<!-- 聊天界面展示https://www.bilibili.com/video/BV1hT4y1P75N?p=22 搭建1和2 -->
<view class="content">
<!-- 聊天內容 -->
<scroll-view class="chat" scroll-y="true" scroll-with-animation="true" :scroll-into-view="scrollToView">
<view class="chat-main" :style="{paddingBottom:inputh+'px'}">
<view class="chat-ls" v-for="(item,index) in unshiftmsg" :key="index" :id="'msg'+ index">
<view class="chat-time" v-if="item.createTime != ''">{{changeTime(item.createTime)}}</view>
<view class="msg-m msg-left" v-if="item.sendName == friendName">
<image class="user-img" src="../../../static/logo.png"></image>
<view class="message" v-if="item.TextType == 0">
<!-- 文字 -->
<view class="msg-text">{{item.sendText}}</view>
</view>
<view class="message" v-if="item.TextType == 1" @tap="previewImg(item.sendText)">
<!-- 圖像 -->
<image :src="item.sendText" class="msg-img" mode="widthFix"></image>
</view>
<view class="message" v-if="item.TextType == 2" @tap="playVoice(item.sendText.voice)">
<!-- 音頻 -->
<view class="msg-text voice" :style="{width:item.sendText.time*4+'rpx'}">
<image src="../../../static/icon/Hotline.png" class="voice-img"></image>
{{item.sendText.time}}″
</view>
</view>
<view class="message" v-if="item.TextType == 3" @tap="openLocation(item.sendText)">
<!-- 位置 -->
<view class="msg-map">
<view class="map-name">{{item.sendText.name}}</view>
<view class="map-address">{{item.sendText.address}}</view>
<!-- 如果map不起作用,就可以直接用一張圖片去替代 -->
<map class="map" :longitude="item.sendText.longitude" :latitude="item.sendText.latitude"
:markers="covers(item.sendText)"></map>
</view>
</view>
</view>
<view class="msg-m msg-right" v-if="item.sendName != friendName">
<image class="user-img" src="../../../static/logo.png"></image>
<view class="message" v-if="item.TextType == 0">
<view class="msg-text">{{item.sendText}}</view>
</view>
<view class="message" v-if="item.TextType == 1" @tap="previewImg(item.sendText)">
<image :src="item.sendText" class="msg-img" mode="widthFix"></image>
</view>
<view class="message" v-if="item.TextType == 2" @tap="playVoice(item.sendText.voice)">
<!-- 音頻 -->
<view class="msg-text voice" :style="{width:item.sendText.time*4+'rpx'}">
{{item.sendText.time}}″
<image src="../../../static/icon/Hotline.png" class="voice-img"></image>
</view>
</view>
<view class="message" v-if="item.TextType == 3" @tap="openLocation(item.sendText)">
<!-- 位置 -->
<view class="msg-map">
<view class="map-name">{{item.sendText.name}}</view>
<view class="map-address">{{item.sendText.address}}</view>
<map class="map" :longitude="item.sendText.longitude" :latitude="item.sendText.latitude"
:markers="covers(item.sendText)"></map>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<submit @inputs="inputs" @heights="heights"></submit>
</view>
</template>
<script>
import dateTime from '../../../common/dateTime.js';
import submit from '../../../components/submit/submit.vue';
//音頻播放
const innerAudioContext = uni.createInnerAudioContext();
export default {
data() {
return {
friendName: "xpq",
msg: [{
"sendName": "xpq",
"receviceName": "゛時光い",
"sendText": {
"address": "湖南省岳陽市湘陰縣新世紀大道",
"latitude": 28.68925,
"longitude": 112.90917,
"name": "湘陰縣政府(新世紀大道北)",
},
"createTime": "2022-01-06 12:40:12",
"updateTime": null,
"chatmState": 1,
"TextType": 3
}, {
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": {
"voice": "時光匆匆流過",
"time": 2 //秒
},
"createTime": "2022-01-06 12:22:12",
"updateTime": null,
"chatmState": 1,
"TextType": 2
}, {
"sendName": "xpq",
"receviceName": "゛時光い",
"sendText": {
"voice": "謝謝你",
"time": 60 //秒
},
"createTime": "2022-01-06 12:00:12",
"updateTime": null,
"chatmState": 1,
"TextType": 2
}, {
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "這是第九條未讀消息",
"createTime": "2022-01-03 12:22:12",
"updateTime": null,
"chatmState": 1,
"TextType": 0
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "這是第八條未讀消息",
"createTime": "2022-01-02 12:22:07",
"updateTime": null,
"chatmState": 1,
"TextType": 0
},
{
"sendName": "xpq",
"receviceName": "xpq",
"sendText": "這是第七條未讀消息",
"createTime": "2021-12-19 12:22:03",
"updateTime": null,
"chatmState": 1,
"TextType": 0
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "這是第六條未讀消息",
"createTime": "2021-12-19 12:21:58",
"updateTime": null,
"chatmState": 1,
"TextType": 0
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "http://demo.rageframe.com/attachment/images/2021/11/18/image_1637224530_diIlZlmm.jpeg",
"createTime": "2021-12-19 12:21:54",
"updateTime": null,
"chatmState": 1,
"TextType": 1
},
{
"sendName": "xpq",
"receviceName": "゛時光い",
"sendText": "http://demo2.rageframe.com/attachment/images/2021/09/01/image_1630483477_N03W37zs.jpg",
"createTime": "2021-12-19 12:21:48",
"updateTime": null,
"chatmState": 1,
"TextType": 1
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "這是第三條未讀消息",
"createTime": "2021-12-19 12:21:42",
"updateTime": null,
"chatmState": 1,
"TextType": 0
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "這是第二條未讀消息",
"createTime": "2021-12-19 12:21:33",
"updateTime": null,
"chatmState": 1,
"TextType": 0
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "http://demo2.rageframe.com/attachment/images/2021/09/01/image_1630483477_N03W37zs.jpg",
"createTime": "2021-12-19 11:02:18",
"updateTime": null,
"chatmState": 1,
"TextType": 1
},
{
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": "愛你啊",
"createTime": "2021-12-18 20:37:03",
"updateTime": null,
"chatmState": 0,
"TextType": 0
}
],
// 反轉數(shù)據接收
unshiftmsg: [],
imgMsg: [],
scrollToView: '',
oldTime: new Date(),
inputh: '60'
}
},
onShow() {
// 數(shù)組倒敘 主要是應對后端傳過來的數(shù)據
for (var i = 0; i < this.msg.length; i++) {
//時間間隔處理
if (i < this.msg.length - 1) { //這里表示頭部時間還是顯示一下
let t = dateTime.spaceTime(this.oldTime, this.msg[i].createTime);
if (t) {
this.oldTime = t;
}
this.msg[i].createTime = t;
}
// 獲取圖片,為下面的預覽做準備
if (this.msg[i].TextType == 1) {
this.imgMsg.unshift(this.msg[i].sendText)
}
this.unshiftmsg.unshift(this.msg[i]);
}
// 跳轉到最后一條數(shù)據 與前面的:id進行對照
this.$nextTick(function() {
this.scrollToView = 'msg' + (this.unshiftmsg.length - 1)
})
},
components: {
submit,
},
methods: {
changeTime(date) {
return dateTime.dateTime1(date);
},
// 進行圖片的預覽
previewImg(e) {
let index = 0;
for (let i = 0; i < this.imgMsg.length; i++) {
if (this.imgMsg[i] == e) {
index = i;
}
}
console.log("index", index)
// 預覽圖片
uni.previewImage({
current: index,
urls: this.imgMsg,
longPressActions: {
itemList: ['發(fā)送給朋友', '保存圖片', '收藏'],
success: function(data) {
console.log('選中了第' + (data.tapIndex + 1) + '個按鈕,第' + (data.index + 1) + '張圖片');
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
},
//音頻播放
playVoice(e) {
innerAudioContext.src = e;
innerAudioContext.onPlay(() => {
console.log('開始播放');
});
},
//地圖定位
covers(e) {
let map = [{
latitude: e.latitude,
longitude: e.longitude,
iconPath: '../../../static/logo.png'
}]
return (map);
},
//跳轉地圖信息
openLocation(e) {
uni.openLocation({
latitude: e.latitude,
longitude: e.longitude,
name: e.name,
address: e.address,
success: function() {
console.log('success');
}
});
},
//接受輸入內容
inputs(e) {
//時間間隔處理
let data = {
"sendName": "゛時光い",
"receviceName": "xpq",
"sendText": e.message,
"createTime": new Date(),
"updateTime": new Date(),
"chatmState": 1,
"TextType": e.type
};
// 發(fā)送給服務器消息
// onSendWS(JSON.stringify(data));
this.unshiftmsg.push(data);
// 跳轉到最后一條數(shù)據 與前面的:id進行對照
this.$nextTick(function() {
this.scrollToView = 'msg' + (this.unshiftmsg.length - 1)
})
if (e.type == 1) {
this.imgMsg.push(e.message);
}
console.log(e)
},
//輸入框高度
heights(e) {
console.log("高度:", e)
this.inputh = e;
this.goBottom();
},
// 滾動到底部
goBottom() {
this.scrollToView = '';
this.$nextTick(function() {
this.scrollToView = 'msg' + (this.unshiftmsg.length - 1)
})
}
}
}
</script>
<style lang="scss">
page {
height: 100%;
}
.content {
height: 100%;
background-color: rgba(244, 244, 244, 1);
}
.chat {
height: 100%;
.chat-main {
padding-left: 32rpx;
padding-right: 32rpx;
padding-top: 20rpx;
// padding-bottom: 120rpx; //獲取動態(tài)高度
display: flex;
flex-direction: column;
}
.chat-ls {
.chat-time {
font-size: 24rpx;
color: rgba(39, 40, 50, 0.3);
line-height: 34rpx;
padding: 10rpx 0rpx;
text-align: center;
}
.msg-m {
display: flex;
padding: 20rpx 0;
.user-img {
flex: none;
width: 80rpx;
height: 80rpx;
border-radius: 20rpx;
}
.message {
flex: none;
max-width: 480rpx;
}
.msg-text {
font-size: 32rpx;
color: rgba(39, 40, 50, 1);
line-height: 44rpx;
padding: 18rpx 24rpx;
}
.msg-img {
max-width: 400rpx;
border-radius: 20rpx;
}
.msg-map {
background: #fff;
width: 464rpx;
height: 284rpx;
overflow: hidden;
.map-name {
font-size: 32rpx;
color: rgba(39, 40, 50, 1);
line-height: 44rpx;
padding: 18rpx 24rpx 0 24rpx;
//下面四行是單行文字的樣式
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
}
.map-address {
font-size: 24rpx;
color: rgba(39, 40, 50, 0.4);
padding: 0 24rpx;
//下面四行是單行文字的樣式
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
}
.map {
padding-top: 8rpx;
width: 464rpx;
height: 190rpx;
}
}
.voice {
// width: 200rpx;
min-width: 100rpx;
max-width: 400rpx;
}
.voice-img {
width: 28rpx;
height: 36rpx;
}
}
.msg-left {
flex-direction: row;
.msg-text {
margin-left: 16rpx;
background-color: #fff;
border-radius: 0rpx 20rpx 20rpx 20rpx;
}
.ms-img {
margin-left: 16rpx;
}
.msh-map {
margin-left: 16rpx;
border-radius: 0rpx 20rpx 20rpx 20rpx;
}
.voice {
text-align: right;
}
.voice-img {
float: left;
transform: rotate(180deg);
width: 28rpx;
height: 36rpx;
padding-bottom: 4rpx;
}
}
.msg-right {
flex-direction: row-reverse;
.msg-text {
margin-right: 16rpx;
background-color: rgba(255, 228, 49, 0.8);
border-radius: 20rpx 0rpx 20rpx 20rpx;
}
.ms-img {
margin-right: 16rpx;
}
.msh-map {
margin-left: 16rpx;
border-radius: 20rpx 0rpx 20rpx 20rpx;
}
.voice {
text-align: left;
}
.voice-img {
float: right;
padding: 4rpx;
width: 28rpx;
height: 36rpx;
}
}
}
}
</style>
chat.vue中引入的js文件
dateTime.js
export default{
//首頁時間轉化
dateTime(e){
let old = new Date(e);
let now = new Date();
//獲取old具體時間
let d = old.getTime();
let h = old.getHours();
let m = old.getMinutes();
let Y = old.getFullYear();
let M = old.getMonth()+1;
let D = old.getDate();
//獲取now具體時間
let nd =now.getTime();
let nh = now.getHours();
let n = now.getMinutes();
let nY = now.getFullYear();
let nM = now.getMonth()+1;
let nD = now.getDate();
//當天的時間
if(D === nD && M === nM && Y === nY){
if(h<10){
h = '0'+h;
}
if(m<10){
m = '0'+m;
}
return h+':'+m;
}
//昨天時間
if(D+1 === nD && M === nM && Y === nY){
if(h<10){
h = '0'+h;
}
if(m<10){
m = '0'+m;
}
return '昨天 '+h+':'+m;
}else{
//大于兩天
return Y+'/'+M+'/'+D;
}
},
//聊天時,發(fā)送時間處理
dateTime1(e){
let old = new Date(e);
let now = new Date();
//獲取old具體時間
let d = old.getTime();
let h = old.getHours();
let m = old.getMinutes();
let Y = old.getFullYear();
let M = old.getMonth()+1;
let D = old.getDate();
//獲取now具體時間
let nd =now.getTime();
let nh = now.getHours();
let n = now.getMinutes();
let nY = now.getFullYear();
let nM = now.getMonth()+1;
let nD = now.getDate();
//當天的時間
if(D === nD && M === nM && Y === nY){
if(h<10){
h = '0'+h;
}
if(m<10){
m = '0'+m;
}
return h+':'+m;
}
//昨天時間
if(D+1 === nD && M === nM && Y === nY){
if(h<10){
h = '0'+h;
}
if(m<10){
m = '0'+m;
}
return '昨天 '+h+':'+m;
}else if( Y == nY){
//今年
if(h<10){
h = '0'+h;
}
if(m<10){
m = '0'+m;
}
return M+'月'+D+'日 '+h+':'+m
}else{
//大于今年
if(h<10){
h = '0'+h;
}
if(m<10){
m = '0'+m;
}
return Y+'年'+ M +'月' +D+ '日 '+h+':'+m
}
},
// 間隔時間差
spaceTime(old,now){
old = new Date(old);
now = new Date(now);
var told = old.getTime();
var tnow = now.getTime();
if(told > (tnow+1000*60*5)){
return now;
}else{
return '';
}
}
}
chat.vue中引入的組件
submit.vue
<template>
<view>
<view class="submit">
<view class="submit-chat">
<view class="bt-img" @tap="records">
<image :src="toc"></image>
</view>
<!-- 文本框 -->
<textarea auto-height="true" class="chat-send btn" :class="{displaynone:isrecord}" @input="inputs"
@focus="focus" v-model="msg"></textarea>
<view class="record btn" :class="{displaynone:!isrecord}" @touchstart="touchstart" @touchend="touchend"
@touchmove="touchmove">
按住說話
</view>
<view class="bt-img" @tap="emoji">
<image src="../../static/icon/commonproblem.png"></image>
</view>
<view class="bt-img" @tap="more">
<image src="../../static/icon/news.png"></image>
</view>
</view>
<!-- 表情 -->
<view class="emoji" :class="{displaynone:!isemoji}">
<view class="emoji-send">
<view class="emoji-send-det" @tap="emojiBack">
<image src="../../static/icon/leftbrackets.png"></image>
</view>
<view class="emoji-send-bt" @tap="emojiSend">發(fā)送</view>
</view>
<emoji @emotion="emotion" :height="260"></emoji>
</view>
<!-- 更多 -->
<view class="more" :class="{displaynone:!ismore}">
<view class="more-list" @tap="sendImg('album')">
<image src="../../static/icon/noreceive.png"></image>
<view class="more-list-title">圖片</view>
</view>
<view class="more-list" @tap="sendImg('camera')">
<image src="../../static/icon/noreceive.png"></image>
<view class="more-list-title">拍照</view>
</view>
<view class="more-list" @tap="choseLocation">
<image src="../../static/icon/noreceive.png"></image>
<view class="more-list-title">定位</view>
</view>
<view class="more-list">
<image src="../../static/icon/noreceive.png"></image>
<view class="more-list-title">視頻</view>
</view>
<view class="more-list">
<image src="../../static/icon/noreceive.png"></image>
<view class="more-list-title">文件</view>
</view>
</view>
</view>
<view class="voice-bg" :class="{displaynone:!voicebg}">
<view class="voice-bg-len">
<view class="voice-bg-time" :style="{width:vlength/0.6+'%'}">
{{vlength}}″
</view>
<view class="voice-del">上滑取消錄音</view>
</view>
</view>
</view>
</template>
<script>
// 引入組件
import emoji from '../emoji/emoji.vue'
// 錄音
const recorderManager = uni.getRecorderManager();
export default {
data() {
return {
isrecord: false,
isemoji: false,
ismore: false,
voicebg: false,
pageY: 0,
msg: "",
// 直接引用地址可能出不來,需要用require
toc: require('../../static/icon/allorder.png'),
timer: '', //計時器
vlength: 0
};
},
components: {
emoji,
},
methods: {
//獲取高度方法
getElementHeight() {
const query = uni.createSelectorQuery().in(this);
query.select('.submit').boundingClientRect(data => {
this.$emit('heights', data.height);
}).exec();
},
//切換音頻
records() {
//切換的時候關閉其他界面
this.ismore = false
this.isemoji = false
//切換高度
setTimeout(() => {
this.getElementHeight();
}, 10)
if (this.isrecord) {
this.isrecord = false;
this.toc = require("../../static/icon/allorder.png");
} else {
this.isrecord = true;
this.toc = require("../../static/icon/wechat.png");
}
},
// 表情
emoji() {
this.isemoji = !this.isemoji;
//切換的時候關閉其功能
this.ismore = false
this.isrecord = false;
this.toc = require("../../static/icon/allorder.png");
//切換高度
setTimeout(() => {
this.getElementHeight();
}, 10)
},
//接收表情
emotion(e) {
console.log(e),
this.msg = this.msg + e
},
//文字發(fā)送
inputs(e) {
var chatm = e.detail.value;
var pos = chatm.indexOf('\n');
// 檢索字符串沒有數(shù)據,返回-1
// if (pos != -1 && chatm.length > 1) {
// this.$emit('inputs', this.msg);
// setTimeout(() => {
// this.msg = '';
// }, 0)
// }
if (pos != -1 && chatm.length > 1) {
// 0為表情和文字
this.send(this.msg, 0)
}
},
// 輸入框聚焦
focus() {
//關閉其他項
this.isemoji = false;
this.ismore = false;
setTimeout(() => {
this.getElementHeight()
}, 10)
},
// 表情內發(fā)送
emojiSend() {
// if (this.msg.length > 0) {
// this.$emit('inputs', this.msg);
// setTimeout(() => {
// this.msg = '';
// }, 0)
// }
if (this.msg.length > 0) {
//0為表情和文字
this.send(this.msg, 0)
}
},
// 表格退格
emojiBack() {
if (this.msg.length > 0) {
this.msg = this.msg.substring(0, this.msg.length - 1);
}
},
//更多功能
more() {
this.ismore = !this.ismore;
//切換的時候關閉其他界面
this.isemoji = false
this.isrecord = false;
this.toc = require("../../static/icon/allorder.png");
setTimeout(() => {
this.getElementHeight();
}, 10)
},
//圖片發(fā)送
sendImg(e) {
let count = 9;
if (e == 'album') {
count = 9;
} else {
count = 1;
}
uni.chooseImage({
count: count, //默認9
sizeType: ['original', 'compressed'], //可以指定是原圖還是壓縮圖,默認二者都有
sourceType: [e], //從相冊選擇
// success: function (res) { //用function的方式會找不到send方法
success: (res) => {
console.log(JSON.stringify(res.tempFilePaths));
const filePaths = res.tempFilePaths;
for (let i = 0; i < filePaths.length; i++) {
this.send(filePaths[i], 1)
}
}
});
},
//音頻處理
//開始錄音
touchstart(e) {
console.log("開始錄音")
console.log("點擊產生數(shù)據", e)
this.pageY = e.changedTouches[0].pageY;
this.voicebg = true;
let i = 1;
this.timer = setInterval(() => {
this.vlength = i;
i++;
console.log("計時器開始工作,第幾秒", i)
//結束計時
if (i > 60) {
clearInterval(this.timer);
this.touchend();
}
}, 1000)
recorderManager.start();
},
//刪除錄音
touchmove(e) {
// console.log("滑動到的y軸高度:",e.changedTouches[0].pageY);
if (this.pageY - e.changedTouches[0].pageY > 100) {
// 關閉錄音界面
this.voicebg = false;
}
},
// 結束錄音
touchend() {
console.log("結束錄音")
clearInterval(this.timer);
recorderManager.stop();
// recorderManager.onStop(function(res) {
recorderManager.onStop((res) => {
let data = {
voice: res.tempFilePath,
time: this.vlength
}
if (this.voicebg) {
this.send(data, 2);
}
// //時長歸位
this.vlength = 0;
this.voicebg = false;
console.log('recorder stop' + JSON.stringify(res));
// self.voicePath = res.tempFilePath;
});
},
//獲取位置
choseLocation() {
uni.chooseLocation({
// success: function(res) {
success: res => {
let data = {
name: res.name,
address: res.address,
latitude: res.latitude,
longitude: res.longitude
}
this.send(data, 3);
// console.log('位置名稱:' + res.name);
// console.log('詳細地址:' + res.address);
// console.log('緯度:' + res.latitude);
// console.log('經度:' + res.longitude);
}
});
},
//發(fā)送
send(msg, type) {
let date = {
message: msg,
type: type
}
this.$emit('inputs', date);
setTimeout(() => {
this.msg = '';
}, 0)
}
}
};
</script>
<style lang="scss" scoped>
.submit {
background: rgba(244, 244, 244, 0.96);
border-top: 1px solid rgba(39, 40, 50, 0.1);
width: 100%;
position: fixed;
bottom: 0;
z-index: 100;
// padding-bottom: var(--status-bar-height);
padding-bottom: env(safe-area-inset-bottom);
}
.displaynone {
display: none;
}
.submit-chat {
width: 100%;
display: flex;
align-items: flex-end;
box-sizing: border-box;
padding: 14rpx 14rpx;
image {
width: 56rpx;
height: 56rpx;
margin: 0 10rpx;
flex: auto;
}
.btn {
flex: auto;
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
max-height: 160rpx;
margin: 0 10rpx;
}
.chat-send {
line-height: 44rpx;
}
.record {
line-height: 44rpx;
text-align: center;
font-size: 20rpx;
color: rgba(39, 40, 50, 0.6);
}
}
.emoji {
width: 100%;
height: 460rpx;
background: rgba(236, 237, 238, 1);
box-shadow: 0px 11rpx 0px 0px rgba(0, 0, 0, 0.1);
.emoji-send {
width: 280rpx;
height: 104rpx;
padding-top: 24rpx;
background-color: rgba(236, 237, 238, 0.8);
position: fixed;
// bottom: 0;
bottom: env(safe-area-inset-bottom);
right: 0;
display: flex;
.emoji-send-bt {
flex: 1;
margin: 0 32rpx 0 20rpx;
height: 80rpx;
background: rgba(255, 228, 49, 1);
font-size: 32rpx;
text-align: center;
line-height: 80rpx;
border-radius: 12rpx;
}
.emoji-send-det {
flex: 1;
margin-left: 24rpx;
height: 80rpx;
background: #fff;
font-size: 32rpx;
text-align: center;
line-height: 80rpx;
border-radius: 12rpx;
image {
width: 42rpx;
height: 32rpx;
}
}
}
}
.more {
width: 100%;
height: 436rpx;
background: rgba(236, 237, 238, 1);
box-shadow: 0px 11rpx 0px 0px rgba(0, 0, 0, 0.1);
bottom: env(safe-area-inset-bottom);
padding: 8rpx 20rpx;
box-sizing: border-box;
.more-list {
width: 25%;
text-align: center;
float: left;
padding-top: 32rpx;
image {
width: 72rpx;
height: 72rpx;
padding: 24rpx;
background: rgba(255, 255, 255, 1);
border-radius: 24rpx;
}
.more-list-title {
font-size: 24rpx;
color: rgba(39, 40, 50, 0.5);
line-height: 34rpx;
}
}
}
.voice-bg {
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
bottom: 0;
z-index: 1001;
.voice-bg-len {
height: 84rpx;
width: 600rpx;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 42rpx;
text-align: center;
}
.voice-bg-time {
display: inline-block;
min-width: 120rpx;
line-height: 84rpx;
background-color: rgba(255, 228, 49, 1);
border-radius: 42rpx;
}
.voice-del {
position: absolute;
bottom: -480rpx;
width: 100%;
text-align: center;
color: #fff;
font-size: 28rpx;
}
}
</style>
submit.vue中引入的組件
emoji.vue
<template>
<view class="emoji" :style="{height:height+'px'}">
<view class="emoji-line" v-for="(line,i) in emoji" :key="i">
<view class="emoji-line-item" v-for="(item,index) in line" :key="index" @tap="clickEmoji(item)">{{item}}
</view>
</view>
</view>
</template>
<script>
export default {
props:{
height:{
type:Number,
default:260
}
},
name: "emoji",
data() {
return {
emoji: [
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '??', '??', '??'],
['??', '??', '??', '??', '????', '???', '???'],
['????', '????', '????', '???', '????', '????', '????'],
['????', '??', '??', '??', '??', '??'] //'??',
]
};
},
methods: {
clickEmoji(e) {
this.$emit('emotion', e)
}
}
}
</script>
<style lang="scss">
.emoji {
width: 100%;
// height: 460rpx;
padding: 16rpx 10rpx 130rpx 10rpx;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
.emoji-line{
display: flex;
.emoji-line-item {
flex: 1;
text-align: center;
font-size: 44rpx;
line-height: 140rpx;
}
}
}
</style>
最后
很多靜態(tài)圖片圖片都是本地的,需要各位用自己的本地圖片代替。
以上就是uniapp模仿微信實現(xiàn)聊天界面的示例代碼的詳細內容,更多關于uniapp仿微信聊天界面的資料請關注腳本之家其它相關文章!
相關文章
vue3實現(xiàn)tabs導航欄點擊每個導航項有下劃線動畫效果
這篇文章主要介紹了vue3實現(xiàn)tabs導航欄點擊每個導航項有下劃線動畫效果,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-07-07
一文解決vue2 element el-table自適應高度問題
在寫公司后臺項目的時候遇到一個需求,要求表格頁面不能有滾動條,所以必須封裝一個公共方法來實現(xiàn)表格自適應高度,本問小編給大家介紹了如何解決vue2 element el-table自適應高度問題,需要的朋友可以參考下2023-11-11
vue 中使用 watch 出現(xiàn)了如下的報錯的原因分析
這篇文章主要介紹了vue 中使用 watch 出現(xiàn)了如下的報錯信息的原因分析及解決方法,本文附有代碼解決方案,非常不錯,需要的朋友可以參考下2019-05-05
Vue2.0實現(xiàn)將頁面中表格數(shù)據導出excel的實例
本篇文章主要介紹了Vue2.0實現(xiàn)將頁面中表格數(shù)據導出excel的實例,非常具有實用價值,感興趣的同學可以了解一下2017-08-08
解決echarts vue數(shù)據更新,視圖不更新問題(echarts嵌在vue彈框中)
這篇文章主要介紹了解決echarts vue數(shù)據更新,視圖不更新問題(echarts嵌在vue彈框中),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vue proxy 的優(yōu)勢與使用場景實現(xiàn)
這篇文章主要介紹了vue proxy 的優(yōu)勢與使用場景實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06

