0

在我们的总体布局中,我们有一个侧边栏,其中包含一些用户详细信息,如姓名和缩略图。但也有一些不同的东西。

我们的想法是使用指令加载侧边栏,在其中有 2 个模板,1 个在登录时,1 个在注销时。

显示和不显示用户详细信息。

但是,我们有一个名为 sidebar 的指令,可以与 2 个中的任何一个一起使用,

App.directive('sidebar', ['UserService', '$compile', function(User, $compile) {

var getTemplate = function() {
    console.warn(User.isLogged);
    var templateUrl = "#sidebar" + ((User.isLogged) ? '_loggedin' : '') + "_template";
    console.log('requesting template: [%s]', templateUrl);
    return $(templateUrl).html();
};

return {
    restrict: 'A',
    link: function link(scope, element, attrs) {
        var tmpl = getTemplate();
        element.html(tmpl);
        element.replaceWith($compile(element.html())(scope));
    },
    template: getTemplate()
};

}]);

我们在服务中加载我们的用户详细信息

App.factory('UserService', [function userService() {
var User = {
    isLogged: false,
    username: ''
};
return User;
}]);

登录表单将此UserService作为依赖项接受,并将其设置isLoggedtrue

但是我怎样才能让指令重绘侧边栏,当isLogged改变时?

我们这样做是否正确?

4

1 回答 1

1

有一个称为编译阶段的阶段,其中

遍历 DOM 以识别模板中所有已注册的指令。对于每个指令,它会根据指令的规则(模板、替换、转置等)转换 DOM,如果存在则调用 compile 函数。结果是一个编译的模板函数,它将调用从所有指令中收集的链接函数。

基本上,你不能有条件地加载模板——它会编译你给它的第一个模板。如果你想动态渲染你的视图,你可以在模板中使用两个带有 ng-show 指令的 div:

<div ng-show="user.isLogged">// logged in content</div>
<div ng-show="!user.isLogged">// logged out content</div>

你可能认为你需要在你的指令中注入一个工厂——我刚刚尝试过,但它不起作用!我相信这是因为指令只能与作用域链上的指令建立单向和双向绑定。考虑到这一点,我将用户对象引入了应用程序范围:

App.controller("AppCtrl", function($rootScope, UserService) {
  $rootScope.user = UserService;
})

然后使用指令中的开放范围:

app.directive("sidebar", function() {

  return {
    restrict: "A",
    template: '<div>' +
      '<div ng-show="user.isLogged">Logged In</div>' +
      '<div ng-show="!user.isLogged">Logged Out</div></div>',
  }

})

这里的用户对象是通过范围链接找到的。因为该指令没有独立的范围(我没有声明范围属性),所以它通过范围链找到它 - 一直到根范围。从某种意义上说,这当然是一个“全局”,并且很容易被隐藏:

$scope.user = somethingElse

不是最漂亮的解决方案,但它可以完成工作。

您还可以有条件地在链接函数中操作 DOM,或者更好的是 - 使用嵌套模板将这种逻辑加载到路由器并解析。

于 2013-07-26T13:39:18.933 回答