【问题标题】:Angular 1.5 component vs. old directive - where is a link function?Angular 1.5 组件与旧指令 - 链接功能在哪里?
【发布时间】:2016-02-15 23:57:04
【问题描述】:

我最近一直在阅读这篇关于 Angular 1.5 中新的 .component() 助手的好消息 article,它应该可以帮助每个人最终迁移到 Angular 2。一切看起来都很好,很简单,但我找不到任何关于组件内部 DOM 操作的信息。

虽然有一个template 属性,它可以是一个函数并接受$element$attrs 参数。我仍然不清楚这是否是 link 函数的替代品。好像不是这样的。

【问题讨论】:

    标签: javascript angularjs angularjs-directive angular-directive


    【解决方案1】:

    好的,现在看来控制器是合适的地方,因为它是唯一可能的地方。我们也不能在组件助手中使用replace 选项。

    【讨论】:

    • replace 已弃用。
    【解决方案2】:

    编辑 2/2/16: 1.5 文档现在涵盖组件:https://docs.angularjs.org/guide/component


    基于阅读的一些想法(以下链接):

    • 组件不是指令的替代品。组件是一种特殊类型的指令,它使用模板组织控制器。

    • 组件没有链接功能,控制器仍然不是您处理 DOM 操作的地方。

    • 如果您需要 DOM 操作,您的组件可以使用在链接函数中包含该 DOM 操作的其他指令。

    我花了一些时间才弄清楚这一点,但一旦我弄明白了,它就有些道理了:组件是指令,但并非所有指令都是——或必须是——组件。

    当我认为组件正在替换指令时,关于链接函数的问题是很自然的,或者对我来说是这样。为什么?因为我们被教导将 DOM 操作放在指令的链接函数中:“想要修改 DOM 的指令通常使用链接选项来注册 DOM 侦听器以及更新 DOM。” https://docs.angularjs.org/guide/directive.

    如果您使用该假设(组件替换指令)运行,那么您会发现 Angular 文档没有回答这个问题,因为,好吧,一旦您知道组件的用途,这不是正确的问题。 (组件在$compileProvider documentation 而非directive documentation 中描述。)

    背景阅读

    我上面所说的实际上是对 Todd Motto 在可能是(迄今为止)关于组件和指令的最佳讨论中所说的话的改写:

    https://www.reddit.com/r/angularjs/comments/3taxjq/angular_15_is_set_to_introduce_the_component/

    将这些 cmets 提取到更一般的文章中可能会很有用。

    大多数关于组件的文章都没有提到链接功能(这并不意味着这些文章不是优秀的文章):

    https://toddmotto.com/exploring-the-angular-1-5-component-method/

    https://medium.com/@tomastrajan/component-paradigm-cf32e94ba78b#.vrbo1xso0

    https://www.airpair.com/angularjs/posts/component-based-angularjs-directives

    或者当提到链接函数时,它在括号中:

    http://teropa.info/blog/2015/10/18/refactoring-angular-apps-to-components.html

    One article 表示组件“使用控制器而不是链接函数”。但这不是“替代”情况:控制器不是链接功能的替代品。

    【讨论】:

    • 说得好。我将组件用于“页面”,其中包含需要 DOM 操作的子指令。一开始这很奇怪,但它工作得非常好,尤其是在 1.5 多嵌入时。
    • 我不知道为什么你说你不应该在组件中进行任何 dom 操作,而 Angular 文档明确指出:“$postLink() - 在此控制器的元素及其子元素被链接后调用. 与 post-link 函数类似,此钩子可用于设置 DOM 事件处理程序并进行直接 DOM 操作。”你能解释一下为什么这对你没有吸引力吗?
    • 我不会在答案中使用“不应该”或“任何”这两个词——如果暗示了这一点,我深表歉意。至于$postLink 是干什么用的,这对阅读很有帮助:toddmotto.com/angular-1-5-lifecycle-hooks#what-postlink-is-not
    • 我是否遗漏了什么,或者组件只是淡化指令的基本共识?可以将组件重新创建为指令,但不能始终将指令重新创建为组件。组件没有指令那么强大,因为它们缺乏执行 DOM 操作的能力。
    • 这是一个很好的答案。 component.$postLink 应该用于在设置 DOM 之后设置逻辑。 directive.link 仍然是 DOM 操作的首选。当您将 $element 注入组件控制器时,您知道是时候创建指令了。
    【解决方案3】:

    根据当前的 Angular2 文档(请参阅 https://github.com/angular/angular/blob/master/modules/angular2/docs/core/02_directives.md),Angular2 中仍然会有指令。所以基本上你可以同时使用@Directive 或@Component,其中:

    • 指令对于封装行为很有用。
    • Component 是一个使用 shadow DOM 来创建封装视觉行为的指令。组件通常用于创建 UI 小部件或将应用程序分解为更小的组件。

    因此,根据这一点,如果您需要 DOM 操作,您将需要使用 @Directive,因此 Angular 1.x 中的 Angular.directive。事件绑定可以使用host 属性来完成。关于 DOM 操作本身,仍然缺少文档(例如 https://github.com/angular/angular/blob/master/modules/angular2/docs/core/09_compilation.mdhttps://github.com/angular/angular/blob/master/modules/angular2/docs/core/08_lifecycle.md),但您可以按照此处 https://stackoverflow.com/a/32062065 的建议查找 Lifecycle

    简而言之,对于 Angular 1.5+,如果您有 DOM 访问权限,请继续使用 angular.directive,否则封装到 angular.component。也尽量减少对非 dom 事件使用 $scope 并更喜欢 RxJS 参见 https://medium.com/front-end-developers/managing-state-in-angular-2-using-rxjs-b849d6bbd5a5#.obgb6dl6n

    【讨论】:

      【解决方案4】:

      这使得以类似于使用 Web 组件或使用 Angular 2 的应用程序架构风格的方式编写应用程序变得更加容易。

      组件的优点:

      比普通指令更简单的配置促进了健全的默认值和 针对基于组件的架构编写优化的最佳实践 组件指令将更容易升级到 Angular 2

      何时不使用组件:

      对于依赖 DOM 操作的指令,添加事件监听器 等等,因为编译和链接功能在您使用时不可用 需要高级指令定义选项,如优先级、终端、 当您想要一个由 属性或 CSS 类,而不是元素

      【讨论】:

        【解决方案5】:

        更新(自 2017 年 8 月 22 日起): $inject 是在 AngularJS 中执行此操作的推荐方法。阅读风格指南: Styleguide link 和 AngularJS 文档:AngularJS docs

        要在组件中使用 DOM 绑定而不是使用链接函数创建指令,您可以在控制器函数中注入“$element”或其他您需要的服务,例如

        app.component('pickerField', {
            controller: PickerField,
            template: '<span>Your template goes here</span>'
          });
        
          PickerField.$inject = ['$element'];
        
          function PickerField(element) {
            var self = this;
            self.model = self.node.model;
            self.open = function() {
              console.log('smth happens here');
            };
            element.bind('click', function(e) {
              console.log('clicked from component', e);
              self.open();
            });
          }

        【讨论】:

        • 注入 $element 是不好的做法。这使得 $componentController 难以测试。
        • @jdrury 实际上,这是 angularJS 推荐的注入依赖项的方式。您可以阅读文档:docs.angularjs.org/guide/di#-inject-property-annotation 和样式指南 github.com/johnpapa/angular-styleguide/blob/master/a1/… 另外我将使用此链接更新我的答案
        • 我同意 - 如果需要将 $element 访问到组件中,您的方式是正确的。但我的论点是,如果你需要访问 $element,你应该使用指令而不是组件。我的原因是:如果你将 $element 注入到一个组件中,当你使用 $componentController 进行单元测试时,你将不得不通过 $compile 创建一个假的 $element。
        【解决方案6】:

        您可以使用最新角度的 $postLink() 函数。

        https://docs.angularjs.org/guide/component

        类似于 post-link 函数,这个钩子可以用来设置 DOM 事件处理程序并进行直接 DOM 操作。

        【讨论】:

          猜你喜欢
          • 2016-05-16
          • 1970-01-01
          • 2016-05-30
          • 2016-08-09
          • 1970-01-01
          • 1970-01-01
          • 2016-12-23
          • 2011-04-03
          • 2013-01-27
          相关资源
          最近更新 更多