@@ -228,7 +228,7 @@ io.sockets.on('connection', function (socket) {
228228
229229下一步,使用Angular.js构建聊天室的客户端。
230230
231- 修改index.html,加上angular了的绑定,添加一个新的js文件technode.js到页面上 :
231+ 修改index.html,添加Angular绑定 :
232232
233233```
234234<!doctype html>
@@ -262,22 +262,22 @@ io.sockets.on('connection', function (socket) {
262262</html>
263263```
264264
265- 在index.html中,我们做了一些添加angular的申明 ;
265+ 来看看在 ` index.html ` 中我们添加的绑定 ;
266266
267- - ng-app="techNodeApp":申明了一个名为techNodeApp的angular应用,该应用的所有逻辑将来technode.js这个文件中定义 ;
268- - ng-controller="RoomCtrl": 申明了一个Room组件,它的Controller是RoomCtrl ;
269- - ng-controller="MessageCreatorCtrl": 另外一个controller,用来控制发送消息组件 ;
270- - ng-repeat="message in messages": 一个repeat绑定,将从服务器端读过来的messages显示在页面中,angluar的数据绑定是双向的,所以当messages中的消息变化时,显示给用户的信息也会跟着变化 。
267+ - ng-app="techNodeApp",绑定一个名为techNodeApp的Angular应用(该应用的所有逻辑都将放到 ` technode.js ` 文件中) ;
268+ - ng-controller="RoomCtrl",绑定一个名为 ` RoomCtrl ` 的房间控制器 ;
269+ - ng-controller="MessageCreatorCtrl",绑定一个名为 ` MessageCreatorCtrl ` 的消息创建控制器, ;
270+ - ng-repeat="message in messages": 一个repeat绑定,将从服务器端读过来的messages显示在页面中,因为Angluar的数据绑定是双向的,所以当messages中有新消息加入时,消息列表就会自动刷新 。
271271
272- 新建technode.js文件,放到static目录下,来看看technode.js的实现 :
272+ 在 ` static ` 目录下新建名为 ` technode.js ` 文件,并引入到 ` index.html ` 中,接下来,逐步在 ` technode.js ` 中实现整个客户端逻辑 :
273273
274- 申明了一个techNodeApp,与页面中的ng-app绑定对应 ;
274+ 申明名为 ` techNodeApp ` 的模块,与 ` index.html ` 页面中的 ` ng-app ` 绑定对应 ;
275275
276276```
277277angular.module('techNodeApp', [])
278278```
279279
280- 为了与服务器通信,我们将socket.io封装成了一个angular的服务socket,接下来我们就可以很方便的与服务端通信了;
280+ 将socket.io封装成了一个名为 ` socket ` 的Angular的服务,这样我们就可以在其他组件中使用 ` socket ` 与服务端通信了:
281281
282282
283283```
@@ -306,33 +306,72 @@ angular.module('techNodeApp').factory('socket', function($rootScope) {
306306})
307307```
308308
309- 接下来是定义我们RoomCtrl,它的职责就是当techNode启动时,通过socket从服务端将聊天室的全部消息读出来;如果服务端有新消息进来,就把消息添加到messages中。由于angular的绑定机制,我们完全不用去操作DOM,messages的变化会动态地反映在页面上。
309+ 仔细阅读上面的代码,socket服务并不是简单的将socket.io分装成了Angular服务,在每个回调函数里,我们调用了` $rootScope.$apply ` 。在Angular中,如果调用` $scope.$apply(callback) ` ,就是告诉Angular,执行` callback ` ,并在执行后,检查$scope(我们用的是$rootScope就是检查整个应用)数据状态,如果有变化就更新` index.html ` 中的绑定。通俗地说,就是每次与服务端通信后,根据数据变化,更新视图。
310+
311+ 接下来是定义` RoomCtrl ` :
310312
311313```
312314angular.module('techNodeApp').controller('RoomCtrl', function($scope, socket) {
313315 $scope.messages = []
314- socket.on('messages.read', function (messages) {
316+ socket.emit('getAllMessages')
317+ socket.on('allMessage', function (messages) {
315318 $scope.messages = messages
316319 })
317- socket.on('messages.add ', function (message) {
320+ socket.on('messageAdded ', function (message) {
318321 $scope.messages.push(message)
319322 })
320- socket.emit('messages.read')
321323})
322324```
323325
326+ ` RoomCtrl ` 控制器可以分为三部分:
327+
328+ ` $scope.messages = [] ` 是这个控制器的数据模型;对应视图中的:
329+
330+ ```
331+ <div class="list-group-item message" ng-repeat="message in messages">
332+ 某某: {{message}}
333+ </div>
334+ ```
335+
336+ 由于Angular的双向绑定机制,我们无需手动操作DOM元素,数据模型` messages ` 的变化能够动态地反映在视图上。
337+
338+ ```
339+ socket.emit('getAllMessages')
340+ socket.on('allMessage', function (messages) {
341+ $scope.messages = messages
342+ })
343+ ```
344+
345+ 在techNode启动后,通过socket服务从服务端获取所有消息,更新到数据模型` messages ` 中。
346+
347+ ```
348+ socket.on('messageAdded', function (message) {
349+ $scope.messages.push(message)
350+ })
351+ ```
352+
353+ 监听服务端` messageAdded ` 事件,接收新的消息,添加到数据模型中。
354+
324355MessageCteatorCtrl的定义也非常简单,当用户按下回车时,将消息通过socket发送给服务端;注意着了的newMessage是通过ng-model与textarea直接绑定的;
325356
357+ 下面是另一个控制器` MessageCteatorCtrl ` :
358+
326359```
327360angular.module('techNodeApp').controller('MessageCreatorCtrl', function($scope, socket) {
361+ $scope.newMessage = ''
328362 $scope.createMessage = function () {
329- socket.emit('messages.create', $scope.newMessage)
363+ if ($scope.newMessage == '') {
364+ return
365+ }
366+ socket.emit('createMessage', $scope.newMessage)
330367 $scope.newMessage = ''
331368 }
332369})
333370```
334371
335- 接下来是angular的两个辅助组件:
372+ 数据模型` $scope.newMessage = '' ` 与视图中的` <textarea ng-model="newMessage" ctrl-enter-break-line="createMessage()"></textarea> ` 绑定。同时绑定了一个控制器方法` createMessage ` ,当用户回车时,调用这个方法,把新消息发送给服务端。
373+
374+ 你一定注意到了视图上有两个奇怪的属性` ctrl-enter-break-line ` 和` auto-scroll-to-bottom ` ,这是我们自定义的两个Angular指令:
336375
337376- autoScrollToBottom:当消息很多出现滚动条时,该组件使得滚动条能随着消息的增加自动滚动到底部;
338377- ctrlEnterBreakLine: 在textarea回车,默认会换行,使用这个组件,可以通过ctrl+enter来换行,而enter则触发绑定的行为,在这里就是createMessage这个方法。
@@ -380,8 +419,10 @@ angular.module('techNodeApp').directive('ctrlEnterBreakLine', function() {
380419});
381420```
382421
383- ### 开始与好友匿名聊天!
422+ > 这是本文中唯一的两个Angular指令,本文并不打算深入探讨` Angular指令 ` 的机制。读者只需明白其作用,学会使用即可。
423+
424+ ### 开始与好友聊天!
384425
385- 一个最简单的聊天室搭建完成了,说简单,因为它没有用户的概念,大家完全就是匿名的, 不过,这个简单的聊天室,让我们了解一个聊天室的全貌,名来了如何结合angular和socket.io的威力快速搭建应用 。
426+ 哦也,一个最简陋的聊天室搭建完成了!说简陋,因为它连用户都没有,消息都是匿名的。 不过,通过这个简单的聊天室,想必大家已经了解了TechNode各个基础部分,学会了如何使用Angular和socket.io的快速搭建Web应用 。
386427
387- 好了,下一步我们就开始加入用户的功能!让大家不再匿名 !
428+ 启动服务器,把地址发给同事朋友,试试看!他们一定会嘲笑你连用户名都没有吧?好了,下一步我们就为TechNode加入用户的功能 !
0 commit comments