Всем привет, это Лин Сансин, Vue реализовал набор API для распространения контента,
<slot>Элементы действуют как выходы для переноса распределенного контента, это указано в документации Vue. Конкретно,slotЭто «пробел», который позволяет вам добавлять контент в компонент.Вы действительно знаете, как «вставляется» слот? Я надеюсь, что вы можете быть таким же простым, как я, и честно прочитать эту статью.
Основное использование слота Vue
одиночный слот | анонимный слот
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
</div>
</template>
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
林三心
</child>
</div>
</template>
Мы знаем, что если вы добавите содержимое «Lin Sanxin» непосредственно в родительский компонент, текст «Lin Sanxin» не будет отображаться на странице. Так как же сделать так, чтобы добавленный контент отображался? Просто добавьте слот в подкомпонент.
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot></slot>
</div>
</template>
область компиляции (родительский компонент в дочернем компоненте<slot></slot>вставьте данные)
Как мы узнали выше, слот на самом деле является «пространством», которое позволяет нам добавлять контент к дочернему компоненту в родительском компоненте. Мы можем добавить любое значение данных в родительский компонент, например:
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child> {{ parent }}</child>
</div>
</template>
new Vue({
el:'.app',
data:{
parent:'父组件'
}
})
Синтаксис использования данных совсем не изменился, но можем ли мы использовать данные напрямую из дочерних компонентов? Очевидно нет! !
// 子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot></slot>
</div>
</template>
new Vue({
el:'child',
data:{
child:'子组件'
}
})
// 父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child> {{ child }}</child>
</div>
</template>
Невозможно передавать данные непосредственно в дочерние компоненты. Потому что: все в родительском шаблоне компилируется в родительской области, все в дочернем шаблоне компилируется в дочерней области.
запасной контент (дочерние компоненты<slot></slot>установить значение по умолчанию)
Так называемый задний контент на самом деле является значением слота по умолчанию.Иногда я не добавляю контент в родительский компонент, тогда слот будет отображать значение по умолчанию, например:
//子组件 : (假设名为:child)
<template>
<div class='child'>
<slot>这就是默认值</slot>
</div>
</template>
именованный слот (несколько подкомпонентов<slot></slot>соответствующий вставленному контенту)
Иногда в дочернем компоненте может быть более одного слота, так как же вставить соответствующий контент в родительский компонент точно в нужное место? Просто дайте слоту имя, то есть добавьте атрибут name.
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot name='one'> 这就是默认值1</slot>
<slot name='two'> 这就是默认值2 </slot>
<slot name='three'> 这就是默认值3 </slot>
</div>
</template>
родительский компонент передан, или
slot="name"(旧语法),v-slot:nameили#name(新语法)добавить контент таким образом:
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
<template v-slot:"one"> 这是插入到one插槽的内容 </template>
<template v-slot:"two"> 这是插入到two插槽的内容 </template>
<template v-slot:"three"> 这是插入到three插槽的内容 </template>
</child>
</div>
</template>
Слоты с заданной областью (родительский компонент в дочернем компоненте<slot></slot>использовать данные подкомпонента)
пройти через
slotМы можем добавить содержимое к дочернему компоненту в родительском компоненте, указавslotКак мы его называем, мы можем добавлять контент из более чем одного места. Но данные, которые мы добавляем, находятся в родительском компоненте. Выше мы сказали, что не можем использовать данные в подкомпоненте напрямую, но есть ли у нас другие методы, позволяющие использовать данные подкомпонента? На самом деле, мы также можем использоватьslot-scopeПуть:
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot name= 'one' :value1='child1'> 这就是默认值1</slot> //绑定child1的数据
<slot :value2='child2'> 这就是默认值2 </slot> //绑定child2的数据,这里我没有命名slot
</div>
</template>
new Vue({
el:'child',
data:{
child1:'数据1',
child2:'数据2'
}
})
//父组件:(引用子组件 child)
<template>
<div class='app'>
<child>
<template v-slot:one='slotone'>
{{ slotone.value1 }} // 通过v-slot的语法 将子组件的value1值赋值给slotone
</template>
<template v-slot:default='slotde'>
{{ slotde.value2 }} // 同上,由于子组件没有给slot命名,默认值就为default
</template>
</child>
</div>
</template>
Как "затыкается" слот (популярная версия)
обычный слот
//子组件 : (假设名为:child)
<template>
<div class='child'>
我在子组件里面
<slot></slot>
<slot name="one"></slot>
</div>
</template>
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
这是插入到默认插槽的内容 {{parent}}
<template v-slot:"one"> 这是插入到one插槽的内容 {{parent}}</template>
</child>
</div>
</template>
new Vue({
el:'.app',
data:{
parent:'父组件的值'
}
})
- Сначала анализируется родительский компонент, а
childРассматривать как дочерний элемент, рассматривать слот какchildДочерний элемент обрабатывается, и значение родительской переменной извлекается в области действия родительского компонента, в результате чего получается такой узел:
{
tag: "div",
children: [{
tag: "child",
children: ['这是插入到默认插槽的内容 父组件的值',
'这是插入到one插槽的内容 父组件的值']
}]
}
- Подкомпонентский разбор,
slotВ качестве заполнителя он будет проанализирован в функцию, что примерно означает, что он будет проанализирован в следующем
{
tag: "div",
children: [
'我在子组件里面',
_t('default'), // 匿名插槽,默认名称为default
_t('one') // 具名插槽,名称为one
]
}
- Функция _t должна передавать имя слота, по умолчанию
default, именованный слот передается вname, функция этой функции состоит в том, чтобы получить узел слота, проанализированный на первом шаге, а затем вернуть проанализированный узел, после чего узел подкомпонента завершен, и слот успешно распознал отца——divЭтикетка
{
tag: "div",
children: ['我在子组件里面',
'这是插入到默认插槽的内容 父组件的值',
'这是插入到one插槽的内容 父组件的值']
}
слот с прицелом
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot :value1='child1' :value2='child1'></slot>
<slot name='one' :value1='child2' :value2='child2'></slot>
</div>
</template>
new Vue({
el:'child',
data:{
child1: '子数据1',
child2: '子数据2'
}
})
//父组件:(引用子组件 child)
<template>
<div class='app'>
<child>
<template v-slot:default='slotde'>
插入默认 slot 中{{ slotde.value1 }}{{ slotde.value2 }}
</template>
<template v-slot:one='slotone'>
插入one slot 中{{ slotone.value1 }}{{ slotone.value2 }}
</template>
</child>
</div>
</template>
- Процесс очень сложный, вот популярный момент, родительский компонент анализируется первым, и когда он сталкивается со слотом области видимости, он инкапсулирует слот в функцию и сохраняет его в дочернем элементе.
childВниз
{
tag: "div",
children: [{
tag: "child"
scopeSlots:{
default (data) { // 记住这个data参数
return ['插入one slot 中插入默认 slot 中' + data.value1 + data.value2]
},
one (data) { // 记住这个data参数
return ['插入one slot 中' + data.value1 + data.value2]
}
}
}]
}
2. Наступает очередь подкомпонента парсить, в это время снова появляется функция _t, а подкомпонент оборачивает соответствующие данные слота в объект и передает их в функцию _t
{
tag: "div",
children: [
'我在子组件里面',
_t('default',{value1: '子数据1', value2: '子数据1'}),
_t('one',{value1: '子数据2', value2: '子数据2'})
]
}
Далее выполняется внутреннее выполнение _t.Обёрнутый объект передается в соответствующие функции в scopeSlots в качестве параметра данных и анализируется в:
{
tag: "div",
children: [
'我在子组件里面',
'插入默认 slot 中 子数据1 子数据1',
'插入one slot 中 子数据2 子数据2'
]
}
$slots
Увидев это, я считаю, что вы уже поняли про процесс (хотя он и не очень подробный), тогда возникает другой вопрос, эти разобранные
节点VNodeГде существует объект? Вы не можете разобрать его и выбросить, верно? Должен найти место, чтобы сохранить его и сделать это真实dom, это место$slots
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot></slot>
<slot name='one'></slot>
<slot name='two'></slot>
<slot name='three'></slot>
</div>
</template>
new Vue({
el:'.child',
created () {
console.log(this.$slots) // 看看里面有啥
}
})
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
<template> 这是插入到默认插槽的内容 </template>
<template v-slot:"one"> 这是插入到one插槽的内容 </template>
<template v-slot:"two"> 这是插入到two插槽的内容 </template>
<template v-slot:"three"> 这是插入到three插槽的内容 </template>
</child>
</div>
</template>
Результат console.log:
Все здесь понимают,
$slotsЯвляетсяMap,keyимя каждого слота (анонимный слотkeyдляdefault), значение, соответствующее ключу, — это узел VNode под каждым слотом, а конкретный объект VNode — это то, как он выглядит. Вы можете вывести его сами. В нем слишком много всего, поэтому я не буду его здесь показывать. Эй-эй.