Javascript 使用ng repeat with指令会导致手表出现缺陷
我已经做了一个新的指令,基本上是一个新的旋转木马,它扩展了角度UI旋转木马引导。这个新的旋转木马将在一帧中显示多个div。我的新指令接受数组中的任何数据以及每个数据的自定义html模板 然而,如果我将我的旋转木马与指令一起使用,我会看到指令内的watch出现一种奇怪的行为。一切正常,但指令中的手表总是为Javascript 使用ng repeat with指令会导致手表出现缺陷,javascript,angularjs,carousel,angular-ui-bootstrap,Javascript,Angularjs,Carousel,Angular Ui Bootstrap,我已经做了一个新的指令,基本上是一个新的旋转木马,它扩展了角度UI旋转木马引导。这个新的旋转木马将在一帧中显示多个div。我的新指令接受数组中的任何数据以及每个数据的自定义html模板 然而,如果我将我的旋转木马与指令一起使用,我会看到指令内的watch出现一种奇怪的行为。一切正常,但指令中的手表总是为newVal和oldVal获取相同的值。我的意思是,这是我的旋转木马代码: <slide ng-repeat="frame in ctrl.frames"> <div
newVal
和oldVal
获取相同的值。我的意思是,这是我的旋转木马代码:
<slide ng-repeat="frame in ctrl.frames">
<div ng-repeat="divs in frame.divs">
<custom-directive data="divs"></custom-directive>
</div>
</slide>
newVal和oldVal总是一样的。。我希望初始状态是oldVal=undefined
,而newVal
将是我的新数据。然而,事实并非如此。数据作为双向绑定传递到carousel和custom指令(在每个指令的范围内使用“=”运算符)
为什么会发生这种情况?我对此进行了长期调查,以下是我的发现:
ng repeat
,此将起作用<代码>旧值将是未定义的
,新值
将是初始状态下的我的数据。但为什么是ng重复导致这种情况?我读过很多关于原型继承的黄金法则的文章,其中说ng repeat将创建新的childScope来隐藏/隐藏父对象,但这只发生在基本对象上,我正在向数据传递一个数组在Plunkr中重现了这个问题。正如您所看到的,oldValue始终与newValue相同(我希望oldValue在开始时未定义)我认为您遇到的问题只是对
$watch
工作原理的误解
$watch
应使用相等的值初始化。请参阅文档。具体而言:
观察者注册到作用域后,监听器fn
异步调用(通过$evalAsync)初始化观察程序。在里面
在极少数情况下,这是不可取的,因为侦听器在
watchExpression的结果没有改变。要检测此场景
在侦听器fn中,可以比较newVal和oldVal。如果
这两个值是相同的(==),然后调用侦听器
初始化
换句话说,检查它们是否相等,这样就不会检测到初始呼叫
在提供的Plunker中,如果需要执行一些初始化代码,可以执行两件事:
$watch
函数中检查它们是否相等,如果相等,则这是带有初始值的初始调用链接
函数中的该函数之外,这些值是它们在那里的初始值(因为链接
函数相当于后链接
,这意味着范围
值已经链接),因此您可以将代码放在那里警报
移到了$watch
之外,并且该值仍然有效
编辑:
当它不在ng repeat
中并且设置为类似于Plunkr中注释掉的代码时,之所以会出现差异,是因为您在$timeout
中添加了数据。当页面最初加载时,以下是两种类型的呈现方式:
- HTML看起来与编写时一样<代码>数据=[]。存在指令元素,使用
数据[0]=未定义的
调用
链接
调用时使用<代码>$watch
prop=undefined
- HTML只是一个注释。等待填充
。不存在指令元素,这意味着不调用数据
链接
数据
添加项目时,它们如下所示:
$scope.$watch("ctrl.data", function(newVal, oldVal){
if (newVal !== oldVal) {
// data is updated, redraw the directive in my case
// however newVal is always the same as oldVal
}
})
- 同上<代码>数据[0]现在已定义,因此已定义
prop
(x3)
- 页面现在有了指令元素。调用
函数,现在已填充链接
调用时链接了数据<代码>$watch
值prop
当您在
链接
函数中注册$watch
时,Angular已经在预链接
阶段处理了绑定,因此您将永远不会在第一次执行watcher时看到未定义的
(该初始化调用是oldVal和newVal可能相同的唯一时刻。如果在绑定解析之前注册了观察者,则oldValue将是未定义的)
如果您确实想查看它,可以覆盖编译
阶段,并添加一个自定义的预链接
方法(默认的链接
是后链接
)
但我真的怀疑你是否想这么做。为什么第一次没有定义是个问题?你应该试着解释你面临的真正问题
另外,请注意,如果传递给指令的
divs
是一个数组,则应使用scope.$watchcollection
而不是scope.$watch
来检测数组元素中的更改,而不是整个数组指针的更改。是否确实正在调用此函数?或者只是因为它已被调用如果(newVal!==oldVal)code?(初始值之外),则从未进入if(newVal!==oldVal)
code?(还有一点不清楚ctrl.data
与html中ng repeat
s中的数据的关系。html中使用的ctrl.data
在哪里