Maison > interface Web > js tutoriel > le corps du texte

Implémenter la fonction de chat de l'interface utilisateur WeChat

php中世界最好的语言
Libérer: 2018-03-19 16:38:56
original
2976 Les gens l'ont consulté

Cette fois, je vais vous expliquer comment implémenter la fonction de chat de WeChat UI. Quelles sont les précautions pour implémenter la fonction de chat de WeChat UI. Voici un cas pratique, jetons un coup d'œil.

Le mini-programme WeChat a été très populaire récemment. Dès que vous ouvrirez WeChat, il sera là. Vous pourrez en trouver une copie dans presque toutes les applications que vous utilisez. De plus, il est officiellement inclus Le saut. l'a poussé à une position élevée sans précédent. Par rapport au compte officiel, à mon avis, il y a les différences suivantes :

  • Le compte officiel est un peu plus lourd : je dois d'abord le suivre pour voir le contenu, alors que le mini-programme ne le fait pas (personnellement parlant, WeChat Le compte public n'est pas bien documenté, donc je m'excuse pour toute erreur)

  • Les performances du mini-programme sont meilleures : même si je Je ne sais pas exactement avec quoi le mini programme est implémenté, l'expérience est en effet un peu plus proche de celle native ; mais les comptes officiels WeChat affichent le contenu sous forme de pages Web, je n'ai pas besoin d'expliquer les problèmes de compatibilité et de performances. . Vous les luers le savez déjà bien

  • Les mini-programmes sont plus faciles à développer : Le mini-programme a publié un nouvel ensemble de règles de codage et fournit également une série de composants par rapport au compte public. Bai Jia soutient, la forme est en effet beaucoup plus unifiée

Après avoir dit tant de bêtises, je n'ai commencé que récemment à examiner la mise en œuvre de mini-programmes, j'en ai fait l'expérience et cela. est en effet assez agréable. Voici un résumé du développement personnel :

Mini programme simple du site officiel

Il y a un mini programme sur le site officiel de WeChat Simple petite démo, l'adresse est ici : https://mp.weixin.qq.com/debug/wxadoc/dev/index.html, suivez ses étapes, vous pouvez certainement en exécuter un et l'officiel. Le même exemple sort, donc je je ne publierai pas le processus ici. Parlez principalement de mes sentiments personnels généraux :

  • js est toujours le js original, css est toujours le css original, en termes de html, quelques choses ont été modifiées, par exemple : p devient vue, Text est devenu texte et img est devenu image, mais la soupe reste la même, comment l'utiliser est toujours la même et la sémantique est plus claire.

  • Ajout du fichier de configuration .json Il existe un app.json global, qui est une configuration globale, telle que la barre de navigation, la configuration des onglets et la configuration du routage global. . Attendez, et dans chaque page, une couverture globale peut toujours être effectuée. Par exemple, list.json spécifie séparément à quoi ressemble la page de liste.

  • Chaque page a un cycle de vie (y compris la page de démarrage), similaire au cycle de déclaration react/vue, ce qui rend plus clair ce qui peut être fait à quelle étape

  • Le code est composé de composants et de nombreux composants encapsulés peuvent être simplement référencés, tels que map Lors du développement sur le compte officiel WeChat, vous devrez peut-être également écrire un plug-in de carte. in

  • L'API est plus facile à utiliser. Bien que je n'ai pas développé beaucoup de comptes publics, le jssdk que j'ai configuré auparavant semble plus compliqué qu'un mini programme. Un mini programme n'a besoin que d'un appId. . Utilisez ensuite l'objet wx directement dans le code pour appeler diverses API

Développez un programme de chat simple similaire à WeChat UI

Je viens de faire une étude de cas. intéressant, les fonctions ne sont peut-être qu'une goutte d'eau dans l'océan, mais je pense qu'il est nécessaire de l'enregistrer et de parler des problèmes que j'ai rencontrés et des solutions. L'interface globale est la suivante :

Implémenter la fonction de chat de linterface utilisateur WeChat.

Tout d'abord, dans Ecrivez le parcours des pages en app.json comme suit :

{
  "pages":[        
    "pages/index/index",
    "pages/list/list",
    "pages/chat/chat"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#000",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle":"#fff"
  }}
Copier après la connexion

Il y a 3 pages ici Un bouton est placé sur la page d'accueil en guise d'entrée, la liste. La page représente l'historique des discussions et il existe une page de discussion.

Il n'y a rien à dire sur la page de liste. Vous pouvez définir le titre de la page de liste dans list.json, comme suit :

// list.json{
  "navigationBarTitleText": "聊天列表"}
Copier après la connexion

La page de liste simule certaines données, et puis cliquez sur Lorsque chaque message est saisi, une seule page de discussion est saisie, dans laquelle certaines informations actuellement cliquées doivent être transférées vers la page suivante. Ici, il n'y a que le nom.

//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
    })  }})
Copier après la connexion

Ensuite, entrez dans la page de chat. Tout d'abord, ce à quoi je pense en entrant dans la page de chat, c'est si chaque bulle et son avatar peuvent être transformés en un composant, car il n'y a qu'une distinction entre la gauche et la droite. . De plus, si vous ajoutez Si c'est l'heure, transmettez simplement le temps.

Donc chat.wxml c'était le plan initial :

<block>
  <template></template></block>
Copier après la connexion

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

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

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

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

Implémenter la fonction de chat de linterface utilisateur WeChat

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

遇到的一些问题:

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

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

针对这两个问题,我按照自己最初的想法是:进入页面获取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 });
  }
});
Copier après la connexion

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

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

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

扩展延伸

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

Implémenter la fonction de chat de linterface utilisateur WeChat-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);
  });});
Copier après la connexion

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)      })    }
  }})
Copier après la connexion

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

  • 头像

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

  • 数据库的历史消息存储

  • 图片以及语音的发送

  • 消息本地化存储

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

推荐阅读:

Vue指令的使用

JS闭包的使用

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!