В настоящее время я работаю над приложением todolist.
Что я хочу сделать, так это добавить функцию редактирования в это приложение, как показано на изображении ниже.
Прежде всего, я попытался передать только this.item.name из дочернего компонента (listItem.vue) в родительский компонент (addItemForm.vue), чтобы он отображался в поле ввода при нажатии на значок редактирования, но это не так. работай.
Если кто-нибудь может помочь мне понять, что я пытаюсь сделать, пожалуйста, дайте мне знать.
вот vue-файл.
app.vue
<template>
<div class = "todoListContainer">
<div class = "heading">
<h2 id = "title">TodoList</h2>
<add-item-form v-on:reloadlist = "getList()" />
</div>
<list-view :items = "items" v-on:reloadlist = "getList()" />
</div>
</template>
<script>
import addItemForm from "./addItemForm.vue";
import listView from "./listView.vue";
export default {
components: {
addItemForm,
listView,
},
data: function () {
return {
items: [],
};
},
methods: {
getList() {
axios
.get("api/items")
.then((response) => {
this.items = response.data;
console.info(this.items);
})
.catch((error) => {
console.info(error);
});
},
},
created() {
this.getList();
console.info("create success!");
},
};
</script>
<style scoped>
.todoListContainer {
width: 350px;
margin: auto;
}
.heading {
background: #e6e6e6;
padding: 10px;
}
#title {
text-align: center;
}
</style>
addItemForm.vue
<template>
<div class = "addItem">
<input type = "text" v-model = "item.name" />
<font-awesome-icon
icon = "plus-square"
@click = "addItem()"
:class = "[item.name ? 'active' : 'inactive', 'plus']"
/>
</div>
</template>
<script>
export default {
data: function () {
return {
item: {
name: "",
},
};
},
methods: {
addItem() {
if (this.item.name == "") {
return;
}
axios
.post("api/item/store", {
item: this.item,
})
.then((response) => {
if (response.status == 201) {
this.item.name = "";
this.$emit("reloadlist");
}
})
.catch((error) => {
console.info(error);
});
},
},
};
</script>
<style scoped>
.addItem {
display: flex;
justify-content: center;
align-items: center;
}
input {
background: #f7f7f7;
border: 0px;
outline: none;
padding: 5px;
margin-right: 10px;
width: 100%;
}
.plus {
font-size: 20px;
}
.active {
color: #00ce25;
}
.inactive {
color: #999999;
}
</style>
listView.vue
<template>
<div>
<div v-for = "(item, index) in items" :key = "index">
<list-item
:item = "item"
class = "item"
v-on:itemchanged = "$emit('reloadlist')"
/>
</div>
</div>
</template>
<script>
import listItem from "./listItem.vue";
export default {
props: ["items"],
components: {
listItem,
},
};
</script>
<style scoped>
.item {
background: #e6e6e6;
padding: 5px;
margin-top: 5px;
}
</style>
listItem.vue
<template>
<div class = "item">
<input type = "checkbox" @change = "updateCheck()" v-model = "item.completed" />
<span :class = "[item.completed ? 'completed' : '', 'itemText']">{{
item.name
}}</span>
<button @click = "removeItem()" class = "trashcan">
<font-awesome-icon icon = "trash" />
</button>
<button @click = "editItem" class = "pencil">
<font-awesome-icon icon = "pencil" />
</button>
</div>
</template>
<script>
export default {
props: ["item"],
methods: {
updateCheck() {
axios
.put("api/item/" + this.item.id, {
item: this.item,
})
.then((response) => {
if (response.status == 200) {
this.$emit("itemchanged");
}
})
.catch((error) => {
console.info(error);
});
},
removeItem() {
axios
.delete("api/item/" + this.item.id)
.then((response) => {
if (response.status == 200) {
this.$emit("itemchanged");
}
})
.catch((error) => {
console.info(error);
});
},
editItem() {
const text = this.item .name;
this.$emit('custom-click', text);
}
},
};
</script>
<style scoped>
.completed {
text-decoration: line-through;
color: #999999;
}
.itemText {
width: 100%;
margin-left: 20px;
}
.item {
display: flex;
justify-content: center;
align-items: center;
}
.trashcan {
background: #e6e6e6;
border: none;
color: #ff0000;
outline: none;
}
.pencil {
background: #e6e6e6;
border: none;
color: #1df548;
outline: none;
}
</style>
items_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('completed')->default(false);
$table->timestamp('completed_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
Прежде всего, я попытался передать только this.item.name из дочернего компонента (listItem.vue) в родительский компонент (addItemForm.vue), чтобы он отображался в поле ввода при нажатии на значок редактирования, но это не так. работай.
Поэтому я хочу, чтобы целевой текст отображался в поле ввода при первом нажатии на символ редактирования.
Постскриптум
Постскриптум2
Я отладил его, поместив точку останова в соответствующую точку в инструментах разработчика Chrome.
Я подтвердил, что значение передается @custom-click="$emit('custom-click', $event)" в listView.vue, но, похоже, оно не достигает функции редактирования.
Кроме того, я получаю предупреждение об ошибке, как показано на изображении.
Постскриптум3
Инструменты разработчика Vue.js
Вы испускаете «пользовательский щелчок» из listItem, это хорошо. Далее нужно прослушать событие в родительском элементе (listView) и повторно передать его следующему родителю, app.vue. Как только app.vue получит элемент, вам нужно передать его обратно в качестве реквизита вашему компоненту AddItemForm.vue и установить его как v-модель <input>
.
Это в основном то, что вам нужно добавить к каждому компоненту:
listView.vue (повторная передача)
<list-item
:item = "item"
class = "item"
v-on:itemchanged = "$emit('reloadlist')"
@custom-click = "$emit('custom-click', $event)"
/>
App.vue (прослушайте излучение, найдите соответствующий элемент в this.items
, отправьте его как реквизит в addItemForm)
<div class = "heading">
<h2 id = "title">TodoList</h2>
<add-item-form v-on:reloadlist = "getList()" :editItem = "editItem" />
</div>
<list-view :items = "items" v-on:reloadlist = "getList()" @custom-click = "edit" />
data: function () {
editItem: null
},
methods: {
edit(item) {
this.editItem = this.items.find(i => i.name === item);
}
}
AddItemForm.vue (установите v-модель с помощью реквизита)
props: {
editItem: {
type: Object,
default() {
return null;
}
}
},
watch: {
editItem(newItem) {
this.item = newItem;
}
}
Спасибо за ваш комментарий. Я отразил то, что вы описали, но когда я нажал на символ редактирования, значение не появилось в поле ввода. Я забыл упомянуть, что я использую vue3, это метод записи, который не работает с vue3? Сделанные мной изменения я прикрепил в постскриптуме.
Поскольку я не могу запустить ваш код для вас, можете ли вы отладить и, возможно, сузить область, в которой может быть проблема? Используйте консольный журнал и/или инструменты разработчика и убедитесь, что 1) первая эмиссия работает, 2) вторая эмиссия работает, 3) правильный элемент находится в app.vue, 4) реквизит передается в addItemForm и установите v-модель. Пожалуйста, выясните, какой шаг терпит неудачу.
Я добавил отладочную информацию. Кстати, когда я отлаживаю vuejs, я обычно делаю это с помощью инструментов разработчика Chrome, какой самый распространенный способ отладки vuejs?
@shozo с помощью инструментов разработки VueJS.
@kissu Спасибо за ваш комментарий. Как я уже добавил, у меня все еще есть расширение Chrome Vue.js devtools, но это расширение не выполняет отладку, как обычные инструменты разработчика Chrome, верно? Я не знаю, как использовать это расширение.
@shozo у вас есть в режиме реального времени, не нужно «останавливаться». Но оба могут хорошо работать вместе.
@kissu Я также узнаю, как использовать инструменты. Приятно знать, что все используют этот инструмент.
@yoduh Я сделал очень глупую ошибку. Я написал функцию редактирования в функции создания, хотя должен был написать ее внутри метода... Я подтвердил, что щелкнутое содержимое успешно отражается в поле ввода. Затем я хотел бы добавить процесс, чтобы сделать отметку плюса меткой редактирования и применить отредактированный контент. Если будут вопросы, спрошу еще раз. Большое спасибо.
can help me understand what I am trying to do
+sharing 400 lines of code
не очень хорошее совпадение. Что вы видите в своих инструментах разработки Vue?