如何“取消观看"一个表情 [英] How to 'unwatch' an expression

查看:20
本文介绍了如何“取消观看"一个表情的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个带有大数组的 ng-repeat.

当 ng-repeat 运行时,它会将该数组的每个元素添加到一个隔离的作用域中,并将数组本身添加到一个作用域中.这意味着 $digest 检查整个数组是否有变化,最重要的是,它会检查该数组中的每个单独元素是否有变化.

这个plunker为例,说明我在说什么.

在我的用例中,我从不更改数组的单个元素,因此我不需要监视它们.我只会改变整个数组,在这种情况下 ng-repeat 会重新渲染整个表格.(如果我错了,请告诉我..)

在(比如说)1000 行的数组中,还有 1000 个不需要计算的表达式.

如何在观察主数组的同时从观察者中注销每个元素?

也许不是取消注册,我可以更好地控制我的 $digest 并以某种方式跳过每一行?

这个具体案例实际上是一个更普遍的问题的例子.我知道 $watch 返回注销"功能,但是当指令正在注册手表,这是大部分时间.

解决方案

拥有一个大阵列的中继器,您不必观看每一项.

您需要创建一个自定义指令,该指令将一个参数和表达式传递给您的数组,然后在链接函数中您只需查看该数组,并且您将让链接函数以编程方式刷新 HTML(而不是而不是使用 ng-repeat)

类似(伪代码):

app.directive('leanRepeat', function() {返回 {限制:'E',范围: {数据":="},链接:函数(范围,元素,属性){scope.$watch('data', function(value) {elem.empty();//假设这里是jquery.angular.forEach(scope.data, function(d) {//写它但是你要在这里写出来.elem.append('

' + d + '

');});});}};});

...这似乎很痛苦.

替代黑客方法

您可以循环遍历 $scope.$$watchers 并检查 $scope.$$watchers[0].exp.exp 以查看它是否匹配您想要删除的表达式,然后使用简单的 splice() 调用将其删除.这里的 PITA 是标签之间的 Blah {{whatever}} Blah 之类的东西将是表达式,甚至包括回车.

从好的方面来说,您可以循环遍历 ng-repeat 的 $scope 并删除所有内容,然后明确添加您想要的手表......我不知道.

无论如何,这似乎是一种黑客行为.

删除 $scope.$watch 制作的观察者

您可以使用 $watch 调用返回的函数取消注册 $watch:

例如,让 $watch 只触发一次:

var unregister = $scope.$watch('whatever', function(){警报('一次!');注销();});

当然,您可以随时调用取消注册函数……这只是一个例子.

结论:没有什么好方法可以完全按照您的要求去做

但要考虑一件事:是否值得担心?此外,将数千条记录分别加载到数十个 DOMElements 中真的是个好主意吗?值得深思.

希望能帮到你.


EDIT 2(删除坏主意)

Say I have an ng-repeat with a big array.

When ng-repeat runs, it adds every element of that array to an isolated scope, as well as having the array itself in a scope. That means that $digest checks the entire array for changes, and on top of that, it checks every individual element in that array for changes.

See this plunker as an example of what I'm talking about.

In my use case, I never change a single element of my array so I don't need to have them watched. I will only ever change the entire array, in which case ng-repeat would re-render the table in it's entirety. (If I'm wrong about this please let me know..)

In an array of (say) 1000 rows, that's 1000 more expressions that I don't need evaluated.

How can I deregister each element from the watcher while still watching the main array?

Perhaps instead of deregistering I could have more control of my $digest and somehow skip each individual row?

This specific case is actually an example of a more general issue. I know that $watch returns a 'deregisteration' function, but that doesn't help when a directive is registering the watches, which is most of the time.

解决方案

To have a repeater with a large array that you don't watch to watch every item.

You'll need to create a custom directive that takes one argument, and expression to your array, then in the linking function you'd just watch that array, and you'd have the linking function programmatically refresh the HTML (rather than using an ng-repeat)

something like (psuedo-code):

app.directive('leanRepeat', function() {
    return {
        restrict: 'E',
        scope: {
           'data' : '='
        },
        link: function(scope, elem, attr) {
           scope.$watch('data', function(value) {
              elem.empty(); //assuming jquery here.
              angular.forEach(scope.data, function(d) {
                  //write it however you're going to write it out here.
                  elem.append('<div>' + d + '</div>');
              });
           });
        }
    };
});

... which seems like a pain in the butt.

Alternate hackish method

You might be able to loop through $scope.$$watchers and examine $scope.$$watchers[0].exp.exp to see if it matches the expression you'd like to remove, then remove it with a simple splice() call. The PITA here, is that things like Blah {{whatever}} Blah between tags will be the expression, and will even include carriage returns.

On the upside, you might be able to just loop through the $scope of your ng-repeat and just remove everything, then explicitly add the watch you want... I don't know.

Either way, it seems like a hack.

To remove a watcher made by $scope.$watch

You can unregister a $watch with the function returned by the $watch call:

For example, to have a $watch only fire once:

var unregister = $scope.$watch('whatever', function(){ 
     alert('once!');
     unregister();
});

You can, of course call the unregister function any time you want... that was just an example.

Conclusion: There isn't really a great way to do exactly what you're asking

But one thing to consider: Is it even worth worrying about? Furthermore is it truly a good idea to have thousands of records loaded into dozens of DOMElements each? Food for thought.

I hope that helps.


EDIT 2 (removed bad idea)

这篇关于如何“取消观看"一个表情的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