Vue+Element Ui 实现MQTT连接,关闭,订阅,发布功能的Vue组件

1.简述

项目采用的前端框架为Vue,界面UI采用Element Ui ,MQTT协议采用mqtt.js,该demo为毕设项目中的一个小模块,可以实现MQTT的连接,关闭,订阅,发布功能,基本上完成了Mqtt.js的四个核心功能,关于Mqtt.js开发的相关说明,你可以参考这篇博文https://www.cnblogs.com/emqx/p/15224045.html进行学习,本文不在阐述,仅仅给出实例代码,demo截图如下图所示:

在这里插入图片描述

2.详细实例代码步骤

组件devicetips.vue代码如下:

在这里插入图片描述

<template>
  <div>
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>连接</span>
      </div>
      <div class="text item">
        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-form-item label="主机地址:">
              <el-input
                v-model="path_info.host"
                :disabled="inputDisabled"
              ></el-input>
            </el-form-item>
            <el-form-item label="端口:">
              <el-input
                v-model="path_info.port"
                :disabled="inputDisabled"
              ></el-input>
            </el-form-item>
            <el-form-item label="path:">
              <el-input
                v-model="path_info.path"
                :disabled="inputDisabled"
              ></el-input>
            </el-form-item>
          </el-form>
        </div>

        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-form-item label="客户端ID:">
              <el-input
                v-model="options.clientId"
                :disabled="inputDisabled"
                ><i slot="suffix" class="el-icon-refresh" @click="refresh"></i
              ></el-input>
            </el-form-item>
            <el-form-item label="用户名:">
              <el-input
                v-model="options.username"
                :disabled="inputDisabled"
              ></el-input>
            </el-form-item>
            <el-form-item label="密码:">
              <el-input
                v-model="options.password"
                :disabled="inputDisabled"
              ></el-input>
            </el-form-item>
            <el-form-item label="心跳:">
              <el-input
                v-model="options.keepalive"
                :disabled="inputDisabled"
              ></el-input>
            </el-form-item>
          </el-form>
        </div>

        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-button
              type="success"
              :loading="connection_loading"
              :disabled="connection_disabled"
              @click="connection"
              >连接</el-button
            >
            <el-button type="success" :disabled="close_disabled" @click="close"
              >断开连接</el-button
            >
            当前状态: {{ connection_info }}
            <el-link type="success" href="http://www.itguye.top:18083/"
              >http://www.itguye.top:18083/</el-link
            >
          </el-form>
        </div>
      </div>
    </el-card>

    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>订阅</span>
      </div>
      <div class="text item">
        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-form-item label="主题:">
              <el-input
                v-model="sub.subscribeTxt"
              ></el-input>
            </el-form-item>
            <el-form-item label="服务质量:">
              <el-input
                v-model="sub.subQuality"
              ></el-input>
            </el-form-item>
          </el-form>
        </div>

        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-button
              type="success"
              @click="subOnclick"
              >订阅</el-button
            >
          </el-form>
        </div>
      </div>
    </el-card>

    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>发布</span>
      </div>
      <div class="text item">
        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-form-item label="主题:">
              <el-input
                v-model="pub.publishTxt"
              ></el-input>
            </el-form-item>

            <el-form-item label="消息:">
              <el-input v-model="pub.msg" ></el-input>
            </el-form-item>

            <el-form-item label="服务质量:">
              <el-input
                v-model="pub.pubQuality"
              ></el-input>
            </el-form-item>
          </el-form>
        </div>

        <div class="grid-content bg-purple">
          <el-form :inline="true" class="demo-form-inline">
            <el-button
              type="success"
              @click="sendMsg"
              >发送</el-button
            >
          </el-form>
        </div>
      </div>
    </el-card>

    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>内容提示:</span>
      </div>
      <div class="text item" style="overflow:auto; height: 200px;">
        <!-- <ul class="infinite-list" > </ul> -->
          <!-- <li  class="infinite-list-item">  </li> -->
          <div style="overflow:auto;height:200px;">
            <pre>{{ resultTxt === "" ? "无" : resultTxt }}</pre>
	      </div>
       
       
      </div>
    </el-card>
  </div>
