官网学习链接:如何在 Vue 项目中使用 MQTT
github库:https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Vue.js
----要是直接进github库进不去,就先进 https://github.com/emqx/MQTT-Client-Examples/tree/master,再进入mqtt-client-Vue.js
分支。
(1)新建项目:自己选定一个文件夹,用于存放vue的文件,执行vue create mqtt_vue11
(2)安装 MQTT 客户端库:在 VSCode 中打开 vue 文件,新建一个终端,输入 npm install mqtt --save
home.scss
文件代码直接复制过来;main.js
文件代码复制过来。main.js
会添加 ‘element-ui’ 的相关依赖。如果不添加会报以下错误:import Vue from 'vue'
import App from './App.vue'
// Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
vue.config.js
文件代码:const { defineConfig } = require('@vue/cli-service')
const webpack = require("webpack");
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
process: "process/browser",
Buffer: ["buffer", "Buffer"],
}),
],
},
})
App.vue
文件代码:<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld,
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
HelloWorld.vue
文件代码:MQTT.js
,建议从笔者【lzl学习笔记:MQTT.js 入门教程】开始学习,先理解 mqtt.js
的机制,在搭建vue的MQTT项目,会更好理解一点。<template>
<div class="home-container">
<el-card shadow="always" style="margin-bottom:30px;">
<div class="emq-title">
Configuration
</div>
<el-form ref="configForm" hide-required-asterisk size="small" label-position="top" :model="connection">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item prop="host" label="Host">
<el-input v-model="connection.host"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="port" label="Port">
<el-input v-model.number="connection.port" type="number" placeholder="8083/8084"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="endpoint" label="Mountpoint">
<el-input v-model="connection.endpoint" placeholder="/mqtt"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="clientId" label="Client ID">
<el-input v-model="connection.clientId"> </el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="username" label="Username">
<el-input v-model="connection.username"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="password" label="Password">
<el-input v-model="connection.password"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-button
type="success"
size="small"
class="conn-btn"
style="margin-right: 20px;"
:disabled="client.connected"
@click="createConnection"
>
{{ client.connected ? 'Connected' : 'Connect' }}
</el-button>
<el-button v-if="client.connected" type="danger" size="small" class="conn-btn" @click="destroyConnection">
Disconnect
</el-button>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="always" style="margin-bottom:30px;">
<div class="emq-title">
Subscribe
</div>
<el-form ref="subscription" hide-required-asterisk size="small" label-position="top" :model="subscription">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item prop="topic" label="Topic">
<el-input v-model="subscription.topic"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="qos" label="QoS">
<el-select v-model="subscription.qos">
<el-option
v-for="(item, index) in qosList"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-button
:disabled="!client.connected"
type="success"
size="small"
class="subscribe-btn"
@click="doSubscribe"
>
{{ subscribeSuccess ? 'Subscribed' : 'Subscribe' }}
</el-button>
<el-button
:disabled="!client.connected"
type="success"
size="small"
class="subscribe-btn"
style="margin-left:20px"
@click="doUnSubscribe"
v-if="subscribeSuccess"
>
Unsubscribe
</el-button>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="always" style="margin-bottom:30px;">
<div class="emq-title">
Publish
</div>
<el-form ref="publish" hide-required-asterisk size="small" label-position="top" :model="publish">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item prop="topic" label="Topic">
<el-input v-model="publish.topic"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="payload" label="Payload">
<el-input v-model="publish.payload" size="small"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="qos" label="QoS">
<el-select v-model="publish.qos">
<el-option
v-for="(item, index) in qosList"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-col :span="24">
<el-button :disabled="!client.connected" type="success" size="small" class="publish-btn" @click="doPublish">
Publish
</el-button>
</el-col>
</el-card>
<el-card shadow="always" style="margin-bottom:30px;">
<div class="emq-title">
Receive
</div>
<el-col :span="24">
<el-input type="textarea" :rows="3" style="margin-bottom: 15px" v-model="receiveNews"></el-input>
</el-col>
</el-card>
</div>
</template>
<script>
import mqtt from 'mqtt'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
connection: {
host: 'broker.emqx.io',
port: 8083,
endpoint: '/mqtt',
clean: true, // 保留会话
connectTimeout: 4000, // 超时时间
reconnectPeriod: 4000, // 重连时间间隔
// 认证信息
clientId: 'emqx_vue_test_lzl',
username: 'emqx_test1',
password: 'emqx_test1',
},
subscription: {
topic: 'testtopic/lzl-MQTTX',
qos: 0,
},
publish: {
topic: 'topic/vue-browser-lzl',
qos: 0,
payload: '{ "msg": "Hello, I am browser." }',
},
receiveNews: '',
qosList: [
{ label: 0, value: 0 },
{ label: 1, value: 1 },
{ label: 2, value: 2 },
],
client: {
connected: false,
},
subscribeSuccess: false,
}
},
methods: {
// 创建连接
createConnection() {
// 连接字符串, 通过协议指定使用的连接方式
// ws 未加密 WebSocket 连接
// wss 加密 WebSocket 连接
// mqtt 未加密 TCP 连接
// mqtts 加密 TCP 连接
// wxs 微信小程序连接
// alis 支付宝小程序连接
const { host, port,endpoint, ...options } = this.connection //
const connectUrl = `ws://${host}:${port}${endpoint}`//broker.emqx.io:8083
try {
this.client = mqtt.connect(connectUrl, options)
} catch (error) {
console.log('mqtt.connect error', error)
}
this.client.on('connect', () => {
console.log('Connection succeeded!')
})
this.client.on('error', error => {
console.log('Connection failed', error)
})
this.client.on('message', (topic, message) => {
this.receiveNews = this.receiveNews.concat(message)
console.log(`Received message ${message} from topic ${topic}`)
})
},
// 订阅主题
doSubscribe() {
const { topic, qos } = this.subscription
this.client.subscribe(topic, { qos }, (error, res) => {
if (error) {
console.log('Subscribe to topics error', error)
return
}
this.subscribeSuccess = true
console.log('Subscribe to topics res', res)
})
},
// 取消订阅
doUnSubscribe() {
const { topic } = this.subscription
this.client.unsubscribe(topic, error => {
if (error) {
console.log('Unsubscribe error', error)
}
})
},
// 发送消息
doPublish() {
const { topic, qos, payload } = this.publish
this.client.publish(topic, payload, qos, error => {
if (error) {
console.log('Publish error', error)
}
})
},
// 断开连接
destroyConnection() {
if (this.client.connected) {
try {
this.client.end()
this.client = {
connected: false,
}
console.log('Successfully disconnected!')
} catch (error) {
console.log('Disconnect failed', error.toString())
}
}
},
},
}
</script>
<style lang="scss">
@import url('../assets/style/home.scss');
.home-container {
max-width: 1100px;
margin: 0 auto;
.conn-btn {
color: #fff;
background-color: #00b173;
font-size: 14px;
}
.publish-btn {
margin-bottom: 20px;
float: right;
}
.el-button--success {
background-color: #34c388 !important;
border-color: #34c388 !important;
font-size: 14px !important;
}
.el-button--danger {
background-color: #f5222d !important;
border-color: #f5222d !important;
}
.el-form-item {
&.is-error {
.el-input__inner,
.el-textarea__inner {
box-shadow: 0 0 0 2px rgba(245, 34, 45, 0.2);
}
}
&.is-success {
.el-input__inner,
.el-textarea__inner {
border-color: #34c388 !important;
}
}
}
}
</style>
(1)运行 / 调试项目最最令人头疼抓狂的了,因为很容易报错……
这一点不太好提供解决办法,只能靠读者遇到什么问题自行查询解决了(只能说,官方文档是没有问题的,鄙人曾经就调试崩溃到怀疑是官方文档的问题)
npm install url
npm install sass-loader
(2)当读者运行到此步,浏览器还没有报错的时候:那就恭喜读者接近胜利的曙光了
npm run serve
Connected
与【MQTTX客户端】建立连接。Subscribe
订阅话题。Publish
发布话题。(1)从最初接触到这一步搭建vue-MQTT项目,耗时2.5天