实现微信UI的聊天功能

这次给大家带来实现微信UI的聊天功能,实现微信UI的聊天功能的注意事项有哪些,下面就是实战案例,一起来看一下。

微信小程序最近很火,火到什么程度,只要你一打开微信,就是它的身影,几乎你用的各个APP都可以在微信中找到它的复制版,另外官方自带的跳一跳更是将它推到了空前至高的位置。对比公众号,就我的感觉来说,有以下区别:

公众号略显繁琐:我首先要关注才能看到内容,而小程序不用(个人对微信公众号研究不深,不对之处还望见谅)

小程序性能要好一些:虽然我不是很清楚小程序用什么实现,就体验来说确实更接近原生一点;但是微信公众号是用网页的形式来展示内容的,其中的兼容性和性能问题不用我说,各位luer就已经清楚了吧

小程序更易开发:小程序发布了一套新的代码规则,也提供了一系列的组件,对比公众号百家争鸣的形式确实要统一得多

废话说了这么多,我也是最近才开始看小程序的实现方式,体验了一把,确实比较爽,以下就是个人开发总结:

简易的官网小程序

微信小程序官网中有个简单的小demo,地址在这里:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html,按照它的步骤来,一定是可以运行一个和官方一样的例子出来的,这里就不贴过程了。主要说一下个人整体感受:

js还是原来的js,css还是原来的css,html方面来说,是改了一点东西,比如:p变成了view,文本变成了text,以及img变成了image,但是换汤不换药,该怎么用还是怎么用,而且语义也更加明确。

增加了配置文件.json,全局有一个app.json,是全局的配置,比如导航栏、TAB的配置,全局路由的配置等等,而在每个页面中,依然是可以进行全局覆盖的,比如list.json中单独规定了列表页面长啥样子。

每个页面都具有生命周期(包括启动页),类似于react/vue的声明周期,更加明确在哪个阶段可以做哪些事情

代码组件化,很多封装的组件都可以简单引用,比如map,而在微信公众号上开发的时候,你可能还需要专门写一个地图插件

API更加好用,虽然我没多少开发过公众号,但是就之前配置的jssdk来说,就感觉比小程序复杂,小程序只需要一个appId就可以了,然后在代码中直接使用wx对象来调用各种API

开发一个类似微信UI的简单聊天程序

只是感兴趣稍微做了一下案例,其中功能可能根本就还只是九牛一毛,但是觉得有必要记录一下,说说自己遇到的问题以及解决办法,界面整体如下:

all

首先,在app.json中编写页面路由,如下:

{  "pages":[            "pages/index/index",    "pages/list/list",    "pages/chat/chat"  ],  "window":{    "backgroundTextStyle":"light",    "navigationBarBackgroundColor": "#000",    "navigationBarTitleText": "WeChat",    "navigationBarTextStyle":"#fff"  }}

登录后复制

这里有3个页面,首页放一个按钮作为入口,列表页表示聊天记录,还有一个聊天页。

列表页没有什么可以讲的,设置列表页的标题可以在list.json中设置即可,如下:

// list.json{  "navigationBarTitleText": "聊天列表"}

登录后复制

列表页模拟了一些数据,然后再点击每一条的时候,进入单个聊天页面当中,其中需要将当前点击的一些信息传入下一个页面当中,这里仅仅只有名字。

//chat.js//获取应用实例const app = getApp()const friends = require('./list-mock-data.js')Page({  data: {    friends: friends.list  },  gotoChat(event) {    const currentUser = event.currentTarget.dataset.user;    wx.navigateTo({      url: '../chat/chat?nickname=' + currentUser.nickname    })  }})

登录后复制

然后进入聊天页面,首先进入聊天页面我想到的是,每一个气泡加上它的头像是否可以做成一个组件,因为只有左右的区分而已,另外如果再加上时间的话,再将时间传递过去就可以了。

因此chat.wxml最开始就是这样规划的:

  

登录后复制

template中的代码就不展示了,最开始我写模板的时候,是开了一个codePen,然后模拟写出来之后,再往模板中套,保证基本的样子差不多,然后再在模板上进行细微的改动就可以了。

聊天页顶部的标题是通过列表页中传过来的,在页面加载完成的时候,设置就好了:

// chat.js// 设置昵称setNickName(option) {    const nickname = option.nickname || 'Marry';    wx.setNavigationBarTitle({      title: nickname    });  },

登录后复制

最开始的样子就是这样子的:

first-chat

至此,基本的页面形态就已经完成了。

遇到的一些问题:

每次进入页面的时候,即使聊天内容已经超过了聊天区域,都会显示为最开始的地方

输入新的聊天记录的时候,如果聊天内容不是处于最底部,那么新加的内容会看不到

