Max*_*ini 5 javascript angularjs
我有一个由多个模块组成的单页AngularJS应用程序,其目的是为用户提供协作板(主要小部件)和其他相关小部件(其他连接用户,pad元数据等).
我选择拆分应用程序如下:
让我们通过假设我只有一个小部件来简化这一点,小部件的唯一目标是向用户显示状态消息:"authenticating","authenticated","error"或"ready".
我选择在服务中使用订阅/通知模式,以通知窗口小部件共享组件状态的更改.
服务:
angular.module("app.core").factory("padService", padService);
function padService() {
// Callback registration and notification code omitted
return {
initialize: function (authToken) { ... },
onAuthenticated: function (callback) { ... },
onReady: function (callback) { ... },
onError: function (callback) { ... }
};
}
Run Code Online (Sandbox Code Playgroud)
小部件:
angular.module("app.widget").directive("widget", widget);
function widget() {
return {
templateUrl: 'app/widget.html',
restrict: 'E',
controller: widgetController
};
}
function widgetController($scope, padService) {
$scope.message = "authenticating";
padService.onAuthenticated(function (user) {
$scope.message = "authenticated";
// Do other stuff related to user authentication event
});
padService.onReady(function (padInstance) {
$scope.message = "ready";
// Do other stuff related to pad readiness event
});
padService.onError(function (error) {
$scope.message = "error";
// Do other stuff related to error event
});
}
Run Code Online (Sandbox Code Playgroud)
现在,"初始化模块"以其最简单的形式authToken从URL片段(类似于OAuth2)收集身份验证令牌并简单地调用padService.initialize(authToken);.请注意,它也可以是专用的身份验证弹出窗口,这就是它驻留在自己的模块中的原因.
我的问题是我不知道在哪里放这段代码.我尝试过的所有地方都导致在角度引导过程中过早放置和/或没有更新小部件:
angular.module("app.initializer").run(run);
function run($document, $timeout, tokenService, padService) {
// This does not work because run() is called before the
// controllers are initialized (widget does not get notified)
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
$document.ready(function () {
// This does not work because angular does not detect
// changes made to the widget controller's $scope
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
// This does not work in firefox for some reason (but
// does in chrome!)... except if I enter debug mode or
// set the timeout to a longer value, which makes it
// either really difficult to diagnostic or ugly as hell
$timeout(function () {
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
}, 0);
});
}
Run Code Online (Sandbox Code Playgroud)
控制器是同步创建的(我假设),因此之后运行一些代码应该没有任何困难。
这是一个错误的假设。AngularJS 框架在应用程序的生命周期中定期创建和销毁指令及其控制器。ng-repeat、ng-if、ng-include等都创建和销毁包含指令的 DOM。如果您的“小部件”是 的一部分ng-repeat,则其控制器会被实例化多次,针对ng-repeat 监视列表中的每个项目实例化一次。
要保留在应用程序的整个生命周期中持续存在的数据,请将其保留在服务中。(或者 on $rootScope;不推荐,但可以选择。)控制器不能假设它们已在引导期间启动。他们需要“赶上”并订阅变化。
将持久数据保存在工厂服务中并提供setter和getter函数。
angular.module("app").factory("padService", function () {
//Store service status here
var status = "none-yet";
function setStatus(s) {
status = s;
return status;
};
function getStatus() {
return status;
};
return {
setStatus: setStatus,
getStatus: getStatus
};
});
Run Code Online (Sandbox Code Playgroud)
在您的“小部件”中,注入服务、订阅更改并“赶上”。
angular.module("app").directive("widget", function() {
function widgetController($scope, padService) {
//subscribe with $watch
$scope.$watch(padService.getStatus, function(newStatus) {
//catch-up and react to changes
case (newStatus) {
"authenticated":
// Do stuff related to authenticated state
break;
"ready":
// Do stuff related to pad ready state
break;
"error":
// Do stuff related to error state
break;
default:
// Do something else
}
$scope.message = newStatus;
};
};
return {
templateUrl: 'app/widget.html',
restrict: 'E',
controller: widgetController
}
});
Run Code Online (Sandbox Code Playgroud)
当指令首次使用 注册监听器时$watch,AngularJS 框架将执行 watch 函数(在本例中为padService.getStatus),并执行监听器函数。这允许指令“赶上”服务的当前状态。
在每个摘要周期中,AngularJS 框架都会执行padService.getStatus. 如果状态发生变化,框架将执行侦听器函数,并将新状态作为第一个参数。这允许指令对更改做出反应。
您不能假设指令及其控制器是同步创建的。但您确实知道该服务在注入控制器之前已实例化并执行其构造函数。
| 归档时间: |
|
| 查看次数: |
4193 次 |
| 最近记录: |