javascript - 如何创建将用户输入发送到另一个组件的 vue 模式
问题描述
我正在尝试创建一个接受用户输入的模式组件,并在保存该信息后显示在另一个组件中。例如,提示用户在模态组件(Modal.vue)中分别输入他们的名字和姓氏。一旦用户保存了该数据(模式上的提交方法),数据就会显示在另一个组件(InputItem.vue)上。
目前,我有一个容纳输入元素的 CreateEvent.vue 组件,一个 modal.vue 组件,它是模式,一个 EventItem.vue 组件,它将在执行 CreateEvent 后显示输入的内容,一个显示的 EventsList.vue 组件用户创建的所有事件,最后是包含 Modal 和 Events 组件的 app.vue。
我已经能够在没有模态组件的情况下成功地让这个 CRUD 功能工作,但是一旦我添加了模态,我就会感到困惑。
如果您能帮助我朝着正确的方向前进,我将不胜感激!
模态的.vue
<template>
<transition name="modal-fade">
<div class="modal-backdrop">
<div
class="modal"
role="dialog"
aria-labelledby="modalTitle"
aria-describedby="modalDescription"
>
<header class="modal-header" id="modalTitle">
<slot name="header">
Create an Event
<button
type="button"
class="btn-close"
@click="close"
aria-label="Close modal"
>
x
</button>
</slot>
</header>
<section class="modal-body" id="modalDescription">
<slot name="body">
<div @keyup.enter="addTodo">
<input
type="text"
class="todo-input"
placeholder="What needs to be done"
v-model="newTodo"
/>
<input
type="text"
placeholder="add an emoji?"
v-model="newEmoji"
/>
</div>
<button @click="doneEdit">Create Event</button>
<button @click="cancelEdit">Cancel</button>
</slot>
</section>
<footer class="modal-footer">
<slot name="footer">
I'm the default footer!
<button
type="button"
class="btn-green"
@click="close"
aria-label="Close modal"
>
Close me!
</button>
</slot>
</footer>
</div>
</div>
</transition>
</template>
<script>
export default {
name: 'modal',
data() {
return {
newTodo: '',
newEmoji: '',
idForTodo: this.todos.length + 1
}
},
methods: {
close() {
this.$emit('close')
},
addTodo() {
if (this.newTodo.trim().length == 0) return
this.todos.push({
id: this.idForTodo,
title: this.newTodo,
emoji: this.newEmoji
})
this.newTodo = ''
this.newEmoji = ''
this.idForTodo++
}
}
}
</script>
创建事件.vue
<template>
<div @keyup.enter="addTodo">
<input
type="text"
class="todo-input"
placeholder="What needs to be done"
v-model="newTodo"
/>
<input type="text" placeholder="add an emoji?" v-model="newEmoji" />
</div>
</template>
<script>
export default {
props: {
todos: {
type: Array
}
},
data() {
return {
newTodo: '',
newEmoji: '',
idForTodo: this.todos.length + 1
}
},
methods: {
addTodo() {
if (this.newTodo.trim().length == 0) return
this.todos.push({
id: this.idForTodo,
title: this.newTodo,
emoji: this.newEmoji
})
this.newTodo = ''
this.newEmoji = ''
this.idForTodo++
}
}
}
</script>
事件项.vue
<template>
<div class="todo-item">
<h3 class="todo-item--left">
<!-- <span v-if="!editing" @click="editTodo" class="todo-item--label">
{{ title }}
{{ emoji }}
</span> -->
<input
class="todo-item--edit"
type="text"
v-model="title"
@click="editTitle"
@blur="doneEdit"
/>
<input
class="todo-item--edit"
type="text"
v-model="emoji"
@click="editEmoji"
@blur="doneEdit"
/>
<!-- <button @click="doneEdit">Update</button>
<button @click="cancelEdit">Cancel</button> -->
</h3>
<button class="remove-item" @click="removeTodo(todo.id)">✘</button>
</div>
</template>
<script>
export default {
name: 'todo-item',
props: {
todo: {
type: Object,
required: true
}
},
data() {
return {
id: this.todo.id,
title: this.todo.title,
emoji: this.todo.emoji,
editing: this.todo.editing,
beforeEditCacheTitle: this.todo.title,
beforeEditCacheEmoji: this.todo.emoji
}
},
methods: {
editTitle() {
this.beforeEditCacheTitle = this.title
this.editing = true
},
editEmoji() {
this.beforeEditCacheEmoji = this.emoji
this.editing = true
},
doneEdit() {
if (this.title.trim() == '') {
this.title = this.beforeEditCacheTitle
}
if (this.emoji.trim() == '') {
this.emoji = this.beforeEditCacheEmoji
}
this.editing = false
this.$emit('finishedEdit', {
id: this.id,
title: this.title,
emoji: this.emoji,
editing: this.editing
})
},
cancelEdit() {
this.title = this.beforeEditCacheTitle
this.emoji = this.beforeEditCacheEmoji
this.editing = false
},
removeTodo(id) {
this.$emit('removedTodo', id)
}
}
}
</script>
事件.vue
<template>
<div>
<transition-group
name="fade"
enter-active-class="animated fadeInUp"
leave-active-class="animated fadeOutDown"
>
<EventItem
v-for="todo in todosFiltered"
:key="todo.id"
:todo="todo"
@removedTodo="removeTodo"
@finishedEdit="finishedEdit"
/>
</transition-group>
</div>
</template>
<script>
import EventItem from '@/components/EventItem'
export default {
components: {
EventItem
},
data() {
return {
filter: 'all',
todos: [
{
id: 1,
title: 'Eat sushi',
emoji: '',
editing: false
},
{
id: 2,
title: 'Take over world',
emoji: '',
editing: false
}
]
}
},
computed: {
todosFiltered() {
if (this.filter == 'all') {
return this.todos
}
}
},
methods: {
removeTodo(id) {
const index = this.todos.findIndex(item => item.id == id)
this.todos.splice(index, 1)
},
finishedEdit(data) {
const index = this.todos.findIndex(item => item.id == data.id)
this.todos.splice(index, 1, data)
}
}
}
</script>
应用程序.vue
<template>
<div id="app" class="container">
<button type="button" class="btn" @click="showModal">
Create Event
</button>
<Modal v-show="isModalVisible" @close="closeModal" />
<Events />
</div>
</template>
<script>
import Events from './components/Events'
import Modal from './components/Modal'
export default {
name: 'App',
components: {
Events,
Modal
},
data() {
return {
isModalVisible: false
}
},
methods: {
showModal() {
this.isModalVisible = true
},
closeModal() {
this.isModalVisible = false
}
}
}
</script>
解决方案
模态组件应该发出值而不是将其推入 todos 数组。当它发出它时,父组件(App.vue)会监听发出的项目。
我会做这样的事情
模态的.vue
<template>
...
// header
<section class="modal-body" id="modalDescription">
<slot name="body">
<div @keyup.enter="addTodo">
...
</div>
<button @click="handleModalSubmit">Create Event</button>
...
//footer
...
</template>
<script>
export default {
...
data() {
...
},
methods: {
...,
handleModalSubmit() {
this.$emit('todos-have-been-submitted', this.todos);
},
addTodo() {
...
this.todos.push({
id: this.idForTodo,
title: this.newTodo,
emoji: this.newEmoji
})
...
}
}
}
</script>
应用程序.vue
<template>
...
<Modal
@todos-have-been-submitted="handleTodoSubmission" //watch the 'todos-have-been-submitted" emission and trigger handleTodoSubmission method when the emission is detected
/>
<Events
:todos="todos" // pass todos as a prop to the Events component
/>
...
</template>
<script>
import Events from './components/Events'
import Modal from './components/Modal'
export default {
name: 'App',
components: {
Events,
Modal
},
data() {
return {
...,
todos: []
}
},
methods: {
...,
handleTodoSubmission(todos) {
this.todos = [...todos];
}
}
}
</script>
推荐阅读
- javascript - TailwindCSS 暗模式在 Nuxt.js 中不起作用
- uwp - UWP:获取 URL Webradio 流的艺术家/标题
- wordpress - 木材:以自定义帖子类型呈现特色图像
- mysql - 使用SQL查找7月份第一次下单的客户
- imagemagick - 如何在不使用任何临时文件的情况下将 Imagemagick 蒙太奇输出和图像属性传递给转换命令?
- javascript - Node接口只是一个概念吗?元素接口和节点接口有什么区别?
- javascript - 在 Vue 中通过 AXIOS 发布请求总是返回 405 和 CORS 错误
- python - 多评分输入 RandomizedSearchCV
- flutter - showDialog 函数没有将父上下文传递给 Flutter 中的子代?是这样构思的吗?
- linux - Bash脚本无限while循环