</template>
<script>
const mqtt = require('mqtt')
import {decode} from '@/utils/encode.js'
let  client  = null;
var _this;
export default {
  data() {
    return {
      // 按钮的禁用
      connection_disabled: false,
      close_disabled: true,
      connection_loading: false,
      // 输入框禁用
      inputDisabled: false,
      connection_info: "未连接", // 连接情况
      sensorData: [],
      controllerData: [],
      timer: null,
      path_info: {
        host: "www.itguye.top",
        port: "8083",
        path: "/mqtt",
      },
      options: {
        clientId: "mqttjs_12e2476c",
        username: "admin",
        password: "public",
        keepalive: 60,
        connectTimeout: 4000,
      },
      sub: {
        subscribeTxt: "smartagriculture/pub/",
        subQuality: 0,
      },
      pub: {
        publishTxt: "smartagriculture/sub/",
        pubQuality: 0,
        msg: '{ "beep":  0 }',
      },
      resultTxt: "",
    };
  },
  methods: {
    connection() {
      // 通过WebSocket连接MQTT服务器
      const path =
        "ws://" +
        this.path_info.host +
        ":" +
        this.path_info.port +
        this.path_info.path;
      // 提交连接
      // this.$store.commit("openConnection", [path, this.options]);
      this.resultTxt += new Date().toLocaleString()+":正在连接MQTT服务器\n";
      this.connection_loading = false;
      this.connection_disabled = true;
      this.close_disabled = false;
      this.inputDisabled = true;
      this.connection_info = "已连接";
      client = mqtt.connect(path, this.options);
      if(client == null){
        this.resultTxt += new Date().toLocaleString()+":未连接\n";
      }else{
        this.resultTxt += new Date().toLocaleString()+":已连接\n";
      }
      console.log(client)
      
      // 开启定时器接收数据
      this.timer = window.setInterval(() => {

       // const client = this.$store.state.devices.client;
        if (client != null) {
          // Received
          client.on("message", (topic, message, packet) => {
            const rs =  JSON.parse(message)
            this.resultTxt +=  new Date().toLocaleString()+":"+decode(new Uint8Array(message),"gb2312")+"\n";
            // 数据展示
           // this.$store.commit("saveDataResult",rs)
          });
        } else {
          this.resultTxt += new Date().toLocaleString()+":未连接\n";
        }
      }, 5000);
      
    },
    subOnclick() {
      // 订阅主题
      if (this.connection_info === "已连接") {
        client.subscribe(
          this.sub.subscribeTxt,
          { qos: this.sub.subQuality },
          function (error, granted) {
            if (error) {
              _this.resultTxt += new Date().toLocaleString()+":出现异常:"+error+"\n";
            } else {
              _this.resultTxt += new Date().toLocaleString()+":订阅" + _this.sub.subscribeTxt + "成功\n";
            }
          }
        );
      }else{
        _this.$message({
          message: '订阅失败,请连接MQTT服务器!',
          type: 'warning'
        });
      }
    },
    sendMsg() {
      // 发布主题
      if (this.connection_info === "已连接") {
        client.publish(
          this.pub.publishTxt,
          this.pub.msg,
          { qos: this.pub.pubQuality, retain: false },
          function (error) {
            if (error) {
              _this.resultTxt += new Date().toLocaleString()+":出现异常:"+error+"\n";
            } else {
              _this.resultTxt += new Date().toLocaleString()+":" + _this.pub.msg + "\n";
            }
          }
        );
      }else{
        _this.$message({
          message: '发送失败,请连接MQTT服务器!',
          type: 'warning'
        });
      }
    },
    refresh() {
      this.options.clientId =
        "mqttjs_" + Math.random().toString(16).substr(2, 8);
      const array = ["clientId", this.options.clientId];
      this.$store.commit("updateOptions", array);
    },
    close() {
      // 用户点击断开
    
      this.resultTxt+=new Date().toLocaleString()+":关闭MQTT连接\n"
      this.connection_info = "未连接";
      this.connection_loading = false;
      this.close_disabled = true;
      this.connection_disabled = false;
      this.inputDisabled = false;
      // 是否关闭成功
      if (client != null) {
        window.clearInterval(this.timer);// 关闭定时器
        client.end(true, null, () => {
          client = null;
          this.resultTxt+=new Date().toLocaleString()+":关闭MQTT连接成功\n"
        });
      }
      // this.$store.commit("closeConnection");
    },

  },
  computed: {

  },created(){
    _this=this;    //保存this一开始指向的对象
  }
};
</script>

<style scoped>
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover,
.el-cascader__dropdown,
.el-color-picker__panel,
.el-message-box,
.el-notification {
  margin: 10px;
}

.el-button--success.is-disabled,
.el-button--success.is-disabled:active,
.el-button--success.is-disabled:focus,
.el-button--success.is-disabled:hover {
  margin-right: 20px;
}

