我正在使用Angular JS和Socket.io来尝试开发一个简单的聊天室。当没有插入插座时,我让客户端工作得很好。然而,在我添加套接字通信之后,绑定就搞乱了。
我输入消息并点击发送。触发addMessage,然后触发'chat message'套接字事件。但是,在我键入另一个字母或再次单击“发送”之前,UI不会更新。然后绑定发挥其魔力,UI添加消息。
有什么想法吗?
js file
//Receive Socket message.
//Runs but UI does not update.
//UI updates on user's next input
$scope.socket.on('chat message', function(msg) {
var message = new Message(msg);
$scope.messages.splice(0, 0, message);
$scope.clear();
});
//Add Message, sends to socket
$scope.addMessage = function () {
if($scope.validate()) {
var message = new Message($scope.message);
$scope.socket.emit('chat message', message.text);
}
};
html文件
<form role="form" ng-submit="addMessage()">
<div class="row">
<div class="input-group" style="margin-bottom: 5px;">
<input type="text" ng-model="message" placeholder="What's up?" class="form-control" ng-change="validate()">
<span class="input-group-btn">
<input type="submit" class="btn btn-primary" value="Add"/>
</span>
</input>
</div>
</div>
</form>
<div ui-sortable ng-model="messages">
<div ng-repeat="message in messages" style="padding:5px 10px;">
<p>{{ message.text }}</p>
</p>
</div>
答案 0 :(得分:0)
我可能会错过一些上下文,但看起来你好像正在更新Angular摘要周期之外的$scope
,通常是来自服务器调用的异步代码块或setTimeout
Angular不知道范围已在此类同步上下文中更新,并且在下一个摘要周期之前不会刷新DOM(例如,在您的情况下通过某些键盘输入触发)。
为了强制Angular手动摘要,您需要在更新后调用$scope.apply
:
$scope.socket.on('chat message', function(msg) {
var message = new Message(msg);
$scope.messages.splice(0, 0, message);
$scope.clear();
$scope.apply();
});
或者在回调中进行更新,如下所示:
$scope.socket.on('chat message', function(msg) {
$scope.$apply(function() {
var message = new Message(msg);
$scope.messages.splice(0, 0, message);
$scope.clear();
});
});
(优点是Angular将处理并委托抛出的任何错误。)
更新:好的,我只是意识到您正在使用自定义$scope.socket
事件发射器,我认为这是第一次阅读时的常规$scope.$emit
。因此,干净的方法是直接在socket.emit
函数中应用范围。如果这是一项服务,您可以在此服务中注入$rootScope
并将发射封装在$rootScope.apply(...)
内。或者使用$timeout
。或者如果它是一个完全没有棱角分明的东西,可以不用它来搞乱角度物品并将它包装成角度服务,或者只需$apply
你的范围(但那是最不干净的解决方案)。