开始

image.png

构建data数据

先来构建data数据
isme是否是好友发的,false 表示是好友发的、
image.png

  1. list: [{
  2. isme: false,
  3. userpic: "../../static/demo/userpic/11.jpg",
  4. type: "text",
  5. data: "哈哈哈",
  6. time: "1555146412"
  7. }]

最上面加一个时间
image.png

  1. <view class="user-chat-time u-f-ajc">11:10</view>

ajc垂直水平居中。
image.png

上下50内间距,左右为0
image.png
时间戳的转换
https://www.matools.com/timestamp
image.png
image.png
这里的时间戳是php生成的 10位的
image.png
js生成的话 后面有3个000
image.png
这里我们的后端也是PHP的所以这里还是用10位的
image.png
image.png

  1. list: [
  2. {
  3. isme: false,
  4. userpic: "../../static/demo/userpic/11.jpg",
  5. type: "text",
  6. data: "哈哈哈",
  7. time: "1555146412"
  8. },
  9. {
  10. isme: true,
  11. userpic: "../../static/demo/userpic/10.jpg",
  12. type: "img",
  13. data: "../../static/demo/3.jpg",
  14. time: "1555146414",
  15. }
  16. ]

循环数据

外层用block
image.png
时间先换成时间戳
image.png
左边是好友发过来的,右边是自己发过来的
image.png
取反代表 好友发送的消息,不是自己发的
image.png

image.png

image.png
如果是文本就显示文本信息。
image.png
如果是图片 就显示图片
image.png

  1. <block v-for="(item,index) in list" :key="index">
  2. <view class="user-chat-time u-f-ajc">{{item.time}}</view>
  3. <view class="user-chat-list u-f user-chat-me">
  4. <image v-if="!item.isme" :src="item.userpic" mode="widthFix"
  5. lazy-load="true"></image>
  6. <view class="user-chat-list-body">
  7. <text v-if="item.type=='text'">{{item.data}}</text>
  8. <image v-if="item.type=='img'" :src="item.data" mode="widthFix" lazy-load="true"></image>
  9. </view>
  10. <image v-if="item.isme" :src="item.userpic" mode="widthFix" lazy-load="true"></image>
  11. </view>
  12. </block>

image.png
这是因为这个样式引起的
image.png
如果是isme是true的时候才添加user-chat-me的class属性
image.png

先把时间栏 暂时屏蔽
image.png

  1. <view class="user-chat-list u-f" :class="{'user-chat-me':item.isme}">

image.png

左边聊天框的小箭头,位置不合适,自己又调整了一下,主要是left

  1. left: -50upx;

增加内边距。上下20 左右为0
image.png

  1. .user-chat-list {
  2. padding: 20upx 0;
  3. }

image.png

处理时间戳

时间转换的工具库,这个是事先写好的
image.png

image.png
判断时间戳是否小于13位,就乘以1000
image.png
当天,隔天,隔年。 当前时间减去传过来的时间戳 判断 当天。隔天 和隔年
image.png

使用工具类

image.png
测试数据。在onLoad的方法里面测试 转换前和转换后的时间戳数据。
image.png

image.png
今天的时间
image.png
今天的时间就显示下午
image.png

image.png

image.png
所以在这里直接调用方法是不支持的
image.png
假设这里就是从服务器上获取到的数据
image.png
一定要在页面加载的时候调用
image.png
循环拿到的数据,单独给时间戳字段进行转换。
image.png
相当于增加一个字段属性,把转换后的属性值复制给这个新的字段。
image.png

image.png

image.png

  1. getData() {
  2. // 从服务器获取到的数据
  3. let arr = [{
  4. isme: false,
  5. userpic: "../../static/demo/userpic/11.jpg",
  6. type: "text",
  7. data: "哈哈哈",
  8. time: "1555146412"
  9. },
  10. {
  11. isme: true,
  12. userpic: "../../static/demo/userpic/10.jpg",
  13. type: "img",
  14. data: "../../static/demo/3.jpg",
  15. time: "1555146414",
  16. },
  17. ];
  18. for (let i = 0; i < arr.length; i++) {
  19. arr[i].gstime = time.gettime.getChatTime(arr[i].time, i > 0 ? arr[i - 1].time : 0);
  20. }
  21. this.list = arr;
  22. },

这样就是转换后的数据了
image.png
改成相差不久的时间
image.png
如果时间都在某个时间段之内。 只会显示一个。
image.png
两个信息如果相差300秒 不会显示时间的。
image.png
传入上一条信息的时间
image.png
第0条的情况。
image.png
只会显示第一条。
image.png
超过300秒
image.png

image.png
如果格式的时间没有的话, 就隐藏当前view这一行。这样他们之间的距离就会减少一点边距。
image.png

  1. <view v-if="item.gstime" class="user-chat-time u-f-ajc">{{item.gstime}}</view>

image.png

封装组件

封装list组件
image.png
剪切走
image.png

  1. <view v-if="item.gstime" class="user-chat-time u-f-ajc">{{item.gstime}}</view>
  2. <view class="user-chat-list u-f" :class="{'user-chat-me':item.isme}">
  3. <image v-if="!item.isme" :src="item.userpic" mode="widthFix" lazy-load="true"></image>
  4. <view class="user-chat-list-body">
  5. <text v-if="item.type=='text'">{{item.data}}</text>
  6. <image v-if="item.type=='img'" :src="item.data" mode="widthFix" lazy-load="true"></image>
  7. </view>
  8. <image v-if="item.isme" :src="item.userpic" mode="widthFix" lazy-load="true"></image>
  9. </view>

