【问题标题】:Angular component triggering method call before variable is updated更新变量之前的角度组件触发方法调用
【发布时间】:2017-02-15 23:55:07
【问题描述】:

我目前正在重构 Angular 1.5.8 应用程序中的一些代码以使用组件。

(与本指南中的一些步骤非常相似:https://teropa.info/blog/2015/10/18/refactoring-angular-apps-to-components.html) 基本情况正常。

但是当我需要让我的组件同时更新一个变量并调用一个函数(都从父级绑定)时,我遇到了一个问题。在这种情况下,函数调用似乎发生在变量绑定之前。因此,当方法在父级上执行时,它仍然使用变量的旧内容。

如何确保在方法执行之前变量已更新?

看下面代码中的注释,就是reset()函数的两行。

angular.module('searchfieldComponent', [])

.component('searchfieldComponent', {
    templateUrl: "/js/common/components/searchfield.component.tpl.html",
    bindings: {
        labelText: '@',
        searchText: '=',
        searchCallback: '&'
    },
    controllerAs: "vm",
    controller: [function() {

        var vm = this;

        vm.search = function() {
            vm.searchCallback();
        }

        vm.reset = function() {
            vm.searchText = null;
            // When the method bound to searchCallback executes in the parent,
            // the variable bound to searchText has not yet been set to null
            // it is still the old value.
            vm.searchCallback();
        }
    }]
});

【问题讨论】:

  • 当你使用一个对象在组件之间传递数据,然后修改它的属性时会发生什么?喜欢searchData: '="; /*...*/ vm.searchData.text = null
  • 那行得通。谢谢!我想这是因为它始终是同一个对象,所以我以这种方式避免了时间问题。随意将其发布为答案,但我认为包装对象是一种解决方法,而不是最佳解决方案。如果没有更好的答案出现,我会在几天后接受。

标签: angularjs


【解决方案1】:

问题的关键在于思考这条线是什么...

vm.searchText = null;

... 确实如此。当然,它会更新在“子”范围内设置的值。但是“父”值究竟是什么时候更新的呢?

无法通过标准原型继承机制直接“链接”父范围变量和子范围变量。当您查询child.foo 属性时,名称解析将其值替换为child.__proto__.foo 1。但是一旦你分配东西给child.foo,原型的属性就会被遮蔽。

AngularJS 以其标志性的摘要方法让您摆脱这个牢笼。在摘要阶段,对子范围的更改会传播到父范围(有关更多详细信息,请查看this answer)。但是,如果您想立即基于此做某事,那您就有麻烦了。

有什么补救措施?我在 cmets 中建议的是最知名和尝试过的一个:使用共享对象而不是原始对象,就像这样...

bindings: {
  labelText: '@',
  searchData: '=',
  searchCallback: '&'
}

// then, in vm methods
vm.searchData.searchText = 'anything';

... 这样您就永远不会更改存储在 vm.searchData 中的引用 - 您改为增加它的属性。由于两个组件都“看”在同一个地方,显然它们都看到了变化。


不过,更好的想法可能是重新考虑searchfieldComponent 的整体结构。我不太清楚为什么这里的父作用域应该知道searchText 的值。看,Angular 组件的重点是将一些松散定义的指令转换为具有严格输入和输出集的实体。

对于一个通用的searchField,提供一些预定义的defaultValue 可能是个好主意(这样这将是一个输入,标有'>' 符号)。但是当您需要更改某些内容时,只需让组件通过输出函数发出changedValue(类似于searchCallback,但名称更好) - 并将此值作为参数传递给此函数.

【讨论】:

  • 可能是我的组件太小了?如果我可以通过其他方式避免重复代码,则不需要使用组件,这里只有父级知道 searchText 的上下文。对于组件,它只是一个没有上下文的字符串。该组件提供了一点点通用代码(布局、输入键检测和清除文本的按钮)。
  • 好的,但这有什么关系呢?您仍然需要正确解耦该组件的输入和输出——成为一个组件,而不仅仅是与父级紧密耦合的扩展。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
  • 2021-10-14
  • 1970-01-01
  • 2022-12-05
  • 2022-07-07
  • 2021-01-10
  • 1970-01-01
相关资源
最近更新 更多