.el-link.el-link--success {
  margin-left: 50px;
}
</style>

上面的组件引入了二个js文件:

const mqtt = require('mqtt')
import {decode} from '@/utils/encode.js'
  • mqtt 采用npm 安装依赖:
npm install mqtt --save
  • encode.js是为了解决乱码问题编写的js文件,在utils中创建encode.js,详细代码如下:
import {
    TextEncoder,
    TextDecoder
  } from 'text-encoding'
  
  /**
   * 编码
   * @param {*} str 需要编码的字符串
   * @param {*} encoding 编码类型(gb2312,utf-8)
   * @returns unit8Array类型的对象
   */
  export function encode(str, encoding) {
    let encode = new TextEncoder(encoding, {
      NONSTANDARD_allowLegacyEncoding: true
    })
    let uint8Array = encode.encode(str);
    return uint8Array;
  }
  
  
  /**
   * 解码
   * @param {*} uint8Array 需要解码的unit8Array类型的对象
   * @param {*} encoding 解码类型(gb2312,utf-8)
   * @returns 解码出来的字符串
   */
  export function decode(uint8Array, encoding) {
    let decode = new TextDecoder(encoding);
    return decode.decode(uint8Array)
  }

备注:text-encoding 需要导入,使用 npm install text-encoding --save 导入即可。

使用的时候导入该Vue组件即可:

<template>
  <div>
    <device_tips></device_tips>
  </div>
</template>

<script>
import device_tips from './devicetips.vue';
export default {
components:{
  device_tips
}
}
</script>

<style>

</style>
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Vue Element UI实现评论功能需要依赖一些组件,如表单、输入框、按钮、弹窗等。下面是一个简单的评论功能实现步骤: 1. 引入Element UI组件库 在Vue项目中,可以通过npm安装Element UI组件库,并在main.js文件中引入。 ``` npm install element-ui --save import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); ``` 2. 创建评论组件Vue组件中,可以创建一个评论组件,用于显示评论列表和评论表单。在该组件中,需要定义data属性,用于存储评论列表和表单数据。 ``` <template> <div> <div v-for="comment in comments" :key="comment.id">{{comment.content}}</div> <el-form :model="form" label-position="left" label-width="80px" inline> <el-form-item label="评论"> <el-input v-model="form.content" placeholder="请输入评论内容"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="addComment">发表评论</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data() { return { comments: [], form: { content: '' } } }, methods: { addComment() { const comment = { id: Date.now(), content: this.form.content } this.comments.push(comment) this.form.content = '' } } } </script> ``` 在上面的代码中,el-form表示表单,el-input表示输入框,el-button表示按钮。comments数组用于存储评论列表,form对象用于存储表单数据。addComment方法用于发表评论,将表单数据存储到comments数组中,并清空表单数据。 3. 在父组件中使用评论组件 在父组件中使用评论组件,并将评论列表传递给该组件。 ``` <template> <div> <comment :comments="comments"></comment> </div> </template> <script> import Comment from './Comment.vue' export default { data() { return { comments: [ {id: 1, content: '这是一条评论'}, {id: 2, content: '这是另一条评论'} ] } }, components: { Comment } } </script> ``` 在上面的代码中,comment组件通过属性comments获取评论列表,并在父组件中定义comments数组,存储评论数据。 4. 给评论组件添加弹窗 在评论组件中,可以添加一个弹窗组件,用于提示评论成功。 ``` <template> <div> <div v-for="comment in comments" :key="comment.id">{{comment.content}}</div> <el-form :model="form" label-position="left" label-width="80px" inline> <el-form-item label="评论"> <el-input v-model="form.content" placeholder="请输入评论内容"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="addComment">发表评论</el-button> </el-form-item> </el-form> <el-dialog title="提示" :visible.sync="dialogVisible"> <p>评论成功!</p> </el-dialog> </div> </template> <script> export default { data() { return { comments: [], form: { content: '' }, dialogVisible: false } }, methods: { addComment() { const comment = { id: Date.now(), content: this.form.content } this.comments.push(comment) this.form.content = '' this.dialogVisible = true setTimeout(() => { this.dialogVisible = false }, 2000) } } } </script> ``` 在上面的代码中,el-dialog表示弹窗,dialogVisible属性用于控制弹窗的显示/隐藏。在addComment方法中,添加评论成功后,弹出评论成功的提示,并在2秒后关闭弹窗。 这就是一个简单的Vue Element UI评论功能实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘟嘟的程序员铲屎官

你的鼓励将是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值