что такое слот
слот (slot) Популярное понимание "оккупация ямы", которая занимает позицию в шаблоне компонента. Когда компонент используется, можно указать содержимое каждой ямы. Это то, что мы часто называем распространением контента.
Стоит отметить, что концепция слотов неVueпредложил, ноweb ComponentsЭто предлагается в проекте спецификации, и вы можете увидеть конкретную запись.Используйте шаблоны и слоты,VueПросто позаимствовал эту идею
В Vue 2.6.0 мы представили новый унифицированный синтаксис для именованных слотов и слотов с заданной областью (т.е.v-slotинструкция). он заменяетslotа такжеslot-scope, эти два атрибута в настоящее время устарели, но не удалены и все еще находятся в документации.
Примеры в этой статье основаны на Vue 2.6.X, поэтому все они используют синтаксис v-slot.
эта статьяDEMOвсе размещеноGithubа такжепесочницаДля всех, чтобы узнать, если у вас есть какие-либо вопросы, пожалуйста, комментируйте.
слот по умолчанию
Создаем новый родительский компонентParentи подкомпонентыChild, структура следующая:
Родительский компонент:
<!-- 默认插槽 -->
<h3>默认插槽</h3>
<Child>
<div class="parent-text">Hi, I am from parent.</div>
</Child>
Сборка:
<div class="child">
<slot></slot>
<div>Hello, I am from Child.</div>
</div>
вызов родительского компонентаChildкомпонент, он будет вChildПередача содержимого в дочерний компонент в теге<slot>метка, как показано ниже
То есть окончательный результат рендеринга выглядит следующим образом:
<div class="child">
<div class="parent-text">Hi, I am from parent.</div>
<div>Hello, I am from Child.</div>
</div>
запасной контент
Мы можем сделать это в дочернем компоненте<slot>Добавьте к нему некоторый контент, как показано ниже.
<div class="child">
<slot>当父组件不传值的时候,我就展示,我只是一个后备军</slot>
<div>Hello, I am from Child.</div>
</div>
Когда вызывается родительский компонент, когда в метке дочернего компонента нет соответствующего содержимого,<slot>Содержимое в метке вступит в силу, иначе не будет рендериться, что можно понимать как "запаску"
Например, родительский компонент вызывает указанный выше дочерний компонент:
<!-- 后备内容 -->
<h3>后备内容</h3>
<Child1></Child1>
Результат выглядит следующим образом:
именованный слот
Конечно слотов может быть больше одного, это в основном для возможности гибкого управления положением слота и абстракцией компонента. Мы можем передать дочерний компонентslotустановить на этикеткеnameсвойство, затем в родительском компоненте черезv-slot:(или используйте сокращение#) + дочерний компонентnameСпособ, которым значение свойства указывает, куда его вставить. Если это слот по умолчанию,v-slot:defaultТолько что
Следующий родительский компонент:
<!-- 具名插槽 -->
<h3>具名插槽</h3>
<Child2>
<template v-slot:footer><div>我是底部</div></template>
<template #header><div>我是头部</div></template>
<template v-slot:default>
<div>我是内容</div>
</template>
</Child2>
Подсборка
<div class="child">
<slot name="header"></slot>
<slot></slot>
<div>Hello, I am from Child.</div>
<slot name="footer"></slot>
</div>
Следует отметить, что окончательный порядок рендеринга основан на порядке подкомпонентов, то есть приведенном выше примере, который рендерится следующим образом:
слот с прицелом
Иногда мы хотим использовать данные и события дочернего компонента в слоте, как показано ниже (примечание:userопределяется вChild3Данные в компоненте):
<Child3>
<template>
<div>我的名字:{{user.name}}</div>
<div>我的年龄:{{user.age}}</div>
<button @click="callMe">Clicl Me</button>
</template>
</Child3>
Непосредственно сообщит:
Причина в том, что родительский компонент не может получить данные дочернего компонента.Запомните принцип:Все в родительском шаблоне компилируется в родительской области, все в дочернем шаблоне компилируется в дочерней области.
Итак, как мы можем получить данные или события дочерних компонентов? Мы можем напрямую передать дочерний компонентv-bindспособ передачи данных или событий родительскому компоненту, как показано ниже
<div class="child">
<div>Hello, I am from Child.</div>
<!-- 将user和callMe通过 v-bind 的方式传递 -->
<slot :user="user" :callMe="callMe"></slot>
</div>
Затем внутри слота в родительском компоненте передайте что-то вродеv-slot:default="slotProps"Получать данные из дочерних компонентов
<Child3>
<!-- slotProps 可以自定义-->
<template v-slot:default="slotProps">
<div>我的名字:{{slotProps.user.name}}</div>
<div>我的年龄:{{slotProps.user.age}}</div>
<button @click="slotProps.callMe">Clicl Me</button>
</template>
</Child3>
надslotPropsМожет быть настроен и может использовать синтаксис деструктурирующего присваивания
<!-- 解构赋值 -->
<template v-slot:other="{ user, callMe}">
<div>我的名字:{{user.name}}</div>
<div>我的年龄:{{user.age}}</div>
<button @click="callMe">Clicl Me</button>
</template>
Пример: разделение бизнес-логики и представлений
Мы часто сталкиваемся со сценарием, когда бизнес-логика двух компонентов может быть повторно использована, но представления разные.Например, у нас часто есть требования, похожие на тумблеры.Функции включают в себя:
- выключатель
- Включи
- Переключить переключатель
- Различное содержимое, когда переключатель закрыт или открыт
Мы можем быстро написать один из егоJSКод бизнес-логики:
export default {
data() {
return {
currentState: this.state
}
},
props: {
state: {
type: Boolean,
default: false
}
},
methods: {
openState() {
this.currentState = true;
},
closeState() {
this.currentState = false;
},
toggle() {
this.currentState = !this.currentState;
}
}
}
Но, может быть, теперь мой стиль такой
Однако стиль в другом месте такой (просто пример, в реальности может быть сложнее, и некоторые кнопки могут быть даже скрыты напрямую)
Здесь на помощь приходят слоты. Как упоминалось выше, слоты с ограниченной областью действия могут передавать данные и события от дочерних компонентов к родительским компонентам, что эквивалентно открытию интерфейса для внешнего мира. и можетHTMLсерединаDOMтак же какCSSОн передается родительскому компоненту (вызывающему) для обслуживания, а дочерний компонент передает<slot>Позиции, в которую вставлена этикетка, достаточно, основная логика следующая:
Сборка:
<template>
<div class="toggle-container">
<slot :currentState="currentState" :setOn="openState" :setOff="closeState" :toggle="toggle"></slot>
</div>
</template>
Родительский компонент:
<Toggle1 :state="state" class="toggle-container-two">
<template v-slot:default="{currentState, setOn, setOff, toggle }">
<button @click="toggle">切换</button>
<button @click="setOff">关闭</button>
<button @click="setOn">打开</button>
<div v-if="currentState">我是打开的内容</div>
<div v-else>我是关闭的内容</div>
</template>
</Toggle1>
Мы сейчас используем однофайловый метод для записи, на самом деле все равно будут связанные подкомпонентыHTMLструктуру, как сделать так, чтобы дочерние компоненты не нужно было рендерить самостоятельноHTMLШерстяная ткань?那得了解下无渲染组件的实现
Дополнительно: реализация компонентов без рендеринга
Компоненты без рендеринга — это те, которым не нужно рендерить какие-либо свои собственные компоненты.HTMLс компонент. Вместо этого он только управляет состоянием и поведением. Он предоставляет отдельную область, предоставляя родительскому компоненту или потребителю полный контроль над тем, что должно быть отображено.Vue, обеспечивает метод записи однофайловых компонентов. Как и в приведенном выше примере, мы по-прежнему выполняем некоторые операции рендеринга в дочерних компонентах, так как же нам на самом деле не рендерить компоненты?
такие как вышеtoggleНапример, мы сделали возможным предоставление дочерним компонентам отдельной области действия, предоставив родительскому компоненту или потребителю полный контроль над тем, что должно быть отображено. Теперь нам нужно поместить один файлtemplateструктура(slotвнешняя этикеткаdiv) полностью передается родительскому компоненту, но в однофайловом компонентеslotЭтикетки неtemplateкорневого элемента
В настоящее время нам нужно понять функцию рендеринга Vue (render function)
В конечном счете,Vueи все его компоненты простоJavaScript. Однофайловые компоненты в конечном итоге будут создаваться с помощью таких инструментов, какwebpack,БудуCSSИзвлеките, чтобы сформировать файл, другое содержимое будет преобразовано вJavaScript, аналогично следующему:
export default {
template: <div class="mood">...</div>,
data: () => ({ todayIsSunny: true })
}
Конечно, это не окончательный его вид, компилятор шаблона извлечетtemplateатрибутировать содержимое и компилировать его содержимое какJavaScript, то черезrenderфункция добавляется к объекту компонента. Окончательная форма должна быть следующей:
render(h) {
return h(
'div',
{ class: 'mood' },
this.todayIsSunny ? 'Makes me happy' : 'Eh! Doesn't bother me'
)
}
Для конкретных функций рендеринга см.Официальный сайт, хотя пишетrenderСтоимость функции будет выше, но ее производительность будет намного лучше, чем у однофайлового компонента.
В приведенном выше примере, когда есть только слоты, нам нужно толькоrenderфункция, использованиеthis.$scopedSlots.defaultзаменять<slot>Просто пометить
код показывает, как показано ниже:
export const toggle = {
data() {
return {
currentState: this.state
}
},
render() {
return this.$scopedSlots.default({
currentState: this.currentState,
setOn: this.openState,
setOff: this.closeState,
toggle: this.toggle,
})
},
props: {
state: {
type: Boolean,
default: false
}
},
methods: {
openState() {
this.currentState = true;
},
closeState() {
this.currentState = false;
},
toggle() {
this.currentState = !this.currentState;
}
}
}
Вышеупомянутое можно сделать так, чтобы дочерний компонент вообще не отображал свой собственныйHTMLохватывать
Суммировать
В этой статье представлены некоторыеVueОсновы слотов, в том числе
- слот по умолчанию
- запасной контент
- именованный слот
- слот с прицелом
Затем я представил, как реализовать разделение бизнес-логики и просмотра через слоты, а затем объединить функцию рендеринга для реализации реальной функции рендеринга.
эта статьяDEMOвсе размещеноGithubа такжепесочницаДля всех, чтобы узнать, если у вас есть какие-либо вопросы, вы можете оставить комментарий.
Так сложно, попроси лайк, ха-ха
Надеюсь, это поможет всем~
Рекомендуемые отличные статьи в прошлом
- [Vue Advanced] — Как добиться прозрачной передачи атрибутов компонентов?
- Знание HTTP, которое должен знать внешний интерфейс
- Самый мощный макет CSS — макет сетки
- Как написать полное приложение Vue с помощью Typescript
- Инструмент веб-отладки, который должен знать внешний интерфейс — свисток
Ссылаться на: