Сводка связи компонента Vue (не vuex и шина событий)

Vue.js

Список методов

  1. props && emit
  2. v-model
  3. $children && $parent
  4. $listeners && $attrs
  5. .sync

метод prop && emit

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

метод v-модели

v-modelСвязь, достигнутая в природе, все еще вышеpropsа такжеemitспособ, использоватьv-modelБольше похоже на синтаксический сахар.Введение в документацию

Возьмите сначала каштан:

// 这是父组件
<template>
  <div>
    <child v-model="msg"></child>
    <p>{{msg}}</p>
  </div>
</template>

<script>
import child from "../components/Child";
export default {
  data() {
    return {
      msg: "hello"
    };
  },
  components: { child }
};
</script>

// 这是子组件
<template>
  <div>
      <input :value="value" @input="$emit('input',$event.target.value)">
  </div>
</template>

<script>
export default {
  props: ["value"]
};
</script>

Когда родительский компонент использует дочерний компонент, используйтеv-modelСвязывать родительский компонентmsgданные, которые анализируются в дочернем компоненте в файл с именемvalueОпора и имяinputсобытие, поэтому в дочернем компонентеpropsопция должна быть записана какvalue,существует$emitСобытие также должно быть записано какinputмероприятие.此时当你在子组件输入时,就会改变父组件的msgстоимость.

Настройте реквизит и события с параметрами модели

Как упоминалось выше, опция props должна быть написанаvalue, событие также должно бытьinput. Это разрешение по умолчанию. На самом деле, мы также можем настроить объекты и события, используяmodelопции,Введение в документацию. Документация использует флажок в качестве примера, измените свойства и событие:

model: {
    prop: 'checked',
    event: 'change'
}

$children && $parentСпособ

Эти два API предоставляются Vue, Как следует из названия, они используются в родительском компоненте.$childrenДоступ к подкомпонентам, использование в подкомпонентах$parentДоступ к родительскому компоненту.

Возьмите простой каштан:

// 这是子组件

<template>
  <div>
     {{$parent.msg}}   // 子组件显示父组件数据
  </div>
</template>

<script>
export default {
  data() {
    return {
      child_msg: "我是子组件数据"
    };
  },
  mounted() {
    this.$parent.test(); // 子组件执行父组件方法
  }
};
</script>
// 这是父组件

<template>
  <div>
    <child/>
  </div>
</template>

<script>
import child from "../components/Child";
export default {
  data() {
    return {
      msg: "我是父组件的数据"
    };
  },
  components: { child },
  methods: {
    test() {
      console.log("我是父组件的方法,被执行");
    }
  },
  mounted() {
    console.log(this.$children[0].child_msg); // 执行子组件方法
  }
};
</script>

【Уведомление】 $childrenявляется массивом, поэтому, когда есть только один дочерний компонент, используйте[0]Получать. Он не гарантирует порядок при наличии нескольких дочерних компонентов и не отвечает на запросы.

$listenersСпособ

С первого взгляда на определение этого API я тоже, кажется, понял:

Содержит прослушиватель событий v-on из родительской области (без декоратора .native). Его можно передать внутренним компонентам через v-on="$listeners" - полезно при создании компонентов более высокого уровня.

Документация также описывает, как его использовать здесь:Введение в документацию

Просматривая некоторые блоги, я либо беру официальные примеры, либо много вводных, на самом деле я тоже выгляжу растерянным. Позже я потихоньку пытался его использовать и, наверное, понял, что он делает. Мое понимание:В бизнесе многоуровневых вложенных компонентов используйте$listenersПередача событий может быть выполнена с меньшим количеством кода.

Или, чтобы проиллюстрировать код, как показано на рисунке ниже, давайте реализуем связь от компонента B к родительскому компоненту,

Как правило, когда уровней вложенности слишком много, мы можем рассматривать vuex, но только передавать данные без промежуточной обработки, что немного излишне, поэтому, как показано на рисунке выше, мы все еще можем использоватьemitСпособ общения — это не что иное, как еще один уровень передачи и дополнительный код, который нужно написать. Итак, теперь есть$listeners, мы можем реализовать его удобнее, я пытаюсь реализовать его с наименьшим количеством кода:

Просто начните с компонента B внизу, у которого есть кнопка, которая запускает событие в экземпляре при нажатии.getFromB

// 组件B

