Vue momentjs 타임스탬프에서 실시간으로 상대 시간 업데이트
포럼 앱을 만들고 있는데, v-for와 함께 모든 댓글이 모멘트j로 언제 올라갔는지 보여주고 싶은데 문제는 렌더가 '몇 초 전'에서 절대 바뀌지 않는다는 것이다.이 질문에서 응답은 기본적으로 구성 요소가 생성되는 간격을 사용하여 내가 원하는 것을 달성하는 것으로 나타난다.
created() {
setInterval(() => {
this.messages = this.messages.map(m => {
m.ago = moment(m.time).fromNow();
return m;
});
}, 1000);
}
하지만 그것 때문에 나는 vuex에서 직접 데이터를 가져왔기 때문에 내 코드와 솔루션을 통합하는 방법을 이해하지 못한다.
여긴 내 가게야
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);
},
},
});
그리고 이건 내 대본이야.
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"])
};
이 모든 논리를 하나의 구성 요소로 추상화하여 날짜를 표시하는 것이 가장 좋으며, 그 다음 코드 경계를 넘어 업데이트를 유발할 필요가 있다.언제든지 쉽게 날짜 렌더링 논리를 변경할 수 있도록 모든 날짜 렌더링 코드를 최대한 최소화하십시오.
날짜 자체는 데이터지만, 그 날짜의 시각적 표현은 그렇지 않다.그래서 나는 Vuex 매장에 포맷된 날짜를 저장하지 않을 것이다.
구성 요소 생성<from-now>
어느 정도 시간이 걸리는 것은date
소품으로 그리고 순간의 시간을 이용하여 날짜를 렌더링하다.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')),
},
});
<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>
단순함을 위해서<from-now>
상대적인 날짜만 표시한다.나는 이것과 비슷한 구성요소를 사용하지만 좀 더 범용적이다.그것은 시간이 걸린다.format
날짜를 표시할 방법을 선택할 수 있는 소품(상대 시간일 수 있음 또는 순간이 수락하는 특정 날짜 형식일 수 있음)
다른 작업을 추가하고 매 초마다 작업을 전송하십시오.
mutations: {
loadComments: (state, comments) => {
state.comments = comments;
},
update:(state)=>{
state.comments=state.comments.map(comment=>{
comment.ago= moment()
.startOf(comment.timestamp)
.fromNow();
return comment;
});
}
},
actions: {
updateComments(context){
context.commit('update')
},
loadComments: async (context) => {
....
그리고
created() {
let user = fb.auth().currentUser;
this.name = user.displayName;
setInterval(() => {
this.$store.dispatch("updateComments");
}, 1000);
},
'Programing' 카테고리의 다른 글
TypeScript에서 조합 유형을 사용하여 배열을 입력하시겠습니까? (0) | 2022.03.21 |
---|---|
TypeError: method()는 1개의 위치 인수를 사용하지만 2개가 지정됨 (0) | 2022.03.21 |
Vue.js에서 생성된 이벤트와 마운트된 이벤트 간의 차이 (0) | 2022.03.21 |
외부 요소 클릭 감지 (0) | 2022.03.21 |
두 번째.그러면() 약속은 정의되지 않은 데이터로 호출된다. (0) | 2022.03.21 |