Skip to content

Commit d3b5227

Browse files
committed
done chapter 01
1 parent 13c2113 commit d3b5227

File tree

1 file changed

+59
-18
lines changed

1 file changed

+59
-18
lines changed

how-to-build-chat-app-with-socket.io-and-angular/01-最简单的聊天室.md

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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
```
277277
angular.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
```
312314
angular.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+
324355
MessageCteatorCtrl的定义也非常简单,当用户按下回车时,将消息通过socket发送给服务端;注意着了的newMessage是通过ng-model与textarea直接绑定的;
325356

357+
下面是另一个控制器`MessageCteatorCtrl`
358+
326359
```
327360
angular.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

Comments
 (0)