Взаимодействие между сестринскими компонентами.

Последнее обновление: 03.11.2020

Одной из частых задач при организации компонентов во Vue составляет организация взаимодействия между компонентами, которые находятся на одном уровне, то есть являются сестринскими.

В этом случае взаимодействие происходит через родительский компонент. Например, определим два дочерних компонента, которые взаимодействуют через родительский компонент:

<!DOCTYPE html>
<html>
<head>
<title>Компоненты Vue 3</title>
<meta charset="utf-8" />
</head>
<body>
<div id="app">
	<h2>User</h2>
    <useredit :name="user" @userchange="change"></useredit>
    <userinfo :name="user" @userreset="reset"></userinfo>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
const app = Vue.createApp({
    data(){
		return {
			user:'Tom'
		}  
    },
	methods:{
        change(name){
            this.user = name;
        },
        reset(){
            this.user = 'Tom';
        },
    }
});

app.component('useredit', { 
    props: ["name"],
    template: '<div><input v-model="username" /><button @click="save">Save</button></div>',
	data(){ 
		return { username: this.name }
	},
	watch: { 
      	name(newVal) {
          this.username = newVal;
        }
	},
    methods:{
        save(){
            this.$emit("userchange", this.username);
        }
    }
});
app.component('userinfo', { 
    props: ["name"],
    template: `<div><p>Имя: {{name}}</p><button @click="reset">Reset</button></div>`,
    methods:{
        reset(){
            this.$emit("userreset");
        }
    }
});
app.mount('#app');
</script>
</body>
</html>

Ключевым моментом здесь является то, что данные, которыми манипулируют оба компонента, хранятся как данные все приложения Vue. В данном случае оба дочерних компонента useredit и userinfo принимают от объекта приложения Vue имя пользователя. То есть оба компонента используют те данные, которые определены в объекте приложения Vue. Вместо объекта приложения Vue это мог бы быть другой компонент, который был бы родительским по отношению к userinfo и useredit.

Первый дочерний компонент - useredit получает данные от родителя через свойство name

props: ["name"],

Однако здесь мы сталкиваемся со следующей задачей. Параметр props передает свойства только для чтения, которые мы не можем изменять. Однако в компоненте useredit мы хотим изменять свойство name. Более того передавать измененное значение другому компоненту и при этом отслеживать, не изменил ли другой компонент сам значение свойства name. То есть необходимо передавать во вне изменения и при этом отслеживать, не произошли ли вне компонента изменения со свойством name.

Чтобы свойство name можно было изменять, компонент useredit определяет новое свойство username:

data(){ 
		return { username: this.name }
	},

Это свойство username привязанно двусторонней привязкой к текстовому полю:

<input v-model="username" /><button @click="save">Save</button>

При нажатии кнопки рядом с текстовым полем вызывается метод save, который, в свою очередь, генерирует событие userchange:

save(){
	this.$emit("userchange", this.username);
}

Через событие userchange объект приложения Vue получит измененное имя пользователя и произведет необходимые изменения:

change(name){
	this.user = name;
},

Чтобы компонент useredit также мог отслеживать внешние изменения со свойством name, он определяет наблюдаемое свойство watcher:

watch: { 
      	name(newVal) {
          this.username = newVal;
        }
	}

В качестве параметра свойству передается новое значение свойства name. В итоге при всех изменениях сработает это свойство, что приведет к переустановке значения в username.

Второй дочерний компонент - userinfo также через свойство name из props получает от приложения Vue имя пользователя:

props: ["name"]

Однако этот компонент напрямую не изменяет значение name, а при нажатию на кнопку генерирует событие userreset

reset(){
	this.$emit("userreset");
}

Приложение Vue отслеживает это событие и при его возникновении сбрасывает имя пользователя в изначальное:

reset(){
	this.user = 'Tom';
},

То есть объект приложения Vue здесь служит медиатором, а непосредственно между собой компоненты не взаимодействуют.

Взаимодействие между сестринскими компонентами одного уровня во Vue 3
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850