{"id":587,"date":"2025-12-07T10:08:11","date_gmt":"2025-12-07T02:08:11","guid":{"rendered":"https:\/\/www.52runoob.com\/?p=587"},"modified":"2025-12-07T10:08:11","modified_gmt":"2025-12-07T02:08:11","slug":"%e5%89%8d%e7%ab%afvue%e4%b8%ad%e4%bd%bf%e7%94%a8signalr%e7%9a%84%e6%96%b9%e6%b3%95%e4%b8%be%e4%be%8b%e8%af%a6%e8%a7%a3","status":"publish","type":"post","link":"https:\/\/www.52runoob.com\/index.php\/2025\/12\/07\/%e5%89%8d%e7%ab%afvue%e4%b8%ad%e4%bd%bf%e7%94%a8signalr%e7%9a%84%e6%96%b9%e6%b3%95%e4%b8%be%e4%be%8b%e8%af%a6%e8%a7%a3\/","title":{"rendered":"\u524d\u7aefvue\u4e2d\u4f7f\u7528signalr\u7684\u65b9\u6cd5\u4e3e\u4f8b\u8be6\u89e3"},"content":{"rendered":"\n<p>\u4e0b\u9762\u7ed9\u4f60\u4e00\u4efd <strong>\u524d\u7aef Vue \u4e2d\u4f7f\u7528 SignalR \u7684\u65b9\u6cd5\u4e0e\u5b8c\u6574\u793a\u4f8b\u8be6\u89e3<\/strong>\uff08\u9002\u7528\u4e8e Vue2 \/ Vue3\u3001TypeScript \/ JavaScript\uff09\u3002<\/p>\n\n\n\n<p>\u5185\u5bb9\u5305\u62ec\uff1a<br>\u2714 \u5982\u4f55\u5b89\u88c5\u5e76\u521d\u59cb\u5316 SignalR<br>\u2714 Vue3 + Composition API \u793a\u4f8b<br>\u2714 Vue2 + Options API \u793a\u4f8b<br>\u2714 \u81ea\u52a8\u91cd\u8fde\u3001\u65ad\u7ebf\u5904\u7406<br>\u2714 \u5c01\u88c5\u6210\u53ef\u590d\u7528\u7684\u6a21\u5757<br>\u2714 \u4f7f\u7528 Element Plus \u505a\u7b80\u5355 UI \u63d0\u793a\uff08\u53ef\u9009\uff09<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u4e00\u3001SignalR \u7b80\u4ecb\uff08\u524d\u7aef\u89c6\u89d2\uff09<\/h1>\n\n\n\n<p>SignalR \u662f\u5fae\u8f6f\u63a8\u51fa\u7684 <strong>\u5b9e\u65f6\u901a\u8baf\u6846\u67b6<\/strong>\uff0c\u53ef\u4ee5\u8ba9\u524d\u7aef\u5b9e\u65f6\u63a5\u6536\u540e\u7aef\u7684\u6d88\u606f\u63a8\u9001\uff0c\u4f8b\u5982\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5b9e\u65f6\u6d88\u606f\u901a\u77e5<\/li>\n\n\n\n<li>\u5728\u7ebf\u7528\u6237\u72b6\u6001<\/li>\n\n\n\n<li>\u804a\u5929\u5ba4<\/li>\n\n\n\n<li>\u5b9e\u65f6\u76d1\u63a7\u9762\u677f<\/li>\n\n\n\n<li>\u6570\u636e\u66f4\u65b0\u7684\u5b9e\u65f6\u5e7f\u64ad<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u4e8c\u3001\u5b89\u88c5 SignalR \u5ba2\u6237\u7aef<\/h1>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nnpm install @microsoft\/signalr\n\n<\/pre><\/div>\n\n\n<p>Vue2 \/ Vue3 \u90fd\u4e00\u6837\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u4e09\u3001Vue3 + Composition API \u4f7f\u7528 SignalR\uff08\u63a8\u8350\uff09<\/h1>\n\n\n\n<p>\u4e0b\u9762\u662f\u6700\u7b80\u793a\u4f8b\uff08\u8fde\u63a5\u3001\u63a5\u6536\u6d88\u606f\u3001\u53d1\u9001\u6d88\u606f\uff09\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccc 1. \u521b\u5efa\u4e00\u4e2a SignalR \u8fde\u63a5\u6a21\u5757\uff08\u53ef\u590d\u7528\uff09<\/h2>\n\n\n\n<p><strong>src\/utils\/signalr.js<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nimport * as signalR from &quot;@microsoft\/signalr&quot;;\n\nlet connection = null;\n\nexport function initSignalR(url) {\n  connection = new signalR.HubConnectionBuilder()\n    .withUrl(url)\n    .withAutomaticReconnect()\n    .configureLogging(signalR.LogLevel.Information)\n    .build();\n\n  return connection;\n}\n\nexport function getConnection() {\n  return connection;\n}\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccc 2. \u5728 Vue3 \u7ec4\u4ef6\u4e2d\u4f7f\u7528<\/h2>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;script setup&gt;\nimport { onMounted, onBeforeUnmount, ref } from &#039;vue&#039;;\nimport { initSignalR, getConnection } from &#039;@\/utils\/signalr&#039;;\n\nconst messages = ref(&#x5B;]);\n\nonMounted(async () =&gt; {\n  const connection = initSignalR(&quot;https:\/\/localhost:5001\/chatHub&quot;);\n\n  \/\/ \u63a5\u6536\u540e\u7aef\u63a8\u9001\u7684\u6d88\u606f\n  connection.on(&quot;ReceiveMessage&quot;, (user, message) =&gt; {\n    messages.value.push(`${user}: ${message}`);\n  });\n\n  \/\/ \u542f\u52a8\u8fde\u63a5\n  try {\n    await connection.start();\n    console.log(&quot;SignalR \u5df2\u8fde\u63a5&quot;);\n  } catch (err) {\n    console.log(&quot;\u8fde\u63a5\u5931\u8d25:&quot;, err);\n  }\n});\n\nonBeforeUnmount(() =&gt; {\n  const connection = getConnection();\n  connection?.stop();\n});\n&amp;lt;\/script&gt;\n\n&amp;lt;template&gt;\n  &amp;lt;div&gt;\n    &amp;lt;h3&gt;SignalR \u6d88\u606f\uff1a &amp;lt;\/h3&gt;\n    &amp;lt;p v-for=&quot;msg in messages&quot; :key=&quot;msg&quot;&gt;{{ msg }}&amp;lt;\/p&gt;\n  &amp;lt;\/div&gt;\n&amp;lt;\/template&gt;\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccc 3. \u524d\u7aef\u53d1\u9001\u6d88\u606f\uff08\u8c03\u7528 server \u65b9\u6cd5\uff09<\/h2>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconst sendMessage = async () =&gt; {\n  const connection = getConnection();\n  await connection.invoke(&quot;SendMessage&quot;, &quot;\u963f\u6770&quot;, &quot;\u4f60\u597d\uff01&quot;);\n};\n\n<\/pre><\/div>\n\n\n<p>\u540e\u7aef SignalR Hub \u9700\u8981\u6709\u5bf9\u5e94\u65b9\u6cd5\uff1a<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic async Task SendMessage(string user, string message)\n{\n    await Clients.All.SendAsync(&quot;ReceiveMessage&quot;, user, message);\n}\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u56db\u3001Vue2 + Options API \u793a\u4f8b<\/h1>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;script&gt;\nimport * as signalR from &#039;@microsoft\/signalr&#039;;\n\nexport default {\n  data() {\n    return {\n      messages: &#x5B;],\n      connection: null\n    };\n  },\n  created() {\n    this.connection = new signalR.HubConnectionBuilder()\n      .withUrl(&quot;https:\/\/localhost:5001\/chatHub&quot;)\n      .withAutomaticReconnect()\n      .build();\n\n    this.connection.on(&quot;ReceiveMessage&quot;, (user, msg) =&gt; {\n      this.messages.push(`${user}: ${msg}`);\n    });\n\n    this.connection.start().catch(err =&gt; console.error(err));\n  },\n  beforeDestroy() {\n    this.connection?.stop();\n  }\n}\n&amp;lt;\/script&gt;\n\n&amp;lt;template&gt;\n  &amp;lt;div&gt;\n    &amp;lt;h3&gt;\u6d88\u606f&amp;lt;\/h3&gt;\n    &amp;lt;p v-for=&quot;(msg,i) in messages&quot; :key=&quot;i&quot;&gt;{{ msg }}&amp;lt;\/p&gt;\n  &amp;lt;\/div&gt;\n&amp;lt;\/template&gt;\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u4e94\u3001\u81ea\u52a8\u91cd\u8fde \/ \u65ad\u7ebf\u5904\u7406<\/h1>\n\n\n\n<p>SignalR \u5185\u7f6e\u81ea\u52a8\u91cd\u8fde\uff0c\u53ea\u9700\u8981\uff1a<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.withAutomaticReconnect()\n\n<\/pre><\/div>\n\n\n<p>\u4f60\u53ef\u4ee5\u76d1\u542c\u4e8b\u4ef6\uff1a<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconnection.onreconnecting(error =&gt; {\n  console.log(&quot;\u6b63\u5728\u91cd\u8fde...&quot;, error);\n});\n\nconnection.onreconnected(connectionId =&gt; {\n  console.log(&quot;\u91cd\u8fde\u6210\u529f&quot;, connectionId);\n});\n\nconnection.onclose(error =&gt; {\n  console.log(&quot;\u8fde\u63a5\u5df2\u5173\u95ed&quot;, error);\n});\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u516d\u3001\u5c06 SignalR \u5c01\u88c5\u6210\u5168\u5c40\u63d2\u4ef6\uff08Vue3\uff09<\/h1>\n\n\n\n<p><strong>src\/plugins\/signalr.js<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nimport * as signalR from &quot;@microsoft\/signalr&quot;;\n\nexport default {\n  install(app, options) {\n    const connection = new signalR.HubConnectionBuilder()\n      .withUrl(options.url)\n      .withAutomaticReconnect()\n      .build();\n\n    app.config.globalProperties.$signalr = connection;\n\n    connection.start().catch(err =&gt; console.log(err));\n  }\n};\n\n<\/pre><\/div>\n\n\n<p>\u5728 main.js \u4e2d\u4f7f\u7528\uff1a<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nimport signalR from &quot;.\/plugins\/signalr&quot;;\n\napp.use(signalR, { url: &quot;https:\/\/localhost:5001\/chatHub&quot; });\n\n<\/pre><\/div>\n\n\n<p>\u7ec4\u4ef6\u4e2d\u4f7f\u7528\uff1a<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nthis.$signalr.invoke(&quot;SendMessage&quot;, &quot;\u963f\u6770&quot;, &quot;Hello!&quot;);\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u2705 \u4e03\u3001SignalR + Element Plus \u63d0\u793a\uff08\u53ef\u9009\uff09<\/h1>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nimport { ElNotification } from &quot;element-plus&quot;;\n\nconnection.on(&quot;ReceiveMessage&quot;, (user, message) =&gt; {\n  ElNotification({\n    title: user,\n    message: message\n  });\n});\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83c\udfaf \u603b\u7ed3\uff08\u53ef\u590d\u5236\uff09<\/h1>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u573a\u666f<\/th><th>\u4f7f\u7528\u65b9\u6cd5<\/th><\/tr><\/thead><tbody><tr><td>\u521d\u59cb\u5316\u8fde\u63a5<\/td><td>HubConnectionBuilder(&#8230;)<\/td><\/tr><tr><td>\u81ea\u52a8\u91cd\u8fde<\/td><td>withAutomaticReconnect()<\/td><\/tr><tr><td>\u63a5\u6536\u6d88\u606f<\/td><td>connection.on(&#8220;ReceiveMessage&#8221;)<\/td><\/tr><tr><td>\u53d1\u9001\u6d88\u606f<\/td><td>connection.invoke(&#8220;SendMessage&#8221;)<\/td><\/tr><tr><td>Vue3 \u4f7f\u7528<\/td><td>Composition API<\/td><\/tr><tr><td>Vue2 \u4f7f\u7528<\/td><td>Options API<\/td><\/tr><tr><td>\u5c01\u88c5<\/td><td>utils \/ plugin<\/td><\/tr><\/tbody><\/table><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\u4e0b\u9762\u7ed9\u4f60\u4e00\u4efd \u524d\u7aef Vue \u4e2d\u4f7f\u7528 SignalR \u7684\u65b9\u6cd5\u4e0e\u5b8c\u6574\u793a\u4f8b\u8be6\u89e3\uff08\u9002\u7528\u4e8e&#8230; <a class=\"more-link\" href=\"https:\/\/www.52runoob.com\/index.php\/2025\/12\/07\/%e5%89%8d%e7%ab%afvue%e4%b8%ad%e4%bd%bf%e7%94%a8signalr%e7%9a%84%e6%96%b9%e6%b3%95%e4%b8%be%e4%be%8b%e8%af%a6%e8%a7%a3\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[],"class_list":["post-587","post","type-post","status-publish","format-standard","hentry","category-javascript"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/posts\/587","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/comments?post=587"}],"version-history":[{"count":1,"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/posts\/587\/revisions"}],"predecessor-version":[{"id":588,"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/posts\/587\/revisions\/588"}],"wp:attachment":[{"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/media?parent=587"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/categories?post=587"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.52runoob.com\/index.php\/wp-json\/wp\/v2\/tags?post=587"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}