最外层套一个view
image.png

全部的css也剪切过来
image.png
传入的属性
image.png

  1. <script>
  2. export default{
  3. props:{
  4. item: Object,
  5. index: Number
  6. }
  7. }
  8. </script>

引入组件

image.png

  1. import userChatList from '@/components/user-list/user-chat-list.vue';

image.png

  1. <user-chat-list :item="item" :index="index"></user-chat-list>

image.png

本节代码

user-chat-list组件

  1. <template>
  2. <view>
  3. <view v-if="item.gstime" class="user-chat-time u-f-ajc">{{item.gstime}}</view>
  4. <view class="user-chat-list u-f" :class="{'user-chat-me':item.isme}">
  5. <image v-if="!item.isme" :src="item.userpic" mode="widthFix" lazy-load="true"></image>
  6. <view class="user-chat-list-body">
  7. <text v-if="item.type=='text'">{{item.data}}</text>
  8. <image v-if="item.type=='img'" :src="item.data" mode="widthFix" lazy-load="true"></image>
  9. </view>
  10. <image v-if="item.isme" :src="item.userpic" mode="widthFix" lazy-load="true"></image>
  11. </view>
  12. </view>
  13. </template>
  14. <script>
  15. export default{
  16. props:{
  17. item: Object,
  18. index: Number
  19. }
  20. }
  21. </script>
  22. <style scoped>
  23. .user-chat-list {
  24. padding: 20upx 0;
  25. }
  26. .user-chat-list>image {
  27. width: 100upx;
  28. height: 100upx;
  29. border-radius: 100%;
  30. flex-shrink: 0;
  31. }
  32. /* 聊天背景 */
  33. .user-chat-list-body {
  34. position: relative;
  35. background: #f4f4f4;
  36. padding: 25upx;
  37. margin-left: 20upx;
  38. border-radius: 20upx;
  39. margin-right: 100upx;
  40. }
  41. .user-chat-list-body:after {
  42. position: absolute;
  43. left: -50upx;
  44. right: 0;
  45. top: 20upx;
  46. content: '';
  47. width: 0;
  48. height: 0;
  49. border: 16px solid #F4F4F4;
  50. border-color: transparent #F4F4F4 transparent transparent;
  51. }
  52. .user-chat-me {
  53. justify-content: flex-end;
  54. }
  55. .user-chat-me .user-chat-list-body {
  56. margin-right: 20upx;
  57. margin-left: 100upx;
  58. }
  59. .user-chat-me .user-chat-list-body:after {
  60. left: auto;
  61. right: -56upx;
  62. border-color: transparent transparent transparent #F4F4F4;
  63. }
  64. .user-chat-list-body>image {
  65. max-width: 150upx;
  66. max-height: 200upx;
  67. }
  68. .user-chat-time {
  69. padding: 50upx 0;
  70. color: #a2a2a2;
  71. font-size: 24upx;
  72. }
  73. </style>

user-chat页面

  1. <template>
  2. <view>
  3. <!-- 聊天列表 -->
  4. <block v-for="(item,index) in list" :key="index">
  5. <user-chat-list :item="item" :index="index"></user-chat-list>
  6. </block>
  7. <!-- 输入框 -->
  8. <user-chat-bottom @submit="submit"></user-chat-bottom>
  9. </view>
  10. </template>
  11. <script>
  12. import userChatBottom from '@/components/user-chat/user-chat-bottom.vue';
  13. import time from '../../common/time.js';
  14. import userChatList from '@/components/user-list/user-chat-list.vue';
  15. export default {
  16. components: {
  17. userChatBottom,
  18. userChatList
  19. },
  20. data() {
  21. return {
  22. list: [{
  23. isme: false,
  24. userpic: "../../static/demo/userpic/11.jpg",
  25. type: "text",
  26. data: "哈哈哈",
  27. time: "1555146412"
  28. },
  29. {
  30. isme: true,
  31. userpic: "../../static/demo/userpic/10.jpg",
  32. type: "img",
  33. data: "../../static/demo/3.jpg",
  34. time: "1555146414",
  35. }
  36. ]
  37. }
  38. },
  39. onLoad() {
  40. this.getData();
  41. },
  42. methods: {
  43. getData() {
  44. // 从服务器获取到的数据
  45. let arr = [{
  46. isme: false,
  47. userpic: "../../static/demo/userpic/11.jpg",
  48. type: "text",
  49. data: "哈哈哈",
  50. time: "1555146412"
  51. },
  52. {
  53. isme: true,
  54. userpic: "../../static/demo/userpic/10.jpg",
  55. type: "img",
  56. data: "../../static/demo/3.jpg",
  57. time: "1555146414",
  58. },
  59. ];
  60. for (let i = 0; i < arr.length; i++) {
  61. arr[i].gstime = time.gettime.getChatTime(arr[i].time, i > 0 ? arr[i - 1].time : 0);
  62. }
  63. this.list = arr;
  64. },
  65. submit(data) {
  66. console.log(data);
  67. }
  68. }
  69. }
  70. </script>
  71. <style>
  72. </style>

结束