Obe*_*lve 3 javascript momentjs vue.js vuex google-cloud-firestore
我正在构建一个论坛应用程序,并使用 v-for,我想显示所有评论何时以 momentjs 相对时间发布,问题是渲染永远不会从“几秒钟前”开始改变。在这个问题中,响应显示可以实现我想要的,基本上在创建组件时使用间隔:
created() {
setInterval(() => {
this.messages = this.messages.map(m => {
m.ago = moment(m.time).fromNow();
return m;
});
}, 1000);
}
Run Code Online (Sandbox Code Playgroud)
但由于我直接从 vuex 获取数据,我不知道如何将解决方案与我的代码集成。
这是我的 store.js:
export default new Vuex.Store({
state: {
comments: [],
},
mutations: {
loadComments: (state, comments) => {
state.comments = comments;
},
},
actions: {
loadComments: async (context) => {
let snapshot = await db
.collection("comments")
.orderBy("timestamp")
.get();
const comments = [];
snapshot.forEach((doc) => {
let appData = doc.data();
appData.id = doc.id;
appData.timestamp = moment()
.startOf(doc.data().timestamp)
.fromNow();
comments.push(appData);
});
context.commit("loadComments", comments);
},
},
});
Run Code Online (Sandbox Code Playgroud)
这是我的脚本:
import { db, fb } from "../firebase";
import { mapState } from "vuex";
export default {
name: "Forum",
data() {
return {
commentText: null,
};
},
mounted() {
this.getComment();
},
methods: {
getComment() {
this.$store.dispatch("loadComments");
},
async sendComment() {
await db
.collection("comments")
.add({
content: this.commentText,
author: this.name,
timestamp: Date.now()
});
this.commentText = null;
this.getComment();
}
},
created() {
let user = fb.auth().currentUser;
this.name = user.displayName;
},
computed: mapState(["comments"])
};
Run Code Online (Sandbox Code Playgroud)
最好将所有这些逻辑抽象为一个用于显示日期的组件,而不是需要跨代码边界触发更新。尽可能减少所有日期呈现代码,以便随时轻松更改日期呈现逻辑。
日期本身是数据,但该日期的视觉表示形式不是。所以我不会将格式化日期存储在 Vuex 存储中。
创建一个<from-now>
以 adate
作为 prop 的组件,并使用 moment 的 渲染日期fromNow
。它还负责定期(每分钟)更新自身。由于它是一个组件,因此您可以将完整日期显示为工具提示,以便用户将鼠标悬停在其上时可以知道确切的时间。
const components = new Set();
// Force update every component at the same time periodically
setInterval(() => {
for (const comp of components) {
comp.$forceUpdate();
}
}, 60 * 1000);
Vue.component('FromNow', {
template: '<span :title="title">{{ text }}</span>',
props: ['date'],
created() {
components.add(this);
},
destroyed() {
components.remove(this);
},
computed: {
text() {
return moment(this.date).fromNow();
},
title() {
return moment(this.date).format('dddd, MMMM Do YYYY, h:mm:ss a');
},
},
});
new Vue({
el: '#app',
data: {
// Test various seconds ago from now
dates: [5, 60, 60 * 5, 60 * 60].map(sec => moment().subtract(sec, 'seconds')),
},
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<div id="app">
<p v-for="date of dates">
<from-now :date="date"></from-now>
</p>
</div>
Run Code Online (Sandbox Code Playgroud)
为了简单起见,<from-now>
仅显示相对日期。我使用与此类似的组件,但更通用。它需要一个format
道具,允许我选择如何显示日期(可以是相对时间,也可以是 moment 接受的特定日期格式)。
归档时间: |
|
查看次数: |
1692 次 |
最近记录: |