<p><code></p> <h2 id="articleHeader0">前言</h2> <p><a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>+Socket.io这个轮子已经有很多人造过了,为了不重复造轮子,我将本项目以三阶段实现(大家可以在github中的Releases查看):</p> <ul> <li>纯前端(<a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>x)</li> <li>后端+前端(JavaScript)</li> <li>后端+前端(TypeScript)</li> </ul> <p>希望能给大家一个渐进学习的经验。<br />本项目地址:<a href="https://github.com/spiritree/vue-socket.io-chat/" rel="nofollow noreferrer" target="_blank">https://github.com/spiritree/...</a><br />欢迎Star&amp;Fork</p> <h2 id="articleHeader1"><a href="http://www.js-code.com/tag/vue" title="浏览关于“Vue”的文章" target="_blank" class="tag_link">Vue</a>-cli创建工程</h2> <p><code>npm install -g vue-cli</code></p> <p><code>vue init webpack my-project</code></p> <p><code>vue init ElemeFE/webpack-typescript my-project</code>(感谢饿了么分享的TypeScript的模板)</p> <p>这样就在当前目录下创建了完整的工程模板</p> <h2 id="articleHeader2">Socket.io</h2> <p>在Server端(Express)</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import * as socketIo from 'socket.io' this.io.on('connection', (socket: any) => {<br /> socket.on('sendMessage', (data: any) => {<br /> this.io.emit('boardcastMessage', data)<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> socketIo <span class="hljs-keyword">from</span> <span class="hljs-string">'socket.io'</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.io.on(<span class="hljs-string">'connection'</span>, (socket: any) =&gt; { socket.on(<span class="hljs-string">'sendMessage'</span>, (data: any) =&gt; { <span class="hljs-keyword">this</span>.io.emit(<span class="hljs-string">'boardcastMessage'</span>, data) })</code></pre> <p>在Client端(Vue)</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<script lang=&quot;ts&quot;><br /> /// <reference path=&quot;../../socket.io.d.ts&quot; ></reference><br /> export default Vue.extend({<br /> mounted() {<br /> socket.on('boardcastMessage', (data: any) => {<br /> this.$store.dispatch('sendMessage', { data })<br /> })<br /> }<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code class="javascipt">&lt;script lang=<span class="hljs-string">"ts"</span>&gt; <span class="hljs-comment">/// &lt;reference path="../../socket.io.d.ts" /&gt;</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a></span> <span class="hljs-keyword">default</span> Vue.extend({ mounted() { socket.on(<span class="hljs-string">'boardcastMessage'</span>, <span class="hljs-function">(<span class="hljs-params">data: <span class="hljs-built_in">any</span></span>) =&gt;</span> { <span class="hljs-keyword">this</span>.$store.dispatch(<span class="hljs-string">'sendMessage'</span>, { data }) }) } })</code></pre> <p>Server端常用<a href="http://www.js-code.com/tag/api" title="API" target="_blank">API</a>:</p> <p><code>socket.emit()</code>:向建立该连接的客户端发送消息</p> <p><code>socket.on()</code>:监听客户端发送信息</p> <p><code>io.sockets.emit()</code>:向所有客户端广播</p> <p>Client端常用<a href="http://www.js-code.com/tag/api" title="API" target="_blank">API</a>:</p> <p><code>socket.emit()</code>:向服务端发送消息</p> <p><code>socket.on()</code>:监听服务端发来的信息</p> <h2 id="articleHeader3">TypeScript教程</h2> <p>关于TypeScript的基本知识,可以直接看xcatliu整理的教程,简单易懂,有Java/C#基础就可快速上手。<br /><a href="https://github.com/xcatliu/typescript-tutorial" rel="nofollow noreferrer" target="_blank">TypeScript 入门教程</a></p> <h2 id="articleHeader4">webpack+TypeScript(前端)</h2> <p><a href="https://zhuanlan.zhihu.com/p/29971290" rel="nofollow noreferrer" target="_blank">Vue + TypeScript 尝鲜体验</a></p> <p>也可用官方插件<code>vue-class-component</code></p> <p>**本项目参考<br /><code>vue init ElemeFE/webpack-typescript my-project</code>**</p> <p>先添加声明文件(Vue全家桶自带就不需要了)<br />本项目用到Express和Socket.io</p> <p><code>npm install typescript --save-dev</code></p> <p><code>npm i ts-loader --save-dev</code></p> <h3 id="articleHeader5">在webpack.base.conf.js中添加</h3> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="{ module: { rules: [ { test: /.tsx?$/, loader: 'ts-loader', exclude: /node_modules/, options: { appendTsSuffixTo: [/.vue$/], } }, ], } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="javascript">{ <span class="hljs-attr">module</span>: { <span class="hljs-attr">rules</span>: [ { <span class="hljs-attr">test</span>: <span class="hljs-regexp">/.tsx?$/</span>, <span class="hljs-attr">loader</span>: <span class="hljs-string">'ts-loader'</span>, <span class="hljs-attr">exclude</span>: <span class="hljs-regexp">/<a href="http://www.js-code.com/tag/node" title="浏览关于“node”的文章" target="_blank" class="tag_link">node</a>_modules/</span>, <span class="hljs-attr">options</span>: { <span class="hljs-attr">appendTsSuffixTo</span>: [<span class="hljs-regexp">/.vue$/</span>], } }, ], } }</code></pre> <h3 id="articleHeader6">在根目录添加声明文件</h3> <p>socket.io.d.ts(为了编译通过)</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="declare namespace socket { var on: any; var emit: any; var data: any; }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="javascript">declare namespace socket { <span class="hljs-keyword">var</span> on: any; <span class="hljs-keyword">var</span> emit: any; <span class="hljs-keyword">var</span> data: any; }</code></pre> <h3 id="articleHeader7">在每个Vue文件中添加</h3> <p><span class="img-wrap"><img data-src="/img/bVXyw6?w=386&amp;h=104" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <h2 id="articleHeader8">Gulp+TypeScript(后端)</h2> <p><code>npm install gulp --save-dev</code></p> <p><code>npm install gulp-typescript --save-dev</code></p> <p><code>npm install @types/express --save-dev</code></p> <p><code>npm install @types/socket.io --save-dev</code></p> <h3 id="articleHeader9">Server文件夹结构</h3> <p>├── app.js<br />├── gulpfile.js<br />├── register.js<br />├── src<br />│&nbsp;&nbsp; ├── type-app.ts<br />│&nbsp;&nbsp; └── type-register.ts<br />├── tsconfig.json<br />├── type-app.js<br />└── type-register.js</p> <h3 id="articleHeader10">添加tsconfig.json</h3> <p><a href="https://www.tslang.cn/docs/handbook/tsconfig-json.html" rel="nofollow noreferrer" target="_blank">TypeScript官方手册</a></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="{ &quot;include&quot;: [ &quot;src/*.ts&quot; ], &quot;compilerOptions&quot;: { &quot;noImplicitAny&quot;: true, &quot;lib&quot;: [&quot;es6&quot;], &quot;target&quot;: &quot;es5&quot;, &quot;outDir&quot;: &quot;&quot; } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="json hljs"><code class="json">{ <span class="hljs-attr">"include"</span>: [ <span class="hljs-string">"src/*.ts"</span> ], <span class="hljs-attr">"compilerOptions"</span>: { <span class="hljs-attr">"noImplicitAny"</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">"lib"</span>: [<span class="hljs-string">"<a href="http://www.js-code.com/tag/es6" title="浏览关于“es6”的文章" target="_blank" class="tag_link">es6</a>"</span>], <span class="hljs-attr">"target"</span>: <span class="hljs-string">"<a href="http://www.js-code.com/tag/es5" title="浏览关于“es5”的文章" target="_blank" class="tag_link">es5</a>"</span>, <span class="hljs-attr">"outDir"</span>: <span class="hljs-string">""</span> } }</code></pre> <h3 id="articleHeader11">配置gulpfile.js</h3> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var gulp = require(&quot;gulp&quot;); var ts = require(&quot;gulp-typescript&quot;); var tsProject = ts.createProject(&quot;tsconfig.json&quot;); gulp.task(&quot;build&quot;, function () { return tsProject.src() .pipe(tsProject()) .js.pipe(gulp.dest(&quot;&quot;)); });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="javascript"><span class="hljs-keyword">var</span> gulp = <span class="hljs-built_in">require</span>(<span class="hljs-string">"gulp"</span>); <span class="hljs-keyword">var</span> ts = <span class="hljs-built_in">require</span>(<span class="hljs-string">"gulp-typescript"</span>); <span class="hljs-keyword">var</span> tsProject = ts.createProject(<span class="hljs-string">"tsconfig.json"</span>); gulp.task(<span class="hljs-string">"build"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> tsProject.src() .pipe(tsProject()) .js.pipe(gulp.dest(<span class="hljs-string">""</span>)); });</code></pre> <h3 id="articleHeader12">从JavaScript=&gt;TypeScript</h3> <p><span class="img-wrap"><img data-src="/img/bVXyw9?w=887&amp;h=531" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <h2 id="articleHeader13">部署到服务器</h2> <p>Linux+Nginx的组合,可以一键部署虚拟主机<br /><a href="https://oneinstack.com/" rel="nofollow noreferrer" target="_blank">OneinStack</a></p> <p>部署的遇到的坑<br /><a href="https://github.com/socketio/socket.io/issues/1942" rel="nofollow noreferrer" target="_blank">https://github.com/socketio/s...</a></p> <p><code>Error during WebSocket handshake: Unexpected response code: 400</code></p> <p>在nginx.conf添加</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="location / { proxy_pass http://localhost:8989; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection &quot;upgrade&quot;; proxy_set_header Host $host; }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="nginx hljs"><code class="nginx"><span class="hljs-attribute">location</span> / { <span class="hljs-attribute">proxy_pass</span> http://localhost:8989; <span class="hljs-attribute">proxy_http_version</span> <span class="hljs-number">1</span>.<span class="hljs-number">1</span>; <span class="hljs-attribute">proxy_set_header</span> Upgrade <span class="hljs-variable">$http_upgrade</span>; <span class="hljs-attribute">proxy_set_header</span> Connection <span class="hljs-string">"upgrade"</span>; <span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$host</span>; }</code></pre> <h2 id="articleHeader14">如何使用</h2> <p><strong>预览地址:<a href="https://app.spiritree.me/" rel="nofollow noreferrer" target="_blank">https://app.spiritree.me/</a></strong></p> <p><strong>Github地址:<a href="https://github.com/spiritree/vue-socket.io-chat" rel="nofollow noreferrer" target="_blank">https://github.com/spiritree/...</a></strong></p> <h3 id="articleHeader15">开启JavaScript服务端</h3> <p><code>git clone https://github.com/spiritree/vue-socket.io-chat.git</code></p> <p><code>npm install</code></p> <p><code>npm run server</code></p> <h3 id="articleHeader16">开启TypeScript服务端</h3> <p><code>npm install</code></p> <p><code>cd server</code></p> <p><code>gulp build</code></p> <p><code>npm run tsserver</code></p> <p>浏览器访问 <a href="http://localhost" rel="nofollow noreferrer" target="_blank">http://localhost</a>:8989<br />如遇在线列表不同步,刷新重进即可</p> <h2 id="articleHeader17">预览</h2> <p><span class="img-wrap"><img data-src="/img/bVXywX?w=1409&amp;h=627" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <p><span class="img-wrap"><img data-src="/img/bVXyw0?w=360&amp;h=708" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <h2 id="articleHeader18">参考资料</h2> <ul> <li><a href="https://github.com/xcatliu/typescript-tutorial" rel="nofollow noreferrer" target="_blank">TypeScript 入门教程</a></li> <li><a href="https://zhuanlan.zhihu.com/p/29971290" rel="nofollow noreferrer" target="_blank">Vue + TypeScript 尝鲜体验</a></li> <li><a href="https://www.tslang.cn/docs/handbook/tsconfig-json.html" rel="nofollow noreferrer" target="_blank">TypeScript官方手册</a></li> </ul> <p></code></p>

本文固定链接: http://www.js-code.com/vue-js/vue-js_26838.html