因此,我面临的问题是我有一个模板,可从Realtime Firebase数据库获取数据,同时用户可以通过一个input
元素导入更多数据。我正在使用Vue.js,我需要数据相互绑定。
这是我的模板:
<template>
<ul>
<li>
<input type="text" v-model="email" v-on:keyup.enter="addData()"/>
<img @click="addData()" src="@/assets/Plus.png" />
</li>
</ul>
<ul>
<li v-for="(item, key) in emails" :key="key">
<div>
<p>{{ item.data }}</p>
<img @click="deleteDataByKey(key)" src="@/assets/Delete.png" />
</div>
<div class="first">
<input type="text" v-model="comment[key]" v-on:keyup.enter="addComment(key, comment[key])"/>
<img @click="addComment(key, comment[key])" src="@/assets/Plus.png" />
</div>
<div class="second">
<p>{{ comment[key] }}</p>
<img @click="deleteCommentByKey(key)" src="@/assets/Delete.png" />
</div>
</li>
</ul>
</template>
现在发生的是,我想显示<div class="first">
什么时候没有评论,什么时候有评论,<div class="second">
应该在隐藏第一个评论的同时显示。
我尝试使用,v-if="comment[key]"
但它将立即切换div。我也尝试了v-model.lazy
似乎正在工作,但没有调用更新数据库的方法。我尝试在该方法中使用纯JS来更改HTML,但它似乎也不起作用。
这些是我的方法和数据:
data() {
return {
emailList: [],
email: "",
comment: []
};
},
addData() {
db.ref("emailItems").push({
data: data
});
this.email = "";
this.fetchData();
},
deleteDataByKey(key) {
db.ref("emailItems"+key).remove();
this.fetchData();
},
addComment(key, comment) {
db.ref(`emailItems/${key}/comment`).set(comment);
},
deleteCommentByKey(key){
db.ref("comment/"+key).remove();
this.fetchData();
},
fetchData() {
db.ref("emailItems")
.once("value")
.then(snapshot => {
this.emailList = snapshot.val().emailItems;
});
}
db结构看起来像这样
任何帮助将不胜感激...
我认为你应该更多地基于Vue的最大功能(即 React 性和组件)构建。
进一步分解逻辑,直到找到只做一件事的元素-这些元素可以成为你的组件。然后从这些原子组件构建业务逻辑。
Vue.component('NewEmail', {
data() {
return {
email: null,
}
},
methods: {
handleKeyup() {
this.$emit("add-email", {
email: this.email,
comment: null
})
this.email = null
}
},
template: `
<div>
<label>
NEW EMAIL: <input
type="email"
placeholder="Type in an email"
v-model="email"
@keyup.enter="handleKeyup"
/>
</label>
</div>
`
})
Vue.component('SingleEmailRow', {
props: {
email: {
type: Object,
default: null,
}
},
methods: {
handleDeleteClick() {
this.$emit('remove-email', this.email)
},
},
template: `
<li
class="d-flex"
>
<div>
{{ email.email }}
</div>
<div>
<button
@click="handleDeleteClick"
>
X
</button>
</div>
<component
:is="email.comment ? 'HasEmailComment' : 'NoEmailComment'"
:email="email"
v-on="$listeners"
></component>
</li>
`
})
Vue.component('HasEmailComment', {
props: {
email: {
type: Object,
required: true
}
},
methods: {
handleUpdateComment() {
this.$emit('update:comment', { ...this.email,
comment: null
})
}
},
template: `
<div
class="d-flex"
>
<div>
{{ email.comment }}
</div>
<button
title="Remove comment"
@click="handleUpdateComment"
>
-
</button>
</div>
`
})
Vue.component('NoEmailComment', {
props: {
email: {
type: Object,
required: true
}
},
data() {
return {
comment: null,
}
},
methods: {
handleUpdateComment() {
this.$emit('update:comment', { ...this.email,
comment: this.comment
})
}
},
template: `
<div
class="d-flex"
>
<div>
<input
v-model="comment"
type="text"
placeholder="Write a comment"
/>
</div>
<button
title="Add comment"
@click="handleUpdateComment"
>
+
</button>
</div>
`
})
new Vue({
el: "#app",
data() {
return {
emailList: [],
}
},
methods: {
handleAddEmail(newEmail) {
if (!this.emailList.find(({
email
}) => email === newEmail.email)) {
this.emailList.push(newEmail)
}
},
handleRemoveEmail(toRemove) {
this.emailList = this.emailList.filter(({
email
}) => {
return email !== toRemove.email
})
},
handleUpdateComment(newEmail) {
this.emailList = this.emailList.map(email => {
if (email.email === newEmail.email) {
return newEmail
} else {
return email
}
})
}
}
})
.d-flex {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<new-email @add-email="handleAddEmail"></new-email>
<ul v-for="(email, i) in emailList" :key="i">
<single-email-row :email="email" @remove-email="handleRemoveEmail" @update:comment="handleUpdateComment"></single-email-row>
</ul>
</div>
好的,可以将comment
处理SingleEmailRow
放入其单独的组件中(根据我的上述想法)。
上面的摘录中的要点是:
emailList
在根组件中)会props
根据需要向下传递,而所有其他组件和函数都只通过以下方式操纵THAT列表events
( React 性非常好!)props
。(好吧,他们有一些内部状态,但是嘿-这只是一个片段!:))NewEmail
:向中央添加一个项目 emailList
SingleEmailRow
:管理一个电子邮件项目中的数据我希望这可以帮助你找到解决问题的方法。
我不得不更新该代码段,因为我对此不满意。
修改内容:
HasEmailComment
,NoEmailComment
SingleEmailRow
了两个新组件现在,所有组件仅需完成一项任务。
您的解决方案正在运行,并且您提供的信息对我有很大帮助,因此,我接受它作为正确的答案。如果可以的话,我一直在寻找一种更快速的解决方案。现在我需要重新排列整个结构..
仅供参考:我用另一种方式修复了它。基本上,我将数据从div中的db渲染出来,而不是直接将数据与输入字段绑定在一起。非常感谢您的努力@gergely
@MakisMilas感谢您的回复!我很高兴能为您提供帮助,并且您找到了解决方案!