针对这两个问题,我按照自己最初的想法是:进入页面获取scrollHieght然后计算scrollTop值,将其滚动就好了,至于第二个问题按照类似的方法就可以解决了,但是我查看小程序的API之后,并没有发现如何计算scrollHeight的方法。只有类似的API,如:boundingClientRect和scrollTop

好在天无绝人之路,看到了scroll-view中的scroll-into-view属性,于是就想出了解决上面两个问题的方法:

进入页面,获取历史纪录,获取最后一条消息的ID值,记为lastId,在渲染的时候,消息列表中的每个ID值传入组件,作为每个消息记录的唯一标识,然后使用scroll-in-view={{ id }}就可以轻松地使最后一条消息进入视野当中

在聊天的时候,新加的记录会更新这个lastId值,这样就自动更新视图了

// chat.wxml                // chat.jsPage({  data: {    messages: [],         // 聊天记录    msg: '',              // 当前输入    lastId: ''            // 最后一条消息的ID    // ...  },  // ...  send() {    // ...    const data = {      id: `msg${++nums}`,      message: msg,      messageType: 0,      url: '../../images/5.png'    };    this.setData({ msg: '', lastId: data.id });  }});

登录后复制

这样就可以大致实现类似于聊天的效果了,但是还有一个小问题,每次从列表中进入单个聊天页面的时候,会有一个斜向左上方滑动的过程,原因是:页面的转场动画是向左的,但是自动滚动到最后一条记录的动作是向上的,所以会有动作叠加,既然这样,我只需要让滚动的过程延迟一段时间就好

// 延迟页面向顶部滑动  delayPageScroll() {    const messages = this.data.messages;    const length = messages.length;    const lastId = messages[length - 1].id;    setTimeout(() => {      this.setData({ lastId });    }, 300);  },

登录后复制

至此问题就算是解决了,在真机模拟的时候,IOS还有一个问题,就是当点击输入框的时候,整体页面会向上顶起来,这个问题我在论坛中也有看到,但是没有找到解决办法,如果各位有遇到,还望不吝赐教。

扩展延伸

如果是一个真正的聊天程序应该怎么做呢?我的设想是这样的:

first-chat-one

由于当时自己的机器由于莫名的原因不能够进行登录,后来采用了本地开了一个websocket的服务器来实现消息的发送。服务器代码相当简单,只是消息的转发而已

// server.jsconst WebSocket = require('ws');const wss = new WebSocket.Server({ port: 12112 });wss.on('connection', ws => {  console.log('connection established');  ws.on('message', message => {    console.log("on message coming");    ws.send(message);  });});

登录后复制

在chat.js中需模拟历史消息的发送以及新加消息的发送,因此代码整体看起来是这样的:

//chat.js//获取应用实例const app = getApp()const msgs = require('./chat-mock-data.js');Page({  data: {    messages: [],         // 聊天记录    msg: '',              // 当前输入    scrollTop: 0,         // 页面的滚动值    socketOpen: false,    // websocket是否打开    lastId: '',           // 最后一条消息的ID    isFirstSend: true     // 是否第一次发送消息(区分历史和新加)  },  onLoad(option) {    // 设置标题    this.setNickName(option);  },  //事件处理函数  onReady() {    // 连接websocket服务器    this.connect();  },  onUnload() {    const socketOpen = this.data.socketOpen;    if (socketOpen) {      wx.closeSocket({});      wx.onSocketClose(res => {        console.log('WebSocket 已关闭!')      });    }  },  connect() {    wx.connectSocket({      url: 'ws://localhost:12112'    });    wx.onSocketOpen(res => {      this.setData({ socketOpen: true });      // 模拟历史消息的发送      wx.sendSocketMessage({        data: JSON.stringify(msgs),      })    });    wx.onSocketMessage(res => {      const isFirstSend = this.data.isFirstSend;      const data = JSON.parse(res.data);      let messages = this.data.messages;      let lastId = '';            // 第一次为接收历史消息,      // 之后的为新加的消息      if (isFirstSend) {        messages = messages.concat(data);        lastId = messages[0].id;        this.setData({ messages, lastId, isFirstSend: false });        // 延迟页面向顶部滑动        this.delayPageScroll();      } else {        messages.push(data);        const length = messages.length;        lastId = messages[length - 1].id;        this.setData({ messages, lastId });      }    });    wx.onSocketError(res => {      console.log(res);      console.log('WebSocket连接打开失败,请检查!')    })  },  // 设置昵称  setNickName(option) {    const nickname = option.nickname || 'Marry';    wx.setNavigationBarTitle({      title: nickname    });  },  // 延迟页面向顶部滑动  delayPageScroll() {    const messages = this.data.messages;    const length = messages.length;    const lastId = messages[length - 1].id;    setTimeout(() => {      this.setData({ lastId });    }, 300);  },  // 输入  onInput(event) {    const value = event.detail.value;    this.setData({ msg: value });  },  // 聚焦  onFocus() {    this.setData({ scrollTop: 9999999 });  },  // 发送消息  send() {    const socketOpen = this.data.socketOpen;    let messages = this.data.messages;    let nums = messages.length;    let msg = this.data.msg;    if (msg === '') {      return false;    }    const data = {      id: `msg${++nums}`,      message: msg,      messageType: 0,      url: '../../images/5.png'    };    this.setData({ msg: '' });        if (socketOpen) {      wx.sendSocketMessage({        data: JSON.stringify(data)      })    }  }})

登录后复制

整体来说,自己的思路就像是上面的代码所描述的,这个只是初步的构想,还有很多东西需要完善:

头像

列表页和聊天页新消息的处理

数据库的历史消息存储

图片以及语音的发送

消息本地化存储

相信看了本文案例你已经掌握了方法,更多精彩请关注【创想鸟】其它相关文章!

推荐阅读:

Vue指令的使用

JS闭包的使用

以上就是实现微信UI的聊天功能的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2780599.html

(0)
上一篇 2025年3月8日 16:05:19
下一篇 2025年2月25日 05:58:06

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • js中的日期实现方法

    本文主要和大家分享js中的日期实现方法,主要以代码的形式,希望能帮助到大家。 1.简单明了,直接new date(),然后就照着来就是了: var myDate = new Date(); myDate.getYear(); //获取当前年…

    编程技术 2025年3月8日
    200
  • 用js实现html转pdf

    这次给大家带来用js实现html转pdf,用js实现html转pdf的注意事项有哪些,下面就是实战案例,一起来看一下。 于是做了个小案例来测试这个功能。 生成PDF 登录后复制 js写法 window.onload =function(){…

    编程技术 2025年3月8日
    200
  • jquery 分页的两种实现方法

    本文主要和大家分享jquery pagination 分页的两种实现方法,此插件是jQuery的ajax分页插件。如果你用到此插件作分页的时候,涉及到的数据量大,可以采用异步加载数据,当数据不多的时候,直接一次性加载,方便简单。 一:下载地…

    编程技术 2025年3月8日
    200
  • 原生js实现轮播图

    本文主要和大家分享原生js实现轮播图,主要以代码形式,希望能帮助到大家。 nbsp;html>     /*重置样式*/ *{margin: 0;padding: 0; list-style: none;} /*wrap的轮播图和切换…

    编程技术 2025年3月8日
    200
  • vue.js实现单次弹框

    这次给大家带来vue.js实现单次弹框,vue.js实现单次弹框的注意事项有哪些,下面就是实战案例,一起来看一下。 核心代码是 getCookie()部分,控制弹框的显示隐藏则在 created()中。 Lorem ipsum dolor …

    编程技术 2025年3月8日
    200
  • 微信小程序开发图片压缩功能

    这次给大家带来微信小程序开发图片压缩功能,微信小程序开发图片压缩功能的注意事项有哪些,下面就是实战案例,一起来看一下。 小龙大哥的微信小程序在初始阶段相当于IE界的6,在这里给大家说一个刚趟过去的坑。 拍照的API。 wx.chooseIm…

    编程技术 2025年3月8日
    200
  • Vue2.5与Element UI的组件分页功能实现

    这次给大家带来Vue2.5与Element UI的组件分页功能实现,Vue2.5与Element UI的组件分页功能实现的注意事项有哪些,下面就是实战案例,一起来看一下。 2017年底了,总结了这一年多来的前端之路,Vue从入门到放弃,再二…

    编程技术 2025年3月8日
    200
  • 网页页面实现加载进度条

    这次给大家带来网页页面实现加载进度条,网页页面实现加载进度条的注意事项有哪些,下面就是实战案例,一起来看一下。 页面加载进度条最初我是在youtube上看到的,后面几乎在各大网站上都能见到它的身影,可以让用户在加载页面的时候不会对着完全空白…

    编程技术 2025年3月8日
    200
  • node+express实现聊天室

    这次给大家带来node+express实现聊天室,node+express实现聊天室的注意事项有哪些,下面就是实战案例,一起来看一下。 本篇文章使用node+express+jquery写一个个性化聊天室,一起来get一下~(源码地址见文章…

    2025年3月8日 编程技术
    200
  • Vue枚举类型实现HTML

    这次给大家带来Vue枚举类型实现HTML,Vue枚举类型实现HTML的注意事项有哪些,下面就是实战案例,一起来看一下。 下拉框包含option中的Value和用来显示的选项, 一般后台都是使用的Value值,而不是显示在前台的选项 第一步:…

    2025年3月8日
    200

发表回复

登录后才能评论