Vue.js: v-for 循环中的值未与正确的数组项保持一致
Vue.js: A value in a v-for loop is not staying with the correct array items
我正在尝试创建一个简单的应用程序来为服务部门申请车钥匙。显然代码可以写得更好,但这是我使用 Vue.js 的第三天。在代码的第一个 p 标记中调用的时间函数每分钟更新一次以记录经过的时间。我遇到的问题是当我请求一个新键时,时间函数没有按预期跟随数组项。例如,如果没有其他请求,我提交的第一个请求可以完美运行。但是,当我提交新请求时,从我的第一个请求到第二个请求的经过时间。我确信它可能与粘合在一起的代码有关,但我已经尝试了我能想到的一切。任何帮助将不胜感激。
<template>
<div class="row">
<div class="card col-md-6" v-for="(key, index) in keys" :key="index">
<div class="card-body">
<h5 class="card-title">Service Tag: {{ key.service_tag }}</h5>
<p class="card-text"> {{time}} {{key.reqTimestamp}}min</p>
<p class="invisible">{{ start(key.reqTimestamp) }}</p>
<p class="card-text">Associates Name: {{key.requestor_name}}</p>
<p class="card-text">Model: {{key.model}}</p>
<p class="card-text">Color: {{key.color}}</p>
<p class="card-text">Year: {{key.year}}</p>
<p class="card-text">Comments: {{key.comments}}</p>
<p class="card-text">Valet: {{key.valet}}</p>
<input class="form-control" v-model="key.valet" placeholder="Name of the person getting the car...">
<button
@click="claimedKey(key.id, key.valet)"
type="submit"
class="btn btn-primary"
>Claim</button>
<button v-if="key.valet !== 'Unclaimed'"
@click="unclaimedKey(key.id, key.valet)"
type="submit"
class="btn btn-primary"
>Unclaim</button>
<button class="btn btn-success" @click="complete(key.id)">Complete</button>
</div>
</div>
<!-- END OF CARD -->
<!-- START OF FORM -->
<div class="row justify-content-md-center request">
<div class="col-md-auto">
<h1 class="display-4">Operation Tiger Teeth</h1>
<form class="form-inline" @submit="newKey(service_tag, requestor_name, comments, model, year, color, valet, reqTimestamp)">
<div class="form-group col-md-6">
<label for="service_tag">Service Tag: </label>
<input class="form-control form-control-lg" v-model="service_tag" placeholder="ex: TB1234">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Associates Name: </label>
<!-- <input class="form-control form-control-lg" v-model="requestor_name" placeholder="Your name goes here..."> -->
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select v-model="requestor_name" class="form-control" id="requestor_name">
<option>James Shiflett</option>
<option>Austin Hughes</option>
</select>
</div>
</div>
<div class="form-group col-md-6">
<label for="service_tag">Model: </label>
<input class="form-control form-control-lg" v-model="model" placeholder="What is the model of the vehicle?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Color: </label>
<input class="form-control form-control-lg" v-model="color" placeholder="What is the color of the vehicle?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Year: </label>
<input class="form-control form-control-lg" v-model="year" placeholder="What year is the car?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Comments: </label>
<input class="form-control form-control-lg" v-model="comments" placeholder="Place any additional comments here...">
</div>
<div class="form-group col-md-6 invisible">
<label for="service_tag">Valet: </label>
<input v-model="valet">
</div>
<div class="form-group col-md-6 invisible">
<label for="service_tag">Timestamp: </label>
<input v-model="reqTimestamp">
</div>
<div class="col-md-12">
<button class="btn btn-outline-primary" type="submit">Request A Key</button>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
import { db } from "../main";
import { setInterval } from 'timers';
export default {
name: "HelloWorld",
data() {
return {
keys: [],
reqTimestamp: this.newDate(),
service_tag: "",
requestor_name: "",
comments: "",
color: "",
model: "",
year: "",
inputValet: true,
valet: "Unclaimed",
state: "started",
startTime: '',
currentTime: Date.now(),
interval: null,
};
},
firestore() {
return {
keys: db.collection("keyRequests").where("completion", "==", "Incomplete")
};
},
methods: {
newKey(service_tag, requestor_name, comments, model, year, color, valet, reqTimestamp, completion) {
// <-- and here
db.collection("keyRequests").add({
service_tag,
requestor_name,
comments,
color,
model,
year,
valet,
reqTimestamp,
completion: "Incomplete",
});
this.service_tag = "";
this.requestor_name = "";
this.comments = "";
this.color = "";
this.model = "";
this.year = "";
this.reqTimestamp = this.newDate()
},
complete(id) {
db.collection("keyRequests").doc(id).update({
completion: "Complete"
})
},
// deleteKey(id) {
// db.collection("keyRequests")
// .doc(id)
// .delete();
claimedKey(id, valet) {
console.log(id);
this.inputValet = false
db.collection("keyRequests").doc(id).update({
valet: valet,
claimTimestamp: new Date()
})
},
moment: function () {
return moment();
},
newDate () {
var today = new Date()
return today
},
updateCurrentTime: function() {
if (this.$data.state == "started") {
this.currentTime = Date.now();
}
},
start(timestamp) {
return this.startTime = timestamp.seconds * 1000
}
},
mounted: function () {
this.interval = setInterval(this.updateCurrentTime, 1000);
},
destroyed: function() {
clearInterval(this.interval)
},
computed: {
time: function() {
return Math.floor((this.currentTime - this.startTime) /60000);
}
}
}
</script>
理想情况下,我正在寻找跟进每个请求的时间流逝。
所以模板中的问题行是:
<p class="card-text"> {{time}} {{key.reqTimestamp}}min</p>
<p class="invisible">{{ start(key.reqTimestamp) }}</p>
对start
的调用有side-effects,这是渲染组件的主要no-no。在这种情况下,它会更改 startTime
的值,进而导致 time
发生更改。我有点惊讶这没有触发无限渲染递归警告...
相反,我们应该只使用当前迭代项目的相关数据,您称之为 key
。我会介绍一种计算经过时间的方法 key
:
methods: {
elapsedTime (key) {
const timestamp = key.reqTimestamp;
const startTime = timestamp.seconds * 1000;
return Math.floor((this.currentTime - startTime) / 60000);
}
}
您会注意到这结合了函数 start
和 time
的各个方面。重要的是它不会修改 this
.
上的任何内容
然后您可以在您的模板中调用它:
<p class="card-text"> {{elapsedTime(key)}} {{key.reqTimestamp}}min</p>
我正在尝试创建一个简单的应用程序来为服务部门申请车钥匙。显然代码可以写得更好,但这是我使用 Vue.js 的第三天。在代码的第一个 p 标记中调用的时间函数每分钟更新一次以记录经过的时间。我遇到的问题是当我请求一个新键时,时间函数没有按预期跟随数组项。例如,如果没有其他请求,我提交的第一个请求可以完美运行。但是,当我提交新请求时,从我的第一个请求到第二个请求的经过时间。我确信它可能与粘合在一起的代码有关,但我已经尝试了我能想到的一切。任何帮助将不胜感激。
<template>
<div class="row">
<div class="card col-md-6" v-for="(key, index) in keys" :key="index">
<div class="card-body">
<h5 class="card-title">Service Tag: {{ key.service_tag }}</h5>
<p class="card-text"> {{time}} {{key.reqTimestamp}}min</p>
<p class="invisible">{{ start(key.reqTimestamp) }}</p>
<p class="card-text">Associates Name: {{key.requestor_name}}</p>
<p class="card-text">Model: {{key.model}}</p>
<p class="card-text">Color: {{key.color}}</p>
<p class="card-text">Year: {{key.year}}</p>
<p class="card-text">Comments: {{key.comments}}</p>
<p class="card-text">Valet: {{key.valet}}</p>
<input class="form-control" v-model="key.valet" placeholder="Name of the person getting the car...">
<button
@click="claimedKey(key.id, key.valet)"
type="submit"
class="btn btn-primary"
>Claim</button>
<button v-if="key.valet !== 'Unclaimed'"
@click="unclaimedKey(key.id, key.valet)"
type="submit"
class="btn btn-primary"
>Unclaim</button>
<button class="btn btn-success" @click="complete(key.id)">Complete</button>
</div>
</div>
<!-- END OF CARD -->
<!-- START OF FORM -->
<div class="row justify-content-md-center request">
<div class="col-md-auto">
<h1 class="display-4">Operation Tiger Teeth</h1>
<form class="form-inline" @submit="newKey(service_tag, requestor_name, comments, model, year, color, valet, reqTimestamp)">
<div class="form-group col-md-6">
<label for="service_tag">Service Tag: </label>
<input class="form-control form-control-lg" v-model="service_tag" placeholder="ex: TB1234">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Associates Name: </label>
<!-- <input class="form-control form-control-lg" v-model="requestor_name" placeholder="Your name goes here..."> -->
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select v-model="requestor_name" class="form-control" id="requestor_name">
<option>James Shiflett</option>
<option>Austin Hughes</option>
</select>
</div>
</div>
<div class="form-group col-md-6">
<label for="service_tag">Model: </label>
<input class="form-control form-control-lg" v-model="model" placeholder="What is the model of the vehicle?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Color: </label>
<input class="form-control form-control-lg" v-model="color" placeholder="What is the color of the vehicle?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Year: </label>
<input class="form-control form-control-lg" v-model="year" placeholder="What year is the car?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Comments: </label>
<input class="form-control form-control-lg" v-model="comments" placeholder="Place any additional comments here...">
</div>
<div class="form-group col-md-6 invisible">
<label for="service_tag">Valet: </label>
<input v-model="valet">
</div>
<div class="form-group col-md-6 invisible">
<label for="service_tag">Timestamp: </label>
<input v-model="reqTimestamp">
</div>
<div class="col-md-12">
<button class="btn btn-outline-primary" type="submit">Request A Key</button>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
import { db } from "../main";
import { setInterval } from 'timers';
export default {
name: "HelloWorld",
data() {
return {
keys: [],
reqTimestamp: this.newDate(),
service_tag: "",
requestor_name: "",
comments: "",
color: "",
model: "",
year: "",
inputValet: true,
valet: "Unclaimed",
state: "started",
startTime: '',
currentTime: Date.now(),
interval: null,
};
},
firestore() {
return {
keys: db.collection("keyRequests").where("completion", "==", "Incomplete")
};
},
methods: {
newKey(service_tag, requestor_name, comments, model, year, color, valet, reqTimestamp, completion) {
// <-- and here
db.collection("keyRequests").add({
service_tag,
requestor_name,
comments,
color,
model,
year,
valet,
reqTimestamp,
completion: "Incomplete",
});
this.service_tag = "";
this.requestor_name = "";
this.comments = "";
this.color = "";
this.model = "";
this.year = "";
this.reqTimestamp = this.newDate()
},
complete(id) {
db.collection("keyRequests").doc(id).update({
completion: "Complete"
})
},
// deleteKey(id) {
// db.collection("keyRequests")
// .doc(id)
// .delete();
claimedKey(id, valet) {
console.log(id);
this.inputValet = false
db.collection("keyRequests").doc(id).update({
valet: valet,
claimTimestamp: new Date()
})
},
moment: function () {
return moment();
},
newDate () {
var today = new Date()
return today
},
updateCurrentTime: function() {
if (this.$data.state == "started") {
this.currentTime = Date.now();
}
},
start(timestamp) {
return this.startTime = timestamp.seconds * 1000
}
},
mounted: function () {
this.interval = setInterval(this.updateCurrentTime, 1000);
},
destroyed: function() {
clearInterval(this.interval)
},
computed: {
time: function() {
return Math.floor((this.currentTime - this.startTime) /60000);
}
}
}
</script>
理想情况下,我正在寻找跟进每个请求的时间流逝。
所以模板中的问题行是:
<p class="card-text"> {{time}} {{key.reqTimestamp}}min</p>
<p class="invisible">{{ start(key.reqTimestamp) }}</p>
对start
的调用有side-effects,这是渲染组件的主要no-no。在这种情况下,它会更改 startTime
的值,进而导致 time
发生更改。我有点惊讶这没有触发无限渲染递归警告...
相反,我们应该只使用当前迭代项目的相关数据,您称之为 key
。我会介绍一种计算经过时间的方法 key
:
methods: {
elapsedTime (key) {
const timestamp = key.reqTimestamp;
const startTime = timestamp.seconds * 1000;
return Math.floor((this.currentTime - startTime) / 60000);
}
}
您会注意到这结合了函数 start
和 time
的各个方面。重要的是它不会修改 this
.
然后您可以在您的模板中调用它:
<p class="card-text"> {{elapsedTime(key)}} {{key.reqTimestamp}}min</p>