【问题标题】:In Angular, what ways can you auto-update a data binding that is bound to a method?在 Angular 中,有哪些方法可以自动更新绑定到方法的数据绑定?
【发布时间】:2015-05-20 15:14:00
【问题描述】:

假设你有一个带有方法的对象:

/*
chat.author    ==  a String
chat.message   ==  a String
chat.timestamp ==  a Date 
chat.timeago() ==  a method that returns a string, like "2 minutes ago"
*/

你的 html 看起来像这样:

<div>{{ chat.author    }}</div>
<div>{{ chat.message   }}</div>
<div>{{ chat.timeago() }}</div>

chat.timeago() 的返回值会根据从chat.timestamp 开始经过的时间而变化,所以它可能会从“刚刚”、“几秒钟前”、“一分钟前”、“ 2 小时前”等。

存在哪些选项来指示 Angular 何时更新绑定到方法的数据,哪个选项是 Angular 中最优雅或最传统的方式?

【问题讨论】:

  • 我建议使用指令来表示 timeago,并使用特定的间隔并在 UI 上手动绘制它,使用原生 DOM 操作,如 innerHTML,甚至使用 jqlite .text/.html。如果您使用 $timeout, $interval(very bad) 它将再次运行摘要周期以及所有观察者......只是为了更新 timeago 它是一种过度杀伤力,尤其是当您的应用程序变大时。使用角度,您需要回复摘要周期以更新绑定,并且最终会超时等......这有其自身的缺点。
  • @PSL 好点在这里。指令将是实现这一目标的一种更难但更好的方法。
  • @Okazari 是的,但这绝对值得,但不会更难实施。在上次 ng-conf 中看到有一个演示文稿对此进行了讨论,即使对于 mouseover/mouseout 效果也不使用 ng-* 事件,而只是手动绑定事件。在较大的 ui 上或(当它变大时)您最终会遇到严重的性能问题。因此,只有在真正值得时才调用摘要循环..
  • @PSL 一般来说,我不喜欢使用自定义指令。它几乎总是做一些你可以用角度内置服务/指令做的事情,或者它不是指令的目的。据我所知,指令旨在向某些组件添加行为。这正是一个很好的自定义指令的一个很好的用例。
    0
    之类的东西。你有关于这些信息的链接吗?我对此很感兴趣。
  • @PSL 我喜欢这种思维方式。它真的很适合 Angular 的。感谢您提供的信息,我会尽快观看。

标签: javascript angularjs data-binding


【解决方案1】:

您应该绑定到变量形式范围并使用$timeout function 更新此变量。

Angular 只能在某些条件发生时刷新视图状态(执行回调,接收 AJAX,更新 $scope,...),所以你不能绑定到函数并期望它自动刷新

【讨论】:

    【解决方案2】:

    你的做法是完全可以接受的。

    绑定到方法与绑定到变量没有什么不同。每当摘要循环运行时,它都会像评估表达式一样评估每个绑定,并且 Angular 为更复杂的表达式(三元表达式、数学运算符等)提供了很多支持。

    顺便说一句,将表达式放在$watch 中没有任何好处,因为您的绑定会形成一个隐式监视。

    编辑:如果您希望值随着时间的推移而更新,请按照其他人的建议使用 $timeout/$interval 服务。

    【讨论】:

    • 我在一个项目中工作时遇到了很多 Angular 的性能问题。我们发现绑定方法比绑定 var 的成本更高。在每个摘要中,它将运行整个函数,而不仅仅是在前一个值和新值之间进行比较。最好根据需要绑定一个变量并更新它。
    • @Okazari 我理解您的担忧——当您使用过滤器时也会出现同样的问题。虽然我有点惊讶你的发现会显示出很大的不同。我很想在这方面看到一个 jsperf。
    • 团队打破了几乎所有的网络标准(客户要求),做了一些丑陋的事情。我们做了很多工作来找到所有这些麻烦的来源。这是很多事情,包括这个。只有很少的东西,但很多(页面上的 2000 和 6000 之间的绑定)。耻辱殿堂是绑定函数和 $watch 使用。
    • 很高兴知道。我们使用闭包编译器,如果函数体很简单,它将消除额外的函数调用。因此,在所有情况下,我们都致力于提高可读性。我将把这个提交给 Angular 团队,看看他们怎么说,但我确实知道你在说什么,这是一个很好的了解。
    【解决方案3】:

    在我看来,这应该是这样的:

    <div>{{ chat.author    }}</div>
    <div>{{ chat.message   }}</div>
    <div>{{ chat.timeago.time   }}{{chat.timeageo.message}}</div>
    

    在您的控制器中:

     $scope.chat = {
        author: "Me",
        message: "Hi!",
        timeago: {
             time: 0,
             message: "seconds ago"
        }
     }
    

    现在在您的控制器中,您可能会使用$interval 服务来更新您的“timeago”消息

    var updateTimeago = function(){
        $scope.timeageo += 10;
    };
    $interval.(updateTimeago(), 10000);
    

    您的消息每 10 秒更新一次。

    修改它以满足您的确切需求。希望对您有所帮助。

    编辑:正如 PSL 建议的那样,使用自定义指令来更新计时器而不是使用 $interval 会很好,因为在性能方面可能有点贪婪。

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多