<template>
  <div>
    <button @click="handleClick">B组件按钮</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit("getFromB");
    }
  }
};
</script>

Компонент A оборачивает компонент B, что эквивалентно станции передачи между родительским компонентом и компонентом B.$listeners, мы могли бы вызвать здесь другое событие, теперь нам это не нужно, мы делаем это:

// 组件A

<template>
  <div>
    <child-b v-on="$listeners" />
  </div>
</template>

<script>
import childB from "../components/ChildB";
export default {
  components: {
    childB
  },
  mounted() {
    console.log(this.$listeners);
  }
};
</script>

просто добавьv-on="$listeners"Вот и все. Любопытно, мы также можем распечатать его при монтировании$listeners.

Родительский компонент, очевидно, мы связываемся напрямуюgetFromBСобытия могут быть:

// 父组件

<template>
  <div>
   <child-a v-on:getFromB="fromB"/>
  </div>
</template>

<script>
import childA from "../components/ChildA";
export default {
  components: { childA },
  methods: {
    fromB() {
      console.log("B组件触发");
    }
  }
};
</script>

Это$listenersПростое использование , на этом этапе вы должны понимать, что когда компоненты вложены во многие слои, мы можем более удобно общаться без использования vuex.

Говоря об этом, я также хотел бы упомянуть API, который$attrs. это с$listenersОтношения похожи на отношения между props и emit, которые используются для передачи свойств нижележащим компонентам. Сначала вставьте его определение:

Включающая родительскую область не идентифицируется как реквизит (и получение) свойств привязки (кроме класса и стиля). Когда компонент не объявляет никакой пропс, где родительская область будет включать все привязки (и кроме стиля класса), и может быть v-bind="$attrs" Входящие внутренние компоненты - при создании высокоуровневых компонентов очень полезно.

我们回想下,如果使用 props 向孙组件传递数据时,在中间组件里,我们是要一层层使用 props 选项来接收,然后再传递的。 Так$attrsФункция состоит в том, чтобы не использовать реквизиты для получения данных, когда целевой подкомпонент не достигнут, а затем использовать реквизиты для его получения до тех пор, пока не будет достигнут компонент, которому нужны данные.

Когда я читаю другие блоги, эти два API говорят вместе.Там много кода.Для ясности я удалил избыточный код в приведенном выше коде и только продемонстрировал его.$attrsиспользование:

Родительский компонент передает свойствоtoB, что означает, что он используется для компонента B:

// 父组件

<template>
  <div>
   <child-a toB="hello"/>
  </div>
</template>

<script>
import childA from "../components/ChildA";
export default {
  components: { childA }
};
</script>

Компонент используетv-bind="$attrs"Вот и все, вам не нужно реквизиты, чтобы получить, и вы не можете на самом деле получить его, увидеть определение

// 组件 A

<template>
  <div>
     <child-b v-bind="$attrs" />
  </div>
</template>

<script>
import childB from "../components/ChildB";
export default {
  components: { childB }
};
</script>

Компонент B — наш последний дочерний компонент, он используетtoBсвойства, поэтому используйте опцию props, чтобы получить

<template>
  <div>
    <p>父组件传来数据:{{toB}}</p>
  </div>
</template>

<script>
export default {
  props: ["toB"]
};
</script>

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

.syncСпособ

Этот метод на самом деле весьма полезен, его функция в Vue 1.x — выполнять «двустороннюю привязку» к реквизиту. Но после Vue 2 разрешен только односторонний поток данных, поэтому теперь, даже если это выглядит как настоящая «двусторонняя привязка», по сути это просто синтаксический сахар времени компиляции.

Вот пример счетчика:

// 父组件

<template>
  <div>
    {{num}}
   <child-a :count.sync="num" />
  </div>
</template>

<script>
import childA from "../components/ChildA";
export default {
  data() {
    return {
      num: 0
    };
  },
  components: { childA }
};
</script>
// 子组件

<template>
  <div>
     <div @click="handleAdd">ADD</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: this.count
    };
  },
  props: ["count"],
  methods: {
    handleAdd() {
      this.$emit("update:count", ++this.counter);
    }
  }
};
</script>

Хм, выглядит более убедительно.

Эпилог

Глядя на это таким образом, за исключением$childrenа также$parentОн получается напрямую, а остальные тесно связаны с реквизитом и излучением. Как его использовать, решать вам.

наконец,С новым годом!