Javascript 角度JS绑定等待输入
我正在使用Angular JS和Socket.io开发一个简单的聊天室。我让客户端在不插入套接字的情况下工作得很好。然而,在我添加了套接字通信之后,绑定就搞砸了 我输入信息并点击send。addMessage被激发,然后“chat message”套接字事件被激发。但是,在我键入另一封信或再次单击“发送”之前,用户界面不会得到更新。然后绑定发挥其魔力,UI添加消息 有什么想法吗 js文件Javascript 角度JS绑定等待输入,javascript,angularjs,node.js,sockets,Javascript,Angularjs,Node.js,Sockets,我正在使用Angular JS和Socket.io开发一个简单的聊天室。我让客户端在不插入套接字的情况下工作得很好。然而,在我添加了套接字通信之后,绑定就搞砸了 我输入信息并点击send。addMessage被激发,然后“chat message”套接字事件被激发。但是,在我键入另一封信或再次单击“发送”之前,用户界面不会得到更新。然后绑定发挥其魔力,UI添加消息 有什么想法吗 js文件 //Receive Socket message. //Runs but UI does not updat
//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>
{{message.text}
我可能会错过一些上下文,但这一切看起来都像是在角度摘要周期之外更新$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
你需要的范围(但这是最不干净的解决方案)。你能试着在$scope.clear()之后添加$scope.$apply()
?我从未使用过ng表单
,如果它没有为您消化范围,我会感到惊讶,但可能我们缺少了一些内容。@floribon$scope.$apply()有效!非常感谢。如果你加上它作为回答,我将欣然接受。如果您也能解释一下,我将不胜感激。@RyanTankersley,Angular不“知道”异步操作何时完成,不知道何时应用更改(即开始$digest循环)<代码>$scope.$apply
手动触发。好的,我在紧接着的更新中回答并添加了更多信息。不确定你的socket
对象是什么样子的,但是你可能想围绕它做一些工作,这样它就可以一次性修复。