Интервьюер: Каковы способы взаимодействия между родительскими и дочерними компонентами в Vue?
Подумайте минуту.
Бесспорно, что теперь его использовали как крупные, так и мелкие заводы.Vue.jsФреймворк прост и удобен в использовании, с подробными руководствами, активным сообществом и множеством сторонних комплектов. Действительно необходимая вещь для фронтенд-разработчиков. А на собеседовании часто задают разные вопросы о Vue, и большинство интервьюеров зададут вышеуказанные вопросы.
В последнее время я занимаюсь оптимизацией на уровне кода проекта Vue.Если честно, оптимизация чужого кода - дело действительно болезненное.Не будем говорить о реализации функции, но про спецификацию кода я могу написать еще одну статью. Без норм создать кружок действительно невозможно, слишком важно регламентировать это дело! Это немного разглагольствования, вернемся к теме, кашель, давайте поговорим о моем понимании вопросов интервью выше, написание ограничено, и если есть что-то неуместное, пожалуйста, оставьте сообщение в конце статьи.
список
Несколько способов связи представляют собой не что иное, как следующее:
-
Prop(обычно используется) -
$emit(Подробнее об упаковке компонентов) -
.syncсинтаксический сахар (меньше) -
$attrs&$listeners(Подробнее об упаковке компонентов) -
provide&inject(Компоненты/библиотеки компонентов более высокого порядка используются чаще) -
slot-scope&v-slot(vue@2.6.0+) новый -
scopedSlotsАтрибуты - другие средства связи
Давайте представим их по одному, Боже, пожалуйста, в обход.
1. Prop
Британское произношение: [prɒp]. Это часто используется в нашей повседневной разработке. Проще говоря,мы можем пройтиPropПередать данные дочерним компонентам. Если использовать образную метафору, передача данных между родительским и дочерним компонентами эквивалентна нисходящей канализационной трубе, которая может течь только сверху вниз, но не в обратном направлении. Это также часть философии дизайна Vue.Однонаправленный поток данных. А Prop — это связь между трубами и трубами, чтобы вода (данные) могла стекать вниз. Сказав все это, посмотрите на код:
<div id="app">
<child :content="message"></child>
</div>
// Js
let Child = Vue.extend({
template: '<h2>{{ content }}</h2>',
props: {
content: {
type: String,
default: () => { return 'from child' }
}
}
})
new Vue({
el: '#app',
data: {
message: 'from parent'
},
components: {
Child
}
})
ты можешь быть жесткимкликните сюдаПроверьте демо! Вывод браузера:
from parent
2. $emit
Британское произношение: [iˈmɪt]. Официальное заявлениеЗапускает событие в текущем экземпляре. Дополнительные параметры передаются обратному вызову слушателя.. Насколько я понимаю, я не знаю, смогу ли я объяснить это вам.Давайте сначала кратко рассмотрим код:
<div id="app">
<my-button @greet="sayHi"></my-button>
</div>
let MyButton = Vue.extend({
template: '<button @click="triggerClick">click</button>',
data () {
return {
greeting: 'vue.js!'
}
},
methods: {
triggerClick () {
this.$emit('greet', this.greeting)
}
}
})
new Vue({
el: '#app',
components: {
MyButton
},
methods: {
sayHi (val) {
alert('Hi, ' + val) // 'Hi, vue.js!'
}
}
})
ты можешь быть жесткимкликните сюдаПроверьте демо!Общая логика - это соус: когда я нажимаю кнопку на странице, компонент срабатываетMyButtonпрослушать событие наgreetи передать параметры функции обратного вызоваsayHi. Грубо говоря, когда мы начинаем с дочернего компонентаEmit(Отправка) Перед событием его внутренняя часть продвигается в очереди событий.On(прослушивается) это событие и его обратный вызов слушателя. Фактически, это эквивалентно следующему письму:
vm.$on('greet', function sayHi (val) {
console.log('Hi, ' + val)
})
vm.$emit('greet', 'vue.js')
// => "Hi, vue.js"
3. модификатор .sync
Этот парень существовал как функция двусторонней привязки, когда vue@1.x, то есть дочерний компонент мог изменять значение в родительском компоненте. потому что это нарушаетОднонаправленный поток данныхКонцепция дизайна, поэтому она была убита, когда vue@2.0. Но это было повторно введено в vue@2.3.0+ и выше..syncмодификатор. Но на этот раз он существует только как синтаксический сахар времени компиляции. Он будет расширен до прослушивателя v-on, который автоматически обновляет свойства родительского компонента. Грубо говоря, давайте вручную обновим значение в родительском компоненте, чтобы источник изменения данных был более очевиден. Ниже приводится выдержка из официального пассажа:
В некоторых случаях нам может понадобиться «двусторонняя привязка» реквизита. К сожалению, истинное двустороннее связывание создает проблемы сопровождения, поскольку дочерние компоненты могут изменять родительский компонент, а очевидных источников изменений как в родительском, так и в дочернем компонентах нет.
Поскольку это синтаксический сахар, он должен быть сокращенной формой определенного способа написания.Какой способ написания, смотрите в коде:
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event">
</text-document>
Таким образом, мы можем использовать.syncСинтаксический сахар сокращен следующим образом:
<text-document v-bind:title.sync="doc.title"></text-document>
Столько ерунды, как добиться "двусторонней привязки"? Перейдем к рекламе, а после рекламы еще интереснее! ... Хорошо, с возвращением. Предположим, мы хотим добиться такого эффекта: изменение значения в текстовом поле дочернего компонента также меняет значение в родительском компоненте. Как это сделать? Ранк может сначала подумать. Сначала посмотрите на код:
<div id="app">
<login :name.sync="userName"></login> {{ userName }}
</div>
let Login = Vue.extend({
template: `
<div class="input-group">
<label>姓名:</label>
<input v-model="text">
</div>
`,
props: ['name'],
data () {
return {
text: ''
}
},
watch: {
text (newVal) {
this.$emit('update:name', newVal)
}
}
})
new Vue({
el: '#app',
data: {
userName: ''
},
components: {
Login
}
})
ты можешь быть жесткимкликните сюдаПосмотрите демо! Подчеркните ключевые моменты, в коде есть такое предложение:
this.$emit('update:name', newVal)
Официальный синтаксис:update:myPropNameвmyPropNameПредставляет значение реквизита для обновления. Конечно, если вы используете .$emit выше без синтаксического сахара .sync, вы можете добиться того же эффекта. Это все!
4. $attrs & $listeners
- Официальный сайт
$attrsобъясняется следующим образом:
Содержит привязки свойств, которые не распознаются (и не получены) как свойства в родительской области (
classа такжеstyleКроме). Когда компонент не объявляет никаких реквизитов, сюда включаются все привязки родительской области (classа такжеstyleкроме), и может пройтиv-bind="$attrs"Передача внутренних компонентов — полезно при создании высокоуровневых компонентов.
- Официальный сайт
$listenersобъясняется следующим образом:
Входит в родительскую область (исключая
.nativeмодификатор)v-onпрослушиватель событий. это может пройтиv-on="$listeners"Передача внутренних компонентов — полезно при создании компонентов более высокого уровня.
я думаю$attrsа также$listenersАтрибуты похожи на два ящика для хранения, один отвечает за хранение атрибутов, а другой отвечает за хранение событий, оба из которых хранятся в виде объектов. См. объяснение кода ниже:
<div id="app">
<child
:foo="foo"
:bar="bar"
@one.native="triggerOne"
@two="triggerTwo">
</child>
</div>
Как видно из Html, есть два свойства и два метода, разница в том, что одно из свойствpropобъявляет, что событие один.nativeмодификатор.
let Child = Vue.extend({
template: '<h2>{{ foo }}</h2>',
props: ['foo'],
created () {
console.log(this.$attrs, this.$listeners)
// -> {bar: "parent bar"}
// -> {two: fn}
// 这里我们访问父组件中的 `triggerTwo` 方法
this.$listeners.two()
// -> 'two'
}
})
new Vue({
el: '#app',
data: {
foo: 'parent foo',
bar: 'parent bar'
},
components: {
Child
},
methods: {
triggerOne () {
alert('one')
},
triggerTwo () {
alert('two')
}
}
})
ты можешь быть жесткимкликните сюдаПосмотреть демо! Вы можете увидеть, мы можем$attrsа также$listenersОчень удобно передавать данные, звонить и обрабатывать там, где нужно. Конечно, мы также можемv-on="$listeners"Он передается уровень за уровнем, и потомки бесконечны!
Интерлюдия!
Когда мы назначаем компоненту не-Prop объявление, скомпилированный код будет рассматривать эти атрибуты как исходные атрибуты и добавлять их в нативный тег html. Посмотрите, как приведенный выше код выглядит после компиляции:
<h2 bar="parent bar">parent foo</h2>
Это было бы некрасиво, и это бы что-то взорвало. Как избавиться от этого? это точноinheritAttrsАрена недвижимости! Добавьте это свойство на компонент на линии, обычно с$attrsиспользовать. Посмотрите на код:
// 源码
let Child = Vue.extend({
...
inheritAttrs: false, // 默认是 true
...
})
Скомпилируйте снова:
<h2>parent foo</h2>
5. provide & inject
Они вдвоем против КП и чувствуют себя довольно загадочно. Взгляните на официальнуюprovide / injectописание:
provideа такжеinjectВ основном предоставляет варианты использования для библиотек плагинов/компонентов более высокого порядка. Его не рекомендуется использовать непосредственно в коде приложения. И эту пару опций необходимо использовать вместе, чтобы позволить компоненту-предку внедрить зависимость во все его потомки, независимо от того, насколько глубока иерархия компонентов, и это всегда будет действовать, пока устанавливаются отношения восходящего и нисходящего потоков.
看完描述有点懵懵懂懂! Sentence summary is this: Your father a child everything to help you keep waiting for you to grow up with the young married woman you want to marry you buy a house you want to buy a car for as long as he will try to meet some of ты.下面是这句话的代码解释:
<div id="app">
<son></son>
</div>
let Son = Vue.extend({
template: '<h2>son</h2>',
inject: {
house: {
default: '没房'
},
car: {
default: '没车'
},
money: {
// 长大工作了虽然有点钱
// 仅供生活费,需要向父母要
default: '¥4500'
}
},
created () {
console.log(this.house, this.car, this.money)
// -> '房子', '车子', '¥10000'
}
})
new Vue({
el: '#app',
provide: {
house: '房子',
car: '车子',
money: '¥10000'
},
components: {
Son
}
})
ты можешь быть жесткимкликните сюдаПроверьте демо!
6. slot-scope & v-slot
Для ознакомления с этим подходом см. мое введение к этой статье.Портал ->
7. scopedSlotsАтрибуты
Для ознакомления с этим подходом см. мое введение к этой статье.Портал ->
8. Другие средства связи
Помимо вышеперечисленных пяти методов, на самом деле существуют:
- EventBus
Идея состоит в том, чтобы объявить глобальную переменную экземпляра Vue.EventBus, Храните все данные связи и прослушиватели событий в этой переменной. может читатьСвязь между компонентами Vue с использованием шины событийпонять больше. Таким образом достигается обмен данными между компонентами, что несколько похоже наVuex. Но этот метод подходит только для очень маленьких проектов, а Vuex по-прежнему рекомендуется для сложных проектов. Вот простой код для реализации EventBus:
<div id="app">
<child></child>
</div>
// 全局变量
let EventBus = new Vue()
// 子组件
let Child = Vue.extend({
template: '<h2>child</h2>',
created () {
console.log(EventBus.message)
// -> 'hello'
EventBus.$emit('received', 'from child')
}
})
new Vue({
el: '#app',
components: {
Child
},
created () {
// 变量保存
EventBus.message = 'hello'
// 事件监听
EventBus.$on('received', function (val) {
console.log('received: '+ val)
// -> 'received: from child'
})
}
})
ты можешь быть жесткимкликните сюдаПроверьте демо!
- Vuex
Официально рекомендуемый режим Vuex — это режим управления состоянием, специально разработанный для приложений Vue.js.
- $parent
Родительский экземпляр, если он есть у текущего экземпляра. Взаимодействие между данными также может быть выполнено путем доступа к родительскому экземпляру, но в очень небольших случаях данные в родительском компоненте будут изменены напрямую.
- $root
Корневой экземпляр Vue текущего дерева компонентов. Если у текущего экземпляра нет родителя, этот экземпляр будет самим собой. Взаимодействие между данными также может быть выполнено путем доступа к корневому компоненту, но в очень небольших случаях данные в родительском компоненте будут изменены напрямую.
- broadcast / dispatch
Это методы в vue @1.0, которые являются вещанием событий и отправка событий. Хотя Vue@2.0 был удален, эти два метода могут быть смоделированы. может учиться из-заElementвыполнить. Иногда это все еще очень полезно, например, когда мы разрабатываем сборку дерева и т. д.
Суммировать
Сказав так много, я надеюсь, что одноклассники, которые это увидят, приобретут больше или меньше. Пожалуйста, оставьте сообщение, чтобы исправить неправильное место, большое спасибо. На самом деле существует много видов связи между родительскими и дочерними компонентами, в зависимости от обстоятельств, в которых вы их используете. Различные сценарии трактуются по-разному. Суть в том, что вы должны знать, что делать! До Великого Бога еще далеко, пока вы каждый день смотрите на сообщество, просматриваете документацию, пишете демки и каждый день добиваетесь небольшого прогресса, успехи всегда будут. Как говорится,У трех человек должен быть мой учитель, Я надеюсь, что больше друзей-единомышленников смогут собраться вместе, чтобы обменяться технологиями! Следующая группа почти заполнена, вы можете добавить меняQ1769617251. Обратите внимание, что vue достаточно.