【问题标题】:How could I implement a fuzzy time date replacer using Knockout?如何使用 Knockout 实现模糊时间日期替换器?
【发布时间】:2012-06-29 21:09:58
【问题描述】:

我想用 jQuery 实现这个插件的功能: https://github.com/rmm5t/jquery-timeago

对该插件的简短描述:

这会将所有 abbr 元素转换为 timeago 类和 ISO 8601 标题中的时间戳(符合 datetime 设计模式 微格式):

<abbr class="timeago" title="2011-12-17T09:24:17Z">December 17, 2011</abbr>

变成这样:

<abbr class="timeago" title="December 17, 2011">about 1 day ago</abbr>

除了使用敲除,我的标记如下所示:

<abbr data-bind="attr: { title: Posted }" class="timeago"></abbr>

我认为有些东西没有同步,因为即使我在视图模型本身中调用 timeago 也没有发生任何事情。我猜我需要一个附加到可观察的“已发布”的订阅者,但我不确定如何设置它。

【问题讨论】:

    标签: jquery knockout.js knockout-2.0


    【解决方案1】:

    您的方法不起作用,因为 timeago 通过 jQuery 的 data() 函数创建了一个缓存。因此,仅仅更新标题是不够的。

    我认为自定义绑定是最好和最干净的方式:

    ko.bindingHandlers.timeago = {
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            var $this = $(element);
    
            // Set the title attribute to the new value = timestamp
            $this.attr('title', value);
    
            // If timeago has already been applied to this node, don't reapply it -
            // since timeago isn't really flexible (it doesn't provide a public
            // remove() or refresh() method) we need to do everything by ourselves.
            if ($this.data('timeago')) {
                var datetime = $.timeago.datetime($this);
                var distance = (new Date().getTime() - datetime.getTime());
                var inWords = $.timeago.inWords(distance);
    
                // Update cache and displayed text..
                $this.data('timeago', { 'datetime': datetime });
                $this.text(inWords);
            } else {
                // timeago hasn't been applied to this node -> we do that now!
                $this.timeago();
            }
        }
    };
    

    用法就这么简单:

    <abbr data-bind="timeago: Posted"></abbr>
    

    演示:http://jsfiddle.net/APRGc/1/

    【讨论】:

    • 几分钟后会在这里尝试,这是我开始的路线,但不确定。感谢您的回答。
    • $this.attr('title', value); 行替换为$this.attr($.timeago.isTime($this) ? 'datetime' : 'title', value);,使其与&lt;time&gt; 一起使用
    • 应该注意 timeago 只接受 ISO 时间字符串 (github.com/rmm5t/jquery-timeago/issues/76) 所以一定要在你的日期对象上调用 .toISOString()。
    • timeago 现在有一个 updateFromDOM 方法,现在可用于简化此代码。似乎其他人正试图让 timeago 使用淘汰赛绑定 - 请参阅:github.com/rmm5t/jquery-timeago/pull/132
    【解决方案2】:

    这是一个替代方案,与 Niko 的答案相比,它可能根本没有任何优势,除了可能稍微简单一点:) --

    usf.ko.bindings['timeago'] = {
      update: function(element, valueAccessor) {
        var $element, date;
        date = ko.utils.unwrapObservable(valueAccessor());
        $element = $(element);
        if (date) {
          $element.attr('title', date.toISOString());
          $element.data('tiemago', false);
          return $element.timeago();
        }
      }
    };
    

    【讨论】:

    • 这个解决方案有一个主要缺点:timeago('refresh')timeago() 没有什么不同,因为没有公共的“刷新”方法。这实际上意味着每次更新 observable 时,都会使用“setInterval”创建一个新计时器来管理自动刷新。所以你有一个潜在的内存泄漏。
    • @Niko:'refresh' 是一个错字(一厢情愿?)。 :) 你是对的 setInterval 是潜在的内存泄漏。由于这个原因,我建议的代码不应该被使用。
    猜你喜欢
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多