javascript - Angular JS 绑定(bind)等待输入

标签 javascript angularjs node.js sockets

我正在使用 Angular JS 和 Socket.io 尝试开发一个简单的聊天室。当未插入套接字时,我让客户端工作得很好。然而,在我添加套接字通信后,绑定(bind)就变得困惑了。

我输入消息并点击发送。 addMessage 被触发,然后“聊天消息”套接字事件被触发。但是,直到我输入另一个字母或再次单击“发送”后,用户界面才会更新。然后绑定(bind)发挥其魔力,UI 添加消息。

有什么想法吗?

js文件

//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>

最佳答案

我可能会错过一些上下文,但看起来您正在更新您的 $scope在 Angular 摘要周期之外,通常位于来自服务器调用或 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 将处理和委托(delegate)抛出的任何错误)。

更新:好的,我刚刚意识到您正在使用自定义 $scope.socket事件发射器,我以为这是一个常规的$scope.$emit第一次阅读时。因此,最干净的方法是直接在 socket.emit 内应用范围。功能。如果这是一个服务,你可以注入(inject)$rootScope在此服务中并将发射包装在 $rootScope.apply(...) 中。或者使用$timeout 。或者,如果它是一个完全没 Angular 东西,那么不要将它与 Angular 东西搞乱,或者将其包装到 Angular 服务中,或者简单地 $apply 就可以了。您可以在需要时随时使用您的范围(但这是最不干净的解决方案)。

关于javascript - Angular JS 绑定(bind)等待输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30064567/

相关文章:

angularjs - 单击链接时强制重新加载路线/状态

javascript - 每个用户的express.js 唯一目录

node.js - 防止在node js中直接访问html页面

javascript - Angular ng-if 特定路由

javascript - Qt编程: How to use custom data type in QVariantMap?

javascript - 使用 ng-bind 会导致 Chrome 历史记录显示页面 URL 而不是实际标题

javascript - node.js webtorrent 通过磁力链接收集所有文件

javascript - 使用闭包而不是原型(prototype)有缺点吗?

javascript - Electron 菜单动态更改项目标签

AngularJS:将 Controller / View 分离到子目录中的好习惯?