vue +signalR

系列

源码地址:https://github.com/QQ2287991080/SignalRServerAndVueClientDemo

概述:ASP.NET Core SignalR是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能。 实时 web 功能使服务器端代码可以立即将内容推送到客户端。

这玩意的概念我就不多讲了,官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-3.0

今天这个demo,就是用SignalR 做服务端,vue做客户端。

以下演示皆为本地环境

先看看最终效果

 

 

上代码

先建一个项目,我core的版本是3.0,我选择的应用“Web应用程序”,其实我这创建的就跟官网的JavaScript教程一样的。

项目建好之后右键项目->添加>客户端库

 

按图上添加就好了

 把Pages下面的Index视图的代码换成如下:

@page
<div class="container">
    <div class="row">&nbsp;</div>
    <div class="row">
        <div class="col-2">User</div>
        <div class="col-4"><input type="text" id="userInput" /></div>
    </div>
    <div class="row">
        <div class="col-2">Message</div>
        <div class="col-4"><input type="text" id="messageInput" /></div>
    </div>
    <div class="row">&nbsp;</div>
    <div class="row">
        <div class="col-6">
            <input type="button" id="sendButton" value="Send Message" />
        </div>
    </div>
</div>
<div class="row">
    <div class="col-12">
        <hr />
    </div>
</div>
<div class="row">
    <div class="col-6">
        <ul id="messagesList"></ul>
    </div>
</div>
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>

在放静态文件的wwwroot的js下面新建一个chat.js,并放入如下代码

"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable send button until connection is established
document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {
    var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    var encodedMsg = user + " says " + msg;
    var li = document.createElement("li");
    li.textContent = encodedMsg;
    document.getElementById("messagesList").appendChild(li);
});

connection.start().then(function () {
    document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
    return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {
    var user = document.getElementById("userInput").value;
    var message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

添加SignalR中心,加个Hubs文件夹,加个ChatHub类

public class ChatHub : Hub
    {
        /// <summary>
        /// 给所有客户端发送消息
        /// </summary>
        /// <param name="user">用户</param>
        /// <param name="message">消息</param>
        /// <returns></returns>
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
        /// <summary>
        /// 向调用客户端发送消息(备用)
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessageCaller(string message)
        {
            await Clients.Caller.SendAsync("ReceiveCaller", message);
        }
    }

在Startup里配置SignalR

ConfigureServices里加上

services.AddSignalR();

Configure

         app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapHub<ChatHub>("/chathub");
            });

看看效果

是不是有聊天室那味了。。

哎呀不对,标题咋不说要弄vue做客户端啊,咋现在还在这写视图呢。

那么接下来就用vue做客户端,我用的脚手架,引用vue.js也是能实现的。

先用脚手架建一个项目,把不要的东西都删除,只留下一个home.vue,记得路由里面也删除干净,要不然会报错的。

首先我们先安装前端的js包,上文也看到我们调用signalr中心有对应的js客户端

npm install @aspnet/signalr

安装好之后,我们开始写前端代码

在home.vue里面放两个输入框和一个按钮,和core的index视图差不多,样式就不美化,主要做效果。

    <input v-model="user" type="text" />
    <input v-model="message" type="text" />
    <button @click="sendAll">发送全部</button>

引用安装的@aspnet/signalr

import * as signalR from "@aspnet/signalr";

定义需要的变量

data() {
    return {
      user: "",//用户
      message: "",//消息
      connection: "",//signalr连接
      messages: []//返回消息
    };
  },

定义页面加载连接signalr

created: function() {
    let thisVue = this;
    this.connection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:13989/chathub", {
        skipNegotiation: true,
        transport: signalR.HttpTransportType.WebSockets
      })
      .configureLogging(signalR.LogLevel.Information)
      .build();
    this.connection.on("ReceiveMessage", function(user, message) {
      thisVue.messages.push({ user, message });
      console.log({ user, message });
    });
    this.connection.start();
  }

给按钮来个点击事件

 methods: {
    //给全部发送消息
    sendAll: function() {
      this.connection
        .invoke("SendMessage", this.user, this.message)
        .catch(function(err) {
          return console.error(err);
        });
    }
}

🆗。把代码跑起来,npm run serve........

 

 

等一下,先把我们的后端跑起来,要不然是接受不到的。

 

 测试看看先。。

 

 数据拿到了,忘记展示了,先加个<ul>

 <div>
      <ul v-for="(item ,index) in messages" v-bind:key="index +'itemMessage'">
        <li>{{item.user}} says {{item.message}}</li>
      </ul>
    </div>

我再加个标题吧好看点。

 

 哎。有内味儿了。

不知道还有人记得之前chahub里面我预留了一个给自己发消息的方法。

嘿,这会儿就给他实现一下,首先我先加个按钮,然后在注册给自己发送的方法。这回我代码就不填出来,先看看效果,之后代码全都给出来。

 

 来了来了,压缩嚣张至极。。。

先把前端代码放出来,完整版

<template>
  <div class="home">
    <h1>前端演示SignalR</h1>
    <input v-model="user" type="text" />
    <input v-model="message" type="text" />
    <button @click="sendAll">发送全部</button>
    <button @click="sendOwn">对自己发送</button>
    <div>
      <ul v-for="(item ,index) in messages" v-bind:key="index +'itemMessage'">
        <li>{{item.user}} says {{item.message}}</li>
      </ul>
    </div>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
import * as signalR from "@aspnet/signalr";
export default {
  name: "Home",
  components: {
    HelloWorld
  },
  data() {
    return {
      user: "", //用户
      message: "", //消息
      connection: "", //signalr连接
      messages: [] //返回消息
    };
  },
  methods: {
    //给全部发送消息
    sendAll: function() {
      this.connection
        .invoke("SendMessage", this.user, this.message)
        .catch(function(err) {
          return console.error(err);
        });
    },
    //只给自己发送消息
    sendOwn: function() {
      this.connection
        .invoke("SendMessageCaller", this.message)
        .catch(function(err) {
          return console.error(err);
        });
    }

 
  },
  created: function() {
    let thisVue = this;
    this.connection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:13989/chathub", {
        skipNegotiation: true,
        transport: signalR.HttpTransportType.WebSockets
      })
      .configureLogging(signalR.LogLevel.Information)
      .build();
    this.connection.on("ReceiveMessage", function(user, message) {
      thisVue.messages.push({ user, message });
      console.log({ user, message });
    });
    this.connection.on("ReceiveCaller", function(message) {
      let user = "自己";//这里为了push不报错,我就弄了一个默认值。
      thisVue.messages.push({ user, message });
      console.log({ user, message });
    });
    this.connection.start();
  }
};
</script>

完结!!!

这个其实还是不是特别我完整,下次有时间把中心服务到客户端的也搞出来大伙看看。

中心往外部发送

 

 
posted @ 2020-05-13 14:52  飞天猪皮怪  阅读(8483)  评论(4编辑  收藏  举报