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"> </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"> </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, "&").replace(/</g, "<").replace(/>/g, ">"); 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>
完结!!!
这个其实还是不是特别我完整,下次有时间把中心服务到客户端的也搞出来大伙看看。
(中心往外部发送)