微信小程序开发之——WebSocket通信-示例(2)

一 概述

  • 服务器端使用Node.js搭建,接收到消息后,返回一条消息“自动回复”
  • 小程序端模拟聊天对话,右侧是用户端(发送消息后),左侧是Socket回复消息
  • 小程序底部,输入框输入内容,点击发送按钮发送给服务器

二 示例逻辑介绍

  • 在onLoad方法中,小程序连接Node服务器
  • 当输入框中输入内容,并点击发送按钮,此时的role为用户端,显示在右侧
  • 当输入框中内容为空时,提示消息不能为空哦~
  • 服务器端接收到用户发来的消息,返回自动回复,此时的role为服务端,显示在左侧
  • 发送完成后,页面滚动到底部

三 WebSocket通信示例—服务器

3.1 安装package.json中依赖

1
npm install

3.2 启动服务

1
node socket.js

四 WebSocket通信示例—小程序

4.1 布局文件(index.wxml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<view class="wrap">
<scroll-view scroll-y class="chat" scroll-top="{{scrollTop}}">
<view class="list">
<view class="chat-news" wx:for="{{list}}" wx:key="{{item.id}}">
<!--根据角色判断-->
<block wx:if="{{item.role==='me'}}">
<!--自己的消息显示在右侧-->
<view class="news-lf">
<text class="new-txt">{{item.content}}</text>
<image class="new-img" src="/images/man.png"></image>
</view>
</block>
<!--对方的消息显示在左侧-->
<block wx:else>
<view>
<image class="new-img" src="/images/women.png"></image>
<text class="new-txt new-text">{{item.content}}</text>
</view>
</block>
</view>
</view>
</scroll-view>
</view>
<!--聊天输入-->
<view class="message">
<form>
<input type="text" cursor-spacing="20" bindinput="bindChange" placeholder="请输入聊天内容..." />
<button type="primary" bindtap="send" form-type="reset" size="mini">发送</button>
</form>
</view>

4.2 样式文件(index.wxss)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
page{
background-color: #f7f7f7;
height: 100%;
}
.wrap{
width: 100%;
height: 100%;
display: flex;
border-top: 0px;
box-sizing: border-box;
}

.chat{
padding: 5rpx 10rpx;
font-size: 14px;
line-height: 80rpx;
word-break: break-all;
margin-bottom: 100rpx;
box-sizing: border-box;
}
/* 聊天*/
.chat-news{
width: 100%;
overflow: hidden;
}
.news-lf{
float: right;
padding-right: 20rpx;
}
.chat-news::after{
display: block;
height: 0;
clear: both;
content: '';
}
.new-rl{
float: left;
padding-left: 20rpx;
}
.new-img{
width: 60rpx;
height: 60rpx;
border-radius: 50%;
vertical-align: middle;
margin-right: 10rpx;
}
.new-txt{
max-width: 300rpx;
display: inline-block;
border-radius: 6rpx;
line-height: 60rpx;
background: #95d4ff;
padding: 5rpx 20rpx;
margin: 0 10rpx;
margin-left: 50rpx;
}
.new-text{
margin-left: 0;
background: lightgreen;
}
/* 信息输入区域*/
.message{
position: fixed;
bottom: 0;
width: 100%;
height: 102rpx;
padding: 10rpx;
background-color: #fff;
border-top: 2rpx solid #eee;
box-sizing: border-box;
z-index: 3;
}
.message input{
float: left;
width: 76%;
height: 100%;
line-height: 80rpx;
padding: 0 10rpx;
font-size: 35rpx;
color: #666;
}
.message button{
float: right;
font-size: 35rpx;
}

4.3 逻辑文件(index.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
Page({
/**
* 页面的初始数据
*/
data: {
scrollTop: 0,
list: []
},
id: 0,
/** 生命周期函数--监听页面加载*/
onLoad: function (options) {
wx.connectSocket({
//本地服务器地址
url: 'ws://localhost:3000',
})
//连接成功
wx.onSocketOpen((res) => {
console.log('连接成功')
})
wx.onSocketMessage((res) => {
var data = JSON.parse(res.data)
data.id = this.id++
data.role = 'server'
var list = this.data.list
list.push(data)
this.setData({
list: list
})
this.rollingBottom()
})
},
//发送内容
message: '',
send() {
//判断发送内容是否为空
if (this.message) {
wx.sendSocketMessage({
data: this.message,
})
//我自己的消息
console.log(this.data.list)
var list = this.data.list
list.push({
id: this.id++,
content: this.message,
role: 'me'
})
this.setData({
list: list
})
this.rollingBottom()
} else {
//弹出提示框
wx.showToast({
title: '消息不能为空哦~',
icon: 'none',
duration: 2000
})
}
},
//监听Input值的改变
bindChange(res) {
this.message = res.detail.value
},
//页面卸载,关闭连接
onUnload: function () {
wx.closeSocket()
console.log('连接已断开')
},
//聊天内容始终显示在最低端
rollingBottom(e) {
wx.createSelectorQuery().selectAll('.list').boundingClientRect(rects => {
rects.forEach(rect => {
this.setData({
scrollTop: rect.bottom
})
})
}).exec()
}
})

4.4 效果图

小程序端 服务器端

五 参考代码

  • 参考代码