Angular.js - Socket.io 事件更新模型,而不是视图
Angular.js - Socket.io event updates model, not view
我有套接字在工作,因为每个客户端似乎都是运行 console.logs 事件的正确代码块。发送消息的客户端更新视图,但其他连接的客户端不更新。
但是当另一个客户端发送消息时,它的视图会更新它一直推送到模型的所有积压消息,所以我知道这部分正在工作。只是视图没有更新。
我阅读了一些资料,看来我需要重构我的代码才能使用 $scope
和 $scope.$apply
,但我不确定如何重构。
app.controller('StoryController', ['$http', '$scope', function($http, $scope){
var story = this;
socket.on('new storyPoint', function(msg){
//console.log('new storyPoint!', msg);
story.points.push(msg);
$('.story').scrollTop($('.story')[0].scrollHeight);
console.log('last story point:', story.points[story.points.length - 1]);
});
}]);
如您所见,我还没有真正使用 $scope
,而且我很确定我需要,但尝试模仿其他解决方案来解决这个问题失败了。
编辑:
这是视图:
<div class="container story-container" ng-controller="StoryController as storyCtrl">
<aside class="players" id="players"><h1>Players </h1>
<input name="username" type="text" ng-model="storyCtrl.username"/>
<ul class="players-list">
<li>{{storyCtrl.username}}</li>
<li ng-repeat="player in game.settings.players">{{player}}</li>
</ul>
</aside>
<div class="main">
<h1 class="story-title">{{game.settings.title}}</h1>
<ul class="story">
<li ng-repeat="storyPoint in storyCtrl.points"><p>{{storyPoint.body}}</p></li>
<li><p>{{storyCtrl.point.body}}</p></li>
</ul>
<form name="storyForm" ng-submit="storyCtrl.addPoint(storyCtrl)">
<textarea ng-model="storyCtrl.point.body" name="storyPoint" rows="5"></textarea>
<input class="btn btn-success" type="submit"/>
</form>
</div>
问题是 Socket.io 不在 angular 生命周期内,因此 Angular 不知道新数据进来了。你是对的,你需要将 $scope
注入您的控制器,并在您的 socket.io 回调中执行 $scope.$apply()
作为最后一个操作。
$scope.$apply()
让 angular 知道数据已经更新,并刷新需要刷新的内容。
app.controller('StoryController', ['$http', '$scope', function($http, $scope){
var story = this;
socket.on('new storyPoint', function(msg){
//console.log('new storyPoint!', msg);
$scope.$apply(function(){
story.points.push(msg);
$('.story').scrollTop($('.story')[0].scrollHeight);
console.log('last story point:', story.points[story.points.length - 1]);
});
});
}]);
以下代码对我有用,每当你从套接字收到消息时,你只需要在 $scope.$apply() 函数中绑定你的代码
socket.onmessage = function (e) {
$scope.$apply(function () {
$scope.onMessge(e);
});
};
我有套接字在工作,因为每个客户端似乎都是运行 console.logs 事件的正确代码块。发送消息的客户端更新视图,但其他连接的客户端不更新。
但是当另一个客户端发送消息时,它的视图会更新它一直推送到模型的所有积压消息,所以我知道这部分正在工作。只是视图没有更新。
我阅读了一些资料,看来我需要重构我的代码才能使用 $scope
和 $scope.$apply
,但我不确定如何重构。
app.controller('StoryController', ['$http', '$scope', function($http, $scope){
var story = this;
socket.on('new storyPoint', function(msg){
//console.log('new storyPoint!', msg);
story.points.push(msg);
$('.story').scrollTop($('.story')[0].scrollHeight);
console.log('last story point:', story.points[story.points.length - 1]);
});
}]);
如您所见,我还没有真正使用 $scope
,而且我很确定我需要,但尝试模仿其他解决方案来解决这个问题失败了。
编辑: 这是视图:
<div class="container story-container" ng-controller="StoryController as storyCtrl">
<aside class="players" id="players"><h1>Players </h1>
<input name="username" type="text" ng-model="storyCtrl.username"/>
<ul class="players-list">
<li>{{storyCtrl.username}}</li>
<li ng-repeat="player in game.settings.players">{{player}}</li>
</ul>
</aside>
<div class="main">
<h1 class="story-title">{{game.settings.title}}</h1>
<ul class="story">
<li ng-repeat="storyPoint in storyCtrl.points"><p>{{storyPoint.body}}</p></li>
<li><p>{{storyCtrl.point.body}}</p></li>
</ul>
<form name="storyForm" ng-submit="storyCtrl.addPoint(storyCtrl)">
<textarea ng-model="storyCtrl.point.body" name="storyPoint" rows="5"></textarea>
<input class="btn btn-success" type="submit"/>
</form>
</div>
问题是 Socket.io 不在 angular 生命周期内,因此 Angular 不知道新数据进来了。你是对的,你需要将 $scope
注入您的控制器,并在您的 socket.io 回调中执行 $scope.$apply()
作为最后一个操作。
$scope.$apply()
让 angular 知道数据已经更新,并刷新需要刷新的内容。
app.controller('StoryController', ['$http', '$scope', function($http, $scope){
var story = this;
socket.on('new storyPoint', function(msg){
//console.log('new storyPoint!', msg);
$scope.$apply(function(){
story.points.push(msg);
$('.story').scrollTop($('.story')[0].scrollHeight);
console.log('last story point:', story.points[story.points.length - 1]);
});
});
}]);
以下代码对我有用,每当你从套接字收到消息时,你只需要在 $scope.$apply() 函数中绑定你的代码
socket.onmessage = function (e) {
$scope.$apply(function () {
$scope.onMessge(e);
});
};