介紹vue.js如何與signalr搭配,實現即時同步資料
前言
之前有寫過用angularjs與signalr的方式,而這篇則是紀錄vue.js的方式,然後簡單實現signalr的方式。
.net部份
我們先來看一下.net如何實現吧,首先請自行建立一個全新的空白專案,接著打開nuget安裝signalr
建著新增owin cors的部份
在根目錄新增Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR(new HubConfiguration { EnableJSONP = true });
}
}
新增一個MessageModel,來傳遞消息內容的物件
public class MessageModel
{
public string Message { get; set; }
/// <summary>
/// 設立static以保存內容
/// </summary>
public static List<MessageModel> Messages { get; set; } = new List<MessageModel>
{
new MessageModel {Message="預設的內容" }
};
public static void Add(string message)
{
Messages.Add(new MessageModel { Message = message });
}
}
新增一個Hubs的資料夾,此資料夾主要放一些signalr的物件,然後新增一個DefaultHub.cs
public class DefaultHub:Hub
{
public void Get()
{
Clients.All.Get(MessageModel.Messages);
}
}
在預設的ValuesController.cs裡面,改成如下的程式碼
public class ValuesController : ApiController
{
//建立一個對應DefaultHub的介面
IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<DefaultHub>();
public IHttpActionResult Get(string message)
{
MessageModel.Add(message);
//新增完成去觸發signlar,以通知client更新
hub.Clients.All.Get(MessageModel.Messages);
return Ok();
}
}
vue.js部份
因為signalr預設需要安裝jquery,所以我們就先安裝需要的package
npm i jquery signalr --S
接下來請特別注意,如果我們直接在component使用import jquery and signalr的話,會遇到如下的錯誤
"Uncaught Error: jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file."
所以我們不如就直接在webpack動點手腳,把jquery定義為全局的方式來使用,首先打開webpack.base.conf.js,並改成如下
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
const webpack = require('webpack')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
function getService() {
if (process.env.NODE_ENV === 'test') {
return resolve('src/services/fake')
} else {
return resolve('src/services/real')
}
}
module.exports = {
entry: {
app: process.env.NODE_ENV === 'development' ? './src/main.js' : './src/main.build.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
"pages": resolve('src/pages'),
"components": resolve('src/components'),
"services": getService(),
"utilitys": resolve('src/utilitys'),
"images": resolve('src/assets/images')
}
},
// 下面這段是為jquery註冊為全局的
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'root.jQuery': 'jquery'
}),
],
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[ext]')
}
}
]
}
}
接著在起始的main.js加入了signalr
import 'signalr'
再來看一下我自行新增的Test.vue的部份
<template>
<div>
<ul>
<li v-for="item in messages">
{{item.Message}}
</li>
</ul>
</div>
</template>
<script>
import 'signalr'
export default {
name: 'test',
data () {
return {
messages: []
}
},
methods: {
get () {
//下面對應到網址的部份
let hub = $.hubConnection('http://localhost:57128')
//下面對應了.net的DefaultHub
let proxy = hub.createHubProxy('DefaultHub')
proxy.on('Get', data => this.messages = data)
//一開始就先去呼叫Get,以確保畫面一開始就有預設的資料
hub.start().done(() => proxy.invoke('Get'))
}
},
created () {
this.get()
}
}
</script>
<style>
</style>
最後來看一下結果吧
結論
有了signalr要實現即時的網頁互動並不困難,但是為了signalr我們還要引入jquery,不過目前來說這也是一個不得不的選項了,如果有任何更好的做法再請提供建議和指教囉。