一、前期准备
1. 安装mqtt
npm install mqtt
2. 引入pinia,mqtt,ref响应式,配置mqtt连接参数
javascript
import { defineStore } from 'pinia' //引入pinia
import mqtt from 'mqtt' //引入mqtt
import { ref } from 'vue'
const mqttUrl = 'ws://broker.emqx.io:8083/mqtt' //连接地址
const options = { //配置连接参数
clean: true, //每次连接都是新对话
connectTimeout: 4000, //发起连接后,4秒没连上就失败
}
3. 创建变量
创建pinia实例,创建mqtt实例,添加mqtt是否连接标识,mqtt返回的消息体,需要订阅的列表
javascript
export const useMqttStore = defineStore('mqtt', () => {
const client = ref(null) //mqtt实例
const isConnected = ref(false) //mqtt连接标识
const messages = ref([]) //mqtt返回的消息列表
const subscribeTopics = ref([]) //订阅主题列表
二、连接mqtt
第 1 步:创建客户端 + 发起连接(真正连接的动作)
相当于拨打电话!!
javascript
// 连接 MQTT
const connect = () => {
//1.创建客户端
client.value = mqtt.connect(mqttUrl, options)
第 2 步:注册"连接成功"监听
client.value.on('connect' 这句的意思的,我只是注册了一个监听,监听connect事件。并不是主动连接成功,是被动的!!
连接需要时间,不是立刻连上的。 JS 不会卡住等它,而是继续跑后面代码。 (异步)
javascript
// 2.连接成功
client.value.on('connect', () => {
console.log('✅ MQTT 连接成功')
isConnected.value = true
subscribe()
})
第 3 步:订阅主题
如果监听到连接成功,那么一定要订阅主题
client.value.subscribe 这个订阅方法是主动的
MQTT 靠主题分发消息,订阅主题 = 告诉服务器:我只接收这个主题下的数据。
javascript
// 2. 订阅主题
const subscribe = () => {
if (!client.value || !isConnected.value) return
subscribeTopics.value.forEach((topic) => {
client.value.subscribe(topic, (err) => {
if (!err) console.log(`📥 已订阅:${topic}`)
})
})
}
第 4 步:注册"接收消息"监听
监听message事件:它的作用是: 告诉程序:一旦有消息来了,就按这个方法处理。
参数: topic 主题名称 、 message 消息内容
javascript
// 3.接收消息
client.value.on('message', (topic, message) => {
const msg = message.toString()
console.log('📩 收到消息:', topic, msg)
messages.value.push({ topic, message: msg })
})
第 5 步:注册"断开连接"相关的监听
1. 监听异常断开(断网、服务器挂了、超时)
javascript
client.value.on('close', () => {
console.log('❌ MQTT 连接断开(异常/掉线)')
isConnected.value = false // UI 必更新
})
2. 监听主动断开 你主动调用 client.value.end()(正常退出)
javascript
// 2.主动断开
client.value.on('disconnect', () => {
console.log('❌ MQTT 主动断开')
isConnected.value = false
})
**3. 监听被动断开 (**网络断了、WiFi 掉了、服务器崩溃 / 重启 等)
javascript
// 被动断开
client.value.on('offline', () => {
console.log('📴 MQTT离线');
isConnected.value = false;
});
4. 监听报错 (MQTT 服务器地址写错、端口号写错、用户名 / 密码错误、客户端 ID 重复 等)
一句话: 连都连不上,直接报错 → 触发 error
javascript
// 3.错误
client.value.on('error', (err) => {
console.error('❌ MQTT 错误:', err)
isConnected.value = false
})
5. 监听重连 (重连中)
当客户端检测到连接异常断开 ,MQTT.js 内置自动重连机制开始尝试重连时,每一次发起重连请求都会触发。
javascript
// 2. 正在重连(核心监听)
client.value.on('reconnect', () => {
console.log('🔄 MQTT 重连中...')
})
三、其他部分
1. 主动给mqtt发布消息
topic
你要发到哪个主题(频道) 比如:"device/light/switch"
payload
你要发的内容(消息体) 比如:"on"、"off"、{ temperature: 25 }
javascript
// 3. 发布消息
const publishMsg = (topic, payload) => {
if (!isConnected.value) {
alert('未连接 MQTT!')
return
}
client.value.publish(topic, payload, (err) => {
if (!err) console.log(`📤 发布成功:${topic}`)
})
}
2. 主动断开mqtt
client.value.end() 断开mqtt
javascript
// 4. 主动断开
const disconnectMqtt = () => {
if (client.value) {
client.value.end()
client.value = null
isConnected.value = false
console.log('✅ 手动断开 MQTT')
}
}
四、整体代码
javascript
import { defineStore } from 'pinia'
import mqtt from 'mqtt'
import { ref, onUnmounted } from 'vue'
// 公共 MQTT 服务器
const mqttUrl = 'ws://broker.emqx.io:8083/mqtt'
// 生成唯一 clientId(防止多人互踢)
const clientId = `mqtt_${Math.random().toString(16).slice(3)}`
const options = {
clean: true,
connectTimeout: 4000,
clientId, // 必须加!
}
export const useMqttStore = defineStore('mqtt', () => {
const client = ref(null)
const isConnected = ref(false)
const messages = ref([])
const subscribeTopics = ref([]) // 要订阅的主题数组
// =========================================
// 连接 MQTT(防重复连接)
// =========================================
const connect = () => {
// 已经连接 / 正在连接 → 直接返回
if (client.value || isConnected.value) return
// 创建客户端
client.value = mqtt.connect(mqttUrl, options)
// 连接成功
client.value.on('connect', () => {
console.log('✅ MQTT 连接成功')
isConnected.value = true
reSubscribe() // 重连后必须重新订阅!
})
// 收到消息
client.value.on('message', (topic, message) => {
const msg = message.toString()
console.log('📩 收到消息:', topic, msg)
messages.value.push({ topic, message: msg })
})
// 正在重连
client.value.on('reconnect', () => {
console.log('🔄 MQTT 重连中...')
isConnected.value = false // 重连中 = 未连接
})
// 连接断开
client.value.on('close', () => {
console.log('❌ MQTT 连接断开')
isConnected.value = false
})
// 离线
client.value.on('offline', () => {
console.log('📴 MQTT 离线')
isConnected.value = false
})
// 错误
client.value.on('error', (err) => {
console.error('❌ MQTT 错误:', err)
isConnected.value = false
})
}
// =========================================
// 订阅所有主题(重连时自动调用)
// =========================================
const reSubscribe = () => {
if (!client.value || !isConnected.value) return
const topics = subscribeTopics.value
if (topics.length === 0) {
console.log('⚠️ 暂无订阅主题')
return
}
topics.forEach((topic) => {
client.value?.subscribe(topic, (err) => {
if (!err) console.log(`📥 已订阅:${topic}`)
})
})
}
// =========================================
// 发布消息
// =========================================
const publishMsg = (topic, payload) => {
if (!isConnected.value || !client.value) {
alert('❌ MQTT 未连接')
return
}
client.value.publish(topic, payload, (err) => {
if (!err) console.log(`📤 发布成功:${topic}`)
})
}
// =========================================
// 主动断开(安全销毁)
// =========================================
const disconnectMqtt = () => {
if (client.value) {
client.value.end()
client.value = null
isConnected.value = false
messages.value = []
console.log('✅ 已手动断开 MQTT')
}
}
// =========================================
// 外部设置订阅主题数组
// =========================================
const subscribeArr = (arr) => {
subscribeTopics.value = arr
}
// =========================================
// 页面销毁时自动断开(重要!防内存泄漏)
// =========================================
onUnmounted(() => {
disconnectMqtt()
})
return {
client,
isConnected,
messages,
connect,
subscribeArr,
publishMsg,
disconnectMqtt,
}
})
四、总结
1. 安装
npm install mqtt
2. 基础连接
创建mqtt实例: let client = null
连接mqtt:client = mqtt.connect('ws://ip:port/mqtt')
监听连接成功:client.on('connect', () => {})
监听消息返回:client.on('message', (topic, msg) => {})
监听mqtt重连:client.on('reconnect', () => {})
监听mqtt错误:client.on('error', () => {})
监听mqtt断开:client.on('close', () => {})
javascript
import mqtt from 'mqtt'
let client = null
// 连接Broker
const connectMqtt = () => {
client = mqtt.connect('ws://ip:port/mqtt')
// 连接成功
client.on('connect', () => {})
// 接收消息
client.on('message', (topic, msg) => {})
// 重连、错误、断开
client.on('reconnect', () => {})
client.on('error', () => {})
client.on('close', () => {})
}
3. 订阅主题
javascript
client.subscribe('dev/data', { qos: 1 })
4. 发布消息
javascript
client.publish('dev/cmd', JSON.stringify(data), { qos: 1 })
5. 断开连接
javascript
client.end()
6. 常用配置
- qos:0/1/2 消息等级
- keepalive:心跳保活
- clean:是否清空历史会话