Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用ng repeat with指令会导致手表出现缺陷_Javascript_Angularjs_Carousel_Angular Ui Bootstrap - Fatal编程技术网

Javascript 使用ng repeat with指令会导致手表出现缺陷

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

我已经做了一个新的指令,基本上是一个新的旋转木马,它扩展了角度UI旋转木马引导。这个新的旋转木马将在一帧中显示多个div。我的新指令接受数组中的任何数据以及每个数据的自定义html模板

然而,如果我将我的旋转木马与指令一起使用,我会看到指令内的watch出现一种奇怪的行为。一切正常,但指令中的手表总是为
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来隐藏/隐藏父对象,但这只发生在基本对象上,我正在向数据传递一个数组
  • 我需要在我的旋转木马指令中使用ng repeat。。所以我需要知道为什么ng repeat会导致这种情况。。有什么建议吗

    更新:
    在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
    在哪里