Реактивность компонентов в Vue
С компонентами можно работать реактивно, давайте разберемся на примерах:
Реактивное удаление компонентов
Давайте научимся реактивно удалять дочерние компоненты из списка. Сделаем для этого в каждом дочернем компоненте специальную кнопку. По нажатию на эту кнопку будет испускаться событие и в родительском компоненте будет удаляться заданный дочерний компонент по его id
.
Пусть в родительском компоненте дан следующий массив объектов:
App.vuedata()
{
return {
users: [
{
id: 1,
name: 'name1',
surn: 'surn1'
},
{
id: 2,
name: 'name2',
surn: 'surn2'
},
{
id: 3,
name: 'name3',
surn: 'surn3'
},
],
}
}
Напишем в родительском компоненте метод удаления юзера по его id
:
App.vuemethods: {
remove(id)
{
this.users = this.users.filter((user) => {
return user.id !== id;
})
}
}
Создадим компоненты в цикле, передав им параметром имя, фамилию, id
и метод для удаления:
App.vue<template>
<User
v-for ="user in users"
:id ="user.id"
:name ="user.name"
:surn ="user.surn"
@remove ="remove"
:key ="user.id"
/>
</template>
Пропишем входящие данные в настройке props
и испускаемое событие в настройке emits
:
components/User.vueprops: {
id: Number,
name: String,
surn: String,
},
emits: ['remove'],
Выведем в представлении компонента имя и фамилию юзера:
components/User.vue<template>
{{ name }}
{{ surn }}
</template>
А теперь сделаем кнопку, по нажатию на которую будет испускаться событие для удаления. Параметром этого события будет передаваться id
компонента. Родительский компонент при получении события удалит данного юзера из массива объектов и он реактивно исчезнет из списка юзеров:
components/User.vue<template>
{{ name }}
{{ surn }}
<button @click="$emit('remove', id)">
remove
</button>
</template>
Готовый код
App.vue<script>
import User from './components/User.vue'
export default {
data()
{
return {
users: [
{
id: 1,
name: 'name1',
surn: 'surn1'
},
{
id: 2,
name: 'name2',
surn: 'surn2'
},
{
id: 3,
name: 'name3',
surn: 'surn3'
},
],
}
},
methods: {
remove(id)
{
this.users = this.users.filter((user) => {
return user.id !== id;
})
}
},
components: {
User
}
}
</script>
<template>
<User
v-for ="user in users"
:id ="user.id"
:name ="user.name"
:surn ="user.surn"
@remove ="remove"
:key ="user.id"
/>
</template>
components/User.vue<script>
export default {
props: {
id: Number,
name: String,
surn: String,
},
emits: ['remove'],
}
</script>
<template>
{{ name }}
{{ surn }}
<button @click="$emit('remove', id)">
remove
</button>
</template>
Реактивное редактирование данных компонента
Давайте теперь реализуем редактирование данных наших дочерних компонентов. Для начала в родительском компоненте сделаем метод изменения юзера по его id
:
App.vuemethods: {
change(id, name, surn)
{
this.users = this.users.map((user) => {
if (user.id === id) {
user.name = name;
user.surn = surn;
}
return user;
});
}
}
Создадим компоненты в цикле, передав им параметром имя, фамилию, id
и метод для изменения:
App.vue<template>
<User
v-for ="user in users"
:id ="user.id"
:name ="user.name"
:surn ="user.surn"
:key ="user.id"
@change="change"
/>
</template>
Пропишем испускаемое событие в настройке emits
дочернего компонента:
components/User.vueprops: {
id: Number,
name: String,
surn: String,
},
emits: ['change'],
Теперь в дочернем компоненте сделаем свойство, которое будет задавать режим компонента, показ или редактирование:
components/User.vuedata()
{
return {
isEdit: false,
}
}
Сделаем также свойства для поддержки работы инпутов для редактирования:
components/User.vuedata()
{
return {
isEdit: false,
newName: '',
newSurn: '',
}
}
Сделаем так, чтобы начальные значения этих свойств брались из пропсов:
components/User.vuedata()
{
return {
isEdit: false,
newName: this.name,
newSurn: this.surn,
}
}
Сделаем метод, который будет запускать режим редактирования:
components/User.vuemethods: {
edit()
{
this.isEdit = true;
}
}
Сделаем метод, который будет сохранять отредактированные данные, отключая при этом режим редактирования:
components/User.vuemethods: {
save()
{
this.isEdit = false;
this.$emit('change', this.id, this.newName, this.newSurn);
}
}
Сделаем представление дочернего компонента:
components/User.vue<template>
<template v-if="!isEdit">
{{ name }}
{{ surn }}
<button @click="edit">
edit
</button>
</template>
<template v-else>
<input v-model="newName">
<input v-model="newSurn">
<button @click="save">
save
</button>
</template>
</template>
Готовый код
App.vue<script>
import User from './components/User.vue'
export default {
data()
{
return {
users: [
{
id: 1,
name: 'name1',
surn: 'surn1'
},
{
id: 2,
name: 'name2',
surn: 'surn2'
},
{
id: 3,
name: 'name3',
surn: 'surn3'
},
],
}
},
methods: {
change(id, name, surn)
{
this.users = this.users.map((user) => {
if (user.id === id) {
user.name = name;
user.surn = surn;
}
return user;
});
}
},
components: {
User
}
}
</script>
<template>
<User
v-for ="user in users"
:id ="user.id"
:name ="user.name"
:surn ="user.surn"
:key ="user.id"
@change="change"
/>
</template>
components/User.vue<script>
export default {
data()
{
return {
isEdit: false,
newName: this.name,
newSurn: this.surn,
}
},
props: {
id: Number,
name: String,
surn: String,
},
emits: ['change'],
methods: {
edit()
{
this.isEdit = true;
},
save()
{
this.isEdit = false;
this.$emit('change', this.id, this.newName, this.newSurn);
}
}
}
</script>
<template>
<template v-if="!isEdit">
{{ name }}
{{ surn }}
<button @click="edit">
edit
</button>
</template>
<template v-else>
<input v-model="newName">
<input v-model="newSurn">
<button @click="save">
save
</button>
</template>
</template>