我如何不断更新绑定到视图中的数据的值 [英] How can i constantly update a value databinded to a view in knockout

查看:80
本文介绍了我如何不断更新绑定到视图中的数据的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要创建这样的收件箱邮件下拉列表

I am to create an inbox messages drop down like this,

是通过JS时刻显示消息的相对时间.下面的代码片段显示了最终结果.但是此代码的问题在于,以毫秒为单位的时间不会间隔更新以显示毫秒与当前日期的相对时间.所以我尝试在方法内部使用设置间隔.

were the relative time of the message gets displayed via moment JS. The following snippet below shows the final result. but the problem with this code is that the time which is in milliseconds does not get updated at interval to show the relative time of the milliseconds with the present date. So i tried using set interval inside the method.

未设置时间间隔示例(效果很好,但是最终转换时间在第一次更改后不会改变)

Non Set interval Example (works fine, but the final converted time doesnt change after being changed the first time)

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>

<table>
        <thead>
            <tr><th>First name</th><th>Last name</th></tr>
        </thead>
        <tbody data-bind="foreach: people">
            <!-- ko if: ($index() < 5) -->
            <tr>
                <td data-bind="text: firstName"></td>
                <td data-bind="text: message"></td>
                <td data-bind="text: $root.converttime(dateCreated)"></td>
            </tr>
            <!-- /ko -->
        </tbody>
    </table>

    
    <script type="text/javascript">
        var viewmodel = {
            people: ko.observableArray([
                { firstName: 'Bert', message: 'Bertington', dateCreated:1540887096175 },
                { firstName: 'Charles', message: 'Charlesforth',dateCreated:1540887096175 },
                { firstName: 'Author', message: 'Dentiste', dateCreated:1540887096175 }
                
            ])
        };
        viewmodel.converttime = function (milliseconds){
        
      
        
        return moment(milliseconds).fromNow();

         
        };
        ko.applyBindings(viewmodel);
        
    </script>

<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

使用设置间隔示例":但是结果很尴尬

With Set Interval Example : but the result is awkward

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>

<table>
        <thead>
            <tr><th>First name</th><th>Last name</th></tr>
        </thead>
        <tbody data-bind="foreach: people">
            <!-- ko if: ($index() < 5) -->
            <tr>
                <td data-bind="text: firstName"></td>
                <td data-bind="text: message"></td>
                <td data-bind="text: $root.converttime(dateCreated)"></td>
            </tr>
            <!-- /ko -->
        </tbody>
    </table>

    
    <script type="text/javascript">
        var viewmodel = {
            people: ko.observableArray([
                { firstName: 'Bert', message: 'Bertington', dateCreated:1540887096175 },
                { firstName: 'Charles', message: 'Charlesforth',dateCreated:1540887096175 },
                { firstName: 'Author', message: 'Dentiste', dateCreated:1540887096175 }
                
            ])
        };
        viewmodel.converttime = function (milliseconds){
        
        return setInterval(function()
        {
        
          return moment(milliseconds).fromNow();

        }, 3000);
      
        
       

         
        };
        ko.applyBindings(viewmodel);
        
    </script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>

推荐答案

这是我经常采用的方法:

Here's the approach I often take:

您可以创建一个时钟类/对象,以暴露包裹在可观察对象中的moment.时钟负责每x毫秒更新此时刻.

You can create a clock class/object that exposes a moment wrapped in an observable. The clock takes care of updating this moment every x ms.

每当在computed中使用此时刻时,您就会拥有一个自动更新的值!

Whenever you use this moment inside a computed, you have an automatically updating value!

const Clock = (freq) => {
  let active = null;
  const now = ko.observable(moment());
  const tick = () => now(moment());
  const loop = () => {
    active = setTimeout(loop, freq);
    tick();
  }
  
  return {
    now: ko.pureComputed(now), // read only
    start: loop,
    stop: () => clearInterval(active)
  }
};


function App() {
  
  const clock = Clock(1000);
  const creationTime = moment();
  const launchTime = moment().add(1, "minute");
  
  this.countDown = ko.pureComputed(
    () => launchTime.from(clock.now())
  );
  
  this.stopwatch = ko.pureComputed(
    () => clock.now().diff(creationTime, "seconds")
  );
  
  clock.start();
}

ko.applyBindings(new App());

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<p>Time till launch: <code data-bind="text: countDown"></code></p>
<p>Time elapsed: <code data-bind="text: stopwatch"></code></p>

以下是您的数据示例:

const Clock = (freq) => {
  let active = null;
  const now = ko.observable(moment());
  const tick = () => now(moment());
  const loop = () => {
    active = setTimeout(loop, freq);
    tick();
  }

  return {
    now: ko.pureComputed(now), // read only
    start: loop,
    stop: () => clearInterval(active)
  }
};

const Message = (clock, msgData) => ({
  firstName: msgData.firstName,
  message: msgData.message,
  timeIndicator: ko.pureComputed(
    () => moment(msgData.dateCreated).from(clock.now())
  )
});

const App = () => {
  const clock = Clock(100);
  clock.start();

  return {
    messages: ko.observableArray(
      getMsgData()
        .map(msgData => Message(clock, msgData))
    )
  }
};

ko.applyBindings(App());

function getMsgData() {
  return [{
      firstName: 'Bert',
      message: 'Bertington',
      dateCreated: Date.now()
    },
    {
      firstName: 'Charles',
      message: 'Charlesforth',
      dateCreated: 1540889093175
    },
    {
      firstName: 'Author',
      message: 'Dentiste',
      dateCreated: 1540887096175
    }

  ]
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<h2>Messages</h2>
<ul data-bind="foreach: messages">
  <li>
    <em data-bind="text: timeIndicator"></em><br/>
    <strong data-bind="text: firstName"></strong>: <span data-bind="text: message"> </span>
  </li>
</ul>

这篇关于我如何不断更新绑定到视图中的数据的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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