我要创建这样的收件箱邮件下拉列表
是通过JS时刻显示消息的相对时间。下面的代码片段显示了最终结果。但是此代码的问题在于,以毫秒为单位的时间不会按间隔更新,以显示毫秒与当前日期的相对时间。所以我尝试在方法内部使用设置间隔。
未设置时间间隔示例(可以正常工作,但是最终转换时间在第一次更改后不会改变)
graphql(RaceResultsQuery, {
props: ({ ownProps, data }) => ({
race_results: _.get(data, 'me.my_race_results', []),
}),
}),
<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>
<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>
答案 0 :(得分:1)
这是我经常采用的方法:
您可以创建一个时钟类/对象,以暴露包裹在可观察对象中的moment
。时钟负责每x
毫秒更新此时刻。
只要您在computed
中使用此刻,就会拥有一个自动更新的值!
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>