javascript - AngularJS1 指令隔离作用域中的双向绑定模型数据不能及时更新
怪我咯
怪我咯 2017-04-11 11:54:15
0
5
345

我使用 AngularJS 1.5.0 和 bootstrap 写了一个简单的分页指令,完整代码在这里:https://github.com/clearbug/c...
当分页的页码改变时,我调用了外部的方法:https://github.com/clearbug/c...
外部方法:https://github.com/clearbug/c...
但是不明白为啥指令里面$scope.currentPageNo已经更新了,但外面还是旧值,请问我在调用外部方法之前怎么让外部的值及时更新呢?

怪我咯
怪我咯

走同样的路,发现不同的人生

reply all (5)
刘奇

这个应该是你想要的效果吧?其实解决方式很简单,在index.html里面把$scope.currentPageNo = 1改成$scope.current = { pageNo: 1 }

当然,相应地:

$scope.toSearch = function(){ console.log('To search ' + $scope.current.pageNo); };

另外 directive 定义部分也要改:

scope: { totalItems: '=totalItems', itemsPerPage: '=itemsPerPage', maxItemsNum: '=maxItemsNum', current: '=current', changePageNo: '&changePageNo' },

读完 AngularJS 的官方 wiki 就明白了:https://github.com/angular/an...

讲道理,楼上说到的,用$watch或者$timeout之类的应该也行,但恐怕不是最好的写法。


我个人觉得,这是 JavaScript 中传值方式导致的。。你可以考虑下,JS 中这段代码输出的是啥:

function update(a, b, c) { a = a * 2; b.value = 2; c = {value: 2}; } var num = 10; var foo = {value: 1}; var bar = {value: 1}; update(num, foo, bar); console.log(num); console.log(foo.value); console.log(bar.value); //output: // 10 // 2 // 1

numbar都没有变。印象中,这种传值方式应该符合pass by sharing: https://en.wikipedia.org/wiki...
不过我一直的理解是:primitive value 是 pass by value的,而 Object 就是 pass by reference我知道这样说可能不够确切。。

这里的update可以近似的理解为 AngularJS 中的$scope.$apply(),是由$watch检测到$dirty的情况下触发的。foo.value相当于我的写法里面的current.pageNo,当然这个current$scope上的一个属性。num相当于你的写法里面的$scope.currentPageNo

所以这时候,我们需要的是直接把current这个 Object 按照引用(Pass by reference)的方式传进来,而不是把 Object 里面的某一个属性按照值传递(Pass by value)的方式传进来。


试着帮你分析一下,从点击到输出 console log 的过程:

  1. 点击了页码,ng-click的绑定使得 directive 中的changeCurrentPageNo()这个方法触发

  2. 触发后,directive 的scope.currentPageNo会更新,但这一步并不会让 parent 更新

  3. 然后你调用了来自父级的方法changePageNo(),这时候父级只知道你调用了changePageNo这个方法,然而并不知道currentPageNo已经在 directive 中改变。确切一点儿说,你改的是值本身,而不是改了引用。请参考上面例子中的bar情况。所以,这时候只有 directive 内部知道,而父级不知道

  4. 这时候,"digest loop" 得到了第一步触发,启用了$watch(当然也会触发 dirty 检查)。但由于父级上的值并没有改变,你在console.log的时候,还是原来的值。既然也没监测到变化,当然,页面上的数据也是不会更新的

  5. directive 执行完毕,触发$apply,这时候currentPageNo终于得到了更新,父级的也更新了,但这个发生的太晚,你已经看不到了。不过,你在下一次调用的changePageNo的时候,console log 才会输出这一次的值,然后又把它更新到了一个新的值

不知道这样分析是否正确。

    阿神

    $timeout(function(){

    $scope.xxx = xxx

    }, 0)
    原因在于调用第三方方法,angular不能捕捉到变化

      小葫芦

      试试$watch这个函数,手动刷新

        刘奇

        在link里面注册$watch

          Ty80

          调用外部方法后,要数据同步,需要手工执行 $scope.$digest(). 或者 将执行部分放在 $scope.$apply()方法内 来使Angular触发脏检查.

            Latest Downloads
            More>
            Web Effects
            Website Source Code
            Website Materials
            Front End Template
            About us Disclaimer Sitemap
            php.cn:Public welfare online PHP training,Help PHP learners grow quickly!