我目前正在使用角度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();
}
}]
});
答案 0 :(得分:1)
问题的关键在于考虑这条线......
vm.searchText = null;
......确实如此。当然,它会更新“孩子”的价值。范围。但究竟是什么时候父母'价值更新?
直接'链接'父和子范围变量通过标准原型继承机制。在查询child.foo
属性时,名称解析用child.__proto__.foo
替换其值。但是,只要您将某些内容分配给child.foo
,原型的属性就会被隐藏。
AngularJS通过其商标摘要方法让您离开这个监狱。在摘要阶段,对子范围的更改会传播到父级范围(有关详细信息,请查看this answer)。但是,如果你想立即做一些事情,你就会遇到麻烦。
补救措施是什么?我在评论中建议的那个是最着名和最有用的一个:使用共享对象而不是原始对象,像这样......
bindings: {
labelText: '@',
searchData: '=',
searchCallback: '&'
}
// then, in vm methods
vm.searchData.searchText = 'anything';
...以便您永远不会更改存储在vm.searchData
中的引用 - 而是增加其属性。而且因为这两个组件看起来都是'在同一个地方,显然他们都看到了变化。
但更好的想法可能是重新考虑整体searchfieldComponent
的结构。我不太清楚为什么这里的父范围应该知道searchText
的价值。请注意,Angular组件的重点是将一些松散定义的指令转换为具有严格输入和输出集的实体。
对于通用searchField
,最好为其提供一些预定义的defaultValue
(因此这将是一个输入,标有'>'
符号)。但是当你需要改变某些东西时,让组件通过输出函数发出changedValue
(类似于searchCallback
,但名字更好) - 并将此值传递给此函数参数