# Передаем данные из child в parent в Vue

08:09
poster
В этом видео мы с вами разберем, как можно передавать данные из child компоненты в parent.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом видео мы с вами разберем, как можно передавать данные из child компоненты в parent. Например, у нас есть логин форма, которая является чайл компонентом. При отправке формы мы хотим передать логин и пароль в парент компонент.

В Vue есть несколько способов сделать это. На данный момент у меня создан пустой проект webpack-simple из vue-cli и в нем есть только компонент App.

Давайте создадим этот дочерний компонент с логин формой. В ней должно быть два инпута, для логина и пароля и кнопка submit.

LoginForm.vue

<template>
  <div>
    <h3>Login form</h3>
    <div>
      <div>
        <label>Email:</label>
        <input type='text' />
      </div>
      <div>
        <label>Password:</label>
        <input type='password' />
      </div>
      <div>
        <button>Login</button>
      </div>
    </div>
  </div>
</template>

Также, мы должны импортировать наш компонент в App и добавить в локальные компоненты.

App.vue

import loginForm from './LoginForm.vue'

export default {
  ...
  components: {
    loginForm
  }
}

Теперь мы можем отрендерить нашу форму в шаблоне App.

App.vue

<loginForm />

Как мы видим, наша форма успешно отрендерилась в браузере.

Теперь давайте добавить v-model для инпутов.

LoginForm.vue

<input type='text' v-model='email' />
...
<input type='password' v-model='password' />

Мы также должны создать значения по умолчанию для email и password.

LoginForm.vue

data () {
  return {
    email: '',
    password: ''
  }
}

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

LoginForm.vue

<button @click='login'>Login</button>
methods: {
  login () {
    console.log('login', this.email, this.password)
  }
}

Как мы видим в браузере, наш компонент успешно работает и мы получаем емейл и пароль внутри метода login.

Как же мы теперь можем передать эти данные в парент?

Первый способ, это с использованием this.$emit. emit построен на принципе publish/subscribe. Если вы не помните, что это за паттерн, то я оставлю ссылку на видео про этот паттерн в тексте видео. Идея заключается в том, что мы емитим что-то в чайл компоненте и случаем этот евент в парент компоненте.

LoginForm.vue

methods: {
  login () {
    this.$emit('login', {
      email: this.email,
      password: this.password
    })
  }
}

Здесь мы вызвали $emit функцию внутри логин метода. Первым аргументом мы передает имя евента. Это может быть любая строка. Вторым аргументом мы передаем данные, которые относятся к этому евенту. В нашем случае мы передаем емейл и пароль в обьекте.

Теперь мы можем слушать этот емит в нашем App компоненте. Мы должны добавит кастомный евент с таким же именем, с которым мы эмитили евент.

App.vue

<loginForm @login='onLogin' />

То есть, мы хотим вызвать метод onLogin, когда LoginForm заэмитила логин евент. И давайте добавим onLogin метод

App.vue

methods: {
  onLogin (data) {
    console.log('child component said login', data)
  }
}

Как вы видите, в onLogin мы получим первым параметром данные, которые мы передали в emitе. Если мы посмотрим в браузер, то все работает.

Итак еще раз, как это работает.

  1. login метод вызывается при клике в чайлде
  2. Мы эмитим login евент и пробрасываем туда наши данные
  3. В паренте мы случаем этот login евент на чайлде и вызываем onLogin, когда он происходит.

В этом случае наши child и parent компоненты абсолютно не связаны. Это конечно хорошо, но в этом и минус. Мы никогда не узнаем, у действительно ли парент слушает наш емит.

Есть также и другой способ передать данные из чайлда в парент. И это больше способ в стиле React и на мой взгляд он более наглядный, так как код легче дебажить. Мы можем просто передать в child компонент функцию из parent компонента и вызывать ее когда нам нужно.

Давайте изменим loginForm, чтобы мы могли передавать функцию.

App.vue

<loginForm :onLogin='onLogin' />

Не забывайте, что мы использовали v-bind, чтобы пробросить onLogin. Теперь мы должны добавить onLogin в props логин формы.

LoginForm.vue

export default {
  props: ['onLogin']
  ...
}

Теперь мы можем вместо эмита вызвать onLogin метод и получить такой же результат.

LoginForm.vue

login () {
  this.onLogin({
    email: this.email,
    password: this.password
  })
}

Если мы посмотрим в браузер, то все работает как и раньше. Но в этом случае мы можем добавить валидацию props и это нам очень облегчит дебаг в будущем.

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Moe Green
10 месяцев назад
вау! первый раз вижу, как во Vue прокидывают метод из родительского компонента в дочерний, через props )) сейчас понемногу учу react и как раз познакомился на днях с таким способом там )
monsterlessons
10 месяцев назад
На самом деле этим Vue и плох. Там есть много разных подходов и они не учат чему-то хорошему. Тот же Реакт пушит 1 подход. И это очень хорошо. А тут и pubsub, и прокидывание функций, и props validation какие-то обрезанные.