Home > Web Front-end > JS Tutorial > Implement the chat function of WeChat UI

Implement the chat function of WeChat UI

php中世界最好的语言
Release: 2018-03-19 16:38:56
Original
3085 people have browsed it

This time I will bring you the implementation of the chat function of WeChat UI. What are the precautions for implementing the chat function of WeChat UI. The following is a practical case, let’s take a look.

WeChat mini programs are very popular recently. To the extent that they are popular, as soon as you open WeChat, you will see it. You can find a copy of it in almost every APP you use. In addition, it is officiImplement the chat function of WeChat UIy included. The jump pushed it to an unprecedented high position. Comparing the official account, as far as I feel, there are the following differences:

  • The official account is a bit cumbersome: I have to follow it first to see the content, while the mini program does not (personImplement the chat function of WeChat UIy, I have to pay attention to WeChat The public account is not well researched, so I apologize for any mistakes)

  • The performance of the mini program is better: although I don’t know exactly what the mini program is used to implement, the experience is indeed closer to the native one A little; but the WeChat official account displays content in the form of web pages. I don’t need to explain the compatibility and performance issues. You luers already know it.

  • Mini programs are easier to develop : The mini program has released a new set of code rules and also provides a series of components. Compared with the public account Bai Jia contending, the form is indeed much more unified

Having said so much nonsense, I I have only recently begun to look at the implementation of mini programs. I have experienced it and it is indeed quite enjoyable. The following is a summary of my personal development:

Simple official website mini program

There is a mini program on the official website of WeChat Simple smImplement the chat function of WeChat UI demo, the address is here: https://mp.weixin.qq.com/debug/wxadoc/dev/index.html, follow its steps, you can definitely run one and the official one The same example comes out, so I won’t post the process here. Mainly talk about my overImplement the chat function of WeChat UI personal feelings:

  • js is still the original js, css is still the original css, in terms of html, some things have been changed, for example: p becomes view, Text has become text, and img has become image, but the soup remains the same, how to use it is still the same, and the semantics are clearer.

  • Added configuration file .json, there is a global app.json, which is the global configuration, such as The configuration of the navigation bar, TAB, global routing configuration, etc. can still be globImplement the chat function of WeChat UIy covered in each page. For example, list.json separately stipulates what the list page looks like.

  • Each page has a life cycle (including startup page), similar to the declaration cycle of react/vue, which is more clear What can be done at this stage?

  • The code is componentized, and many encapsulated components can be simply referenced, such as map. When developing on the WeChat official account, you You may also need to write a dedicated map plug-in

  • The API is more user-friendly. Although I have not developed many public accounts, as far as the jssdk configured before is concerned, it feels more complicated than a smImplement the chat function of WeChat UI program. The mini program only needs an appId, and then use the wx object directly in the code to cImplement the chat function of WeChat UI various APIs

to develop a simple chat program similar to WeChat UI

I was just interested and made a case. The functions may be just a drop in the bucket, but I feel it is necessary to record it and talk about the problems I encountered and the solutions. The overImplement the chat function of WeChat UI interface is as follows:

Implement the chat function of WeChat UI

First, write the page route in app.json, as follows:

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

There are 3 pages here, and a button is placed on the homepage as the entrance. The list page represents the chat history, and there is also a chat page.

There is nothing to say about the list page. Setting the title of the list page can be set in list.json, as follows:

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

The list page simulates some data , and then when you click on each item, you will enter a single chat page, where you need to transfer some of the currently clicked information to the next page, where there is only the name.

//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
    })  }})
Copy after login

Then enter the chat page. First, what I think about when entering the chat page is whether each bubble and its avatar can be made into a component, because there is only a distinction between left and right. In addition, if time is added , and then just pass the time.

So chat.wxml was originImplement the chat function of WeChat UIy planned like this:

<block>
  <template></template></block>
Copy after login

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

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

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

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

Implement the chat function of WeChat UI

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

遇到的一些问题:

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

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

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

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

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

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

// chat.wxml<scroll-view>
    <block>
      <template></template>    </block>
  </scroll-view>// 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 });
  }
});
Copy after login

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

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

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

扩展延伸

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

Implement the chat function of WeChat UI-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);
  });});
Copy after login

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)      })    }
  }})
Copy after login

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

  • 头像

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

  • 数据库的历史消息存储

  • 图片以及语音的发送

  • 消息本地化存储

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Vue指令的使用

JS闭包的使用

The above is the detailed content of Implement the chat function of WeChat UI. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template