Новое использование слота в vue 2.6

программист Vue.js

Переводчик: Front-end Xiaozhi

оригинал:ву ву ву.smashing magazine.com/2019/07/uu…

Ставь лайк и смотри, поиск в WeChat【Переезд в мир】Обратите внимание на этого человека, который не имеет большого фабричного прошлого, но имеет восходящий и позитивный настрой. эта статьяGitHub GitHub.com/QQ449245884…Он был включен, статьи были классифицированы, и многие мои документы и учебные материалы были систематизированы.

Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.

В недавнем выпуске Vue 2.6 синтаксис использования слотов стал более лаконичным. Это изменение в слотах побудило меня открыть для себя потенциальные возможности слотов для обеспечения повторного использования, новой функциональности и более удобного чтения для наших проектов на основе Vue. Каковы действительно способные слоты?

Если вы новичок в Vue или не видели изменений в версии 2.6, продолжайте читать. Возможно, лучшим ресурсом для изучения слотов является собственная документация Vue, но здесь я дам краткое описание.

Чтобы читать больше качественных статей, пожалуйстаПосетите блог GitHub, Сотни качественных статей ждут вас каждый год!

Что такое слот?

Слоты — это механизм для компонентов Vue, который позволяет вам составлять компоненты таким образом, который отличается от строгих отношений родитель-потомок. Слоты дают вам возможность размещать контент в новом месте или делать компонент более общим. Начните с простого примера:

// frame.vue
<template>
  <div class="frame">
    <slot></slot>
  </div>
</template>

Внешний слой этого компонента представляет собойdiv. Предположениеdivсуществует для создания структуры стиля вокруг его содержимого. Этот компонент можно использовать для оборачивания фрейма вокруг wq как угодно, давайте посмотрим, как это работает. здесьframeКомпонент относится к компоненту, который мы только что сделали.

// app.vue
<template>
  <frame><img src="an-image.jpg"></frame>
</template>

в начале и в концеframeСодержимое между тегами будет вставлено в слот, гдеframeкомпонент, заменитьslotотметка. Это самый основной метод. Вы также можете указать содержимое по умолчанию для размещения в слоте, просто заполнив

// frame.vue
<template>
  <div class="frame">
    <slot>如果这里没有指定任何内容,这就是默认内容</slot>
  </div>
</template>

Итак, теперь, если мы используем это так:

// app.vue
<template>
  <frame />
</template>

"Если здесь ничего не указано, это значение по умолчанию” является содержимым по умолчанию, но если оно используется как прежде, текст по умолчанию будетimgНаложение тегов.

Несколько/именованных слотов

К компоненту можно добавить несколько слотов, но если вы это сделаете, все слоты, кроме одного, должны иметь имена. Если есть слот без имени, это слот по умолчанию. Вот как создать несколько слотов:

// titled-frame.vue
<template>
  <div class="frame">
    <header><h2>
      <slot name="header">Title</slot>
    </h2></header>
    <slot>如果这里没有指定任何内容,这就是默认内容</slot>
  </div>
</template>

Мы сохранили тот же слот по умолчанию, но на этот раз мы добавили слот с именемheaderслот, где вы можете ввести название следующим образом:

// app.vue
<template>
  <titled-frame>
    <template v-slot:header>
      <!-- The code below goes into the header slot -->
      My Image’s Title
    </template>
    <!-- The code below goes into the default slot -->
    <img src="an-image.jpg">
  </titled-frame>
</template>

Как и раньше, если мы хотим добавить контент в слот по умолчанию, просто поместите его прямо вtitled-frameв компоненте. Однако, чтобы добавить содержимое в именованный слот, нам нужно использоватьv-slotДиректива оборачивает код вtemplateМаркировка. существуетv-slotдобавить двоеточие после(:), а затем напишите содержимое, которое будет переданоslotИмя.

Уведомление,v-slotдаVue 2.6, поэтому, если вы используете более старую версию, вам нужно прочитатьДокументация по синтаксису устаревшего слота.

слот с прицелом

Еще одна вещь, которую нужно знать, это то, что слоты могут передавать данные/функции своим дочерним элементам. Чтобы продемонстрировать это, нам нужен совершенно другой пример компонента со слотами: создайте компонент, который отправляет данные текущего пользователя в свой слот:

// current-user.vue
<template>
  <span>
    <slot v-bind:user="user">
      {{ user.lastName }}
    </slot>
  </span>
</template>

<script>
export default {
  data () {
    return {
      user: ...
    }
  }
}
</script>

Этот компонент имеетuser, который содержит сведения о пользователе. По умолчанию компонент отображает фамилию пользователя, но обратите внимание, что он используетv-bindПривязать пользовательские данные кslot. Таким образом, мы можем использовать этот компонент для предоставления пользовательских данных его потомкам.

// app.vue
<template>
  <current-user>
    <template v-slot:default="slotProps">{{ slotProps.user.firstName }}</template>    
  </current-user>
</template>

Для доступа перейдите кslotdata мы используем значение директивы v-slot, чтобы указать имя переменной области видимости.

Здесь следует отметить несколько вещей:

  • мы указалиdefault, но вам не нужно указывать имя слота по умолчанию. Вместо этого мы можем использовать v-slot="slotProps".

  • Не нужно использоватьslotPropsКак имя, вы можете называть его как хотите.

  • Если используется только слот по умолчанию, внутренние компоненты можно пропустить.templateотметка, прямоv-slotкоманда на текущийcurrent-userначальство.

  • Вместо использования одного имени переменной можно использовать деструктурирование объекта для создания прямых ссылок на данные слота с заданной областью. Другими словами, вы можете использоватьv-slot="{user}"заменятьv-slot="slotProps", который затем можно использовать напрямуюuserвместоslotProps.user.

Итак, приведенный выше пример можно переписать так

// app.vue
<template>
  <current-user v-slot="{user}">
    {{ user.firstName }}
  </current-user>
</template>

Еще несколько моментов, которые нужно помнить:

  • можно использоватьv-bindДирективы связывают несколько значений.

  • Также можно передавать функции в слоты с заданной областью действия. Многие библиотеки используют его для предоставления повторно используемых функциональных компонентов.

  • v-slotПсевдоним#. Поэтому вы можете использовать#header="data"заменитьv-slot:header="data". также можно использовать#headerзаменитьv-slot:header(Предпосылка: когда нет слота с областью действия). Для слотов по умолчанию требуется при использовании псевдонимовУкажите имя по умолчанию. Другими словами, вам нужно написать#default="data"вместо#="data".

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

Что можно делать со слотами?

Слоты не созданы для одной цели, или, по крайней мере, если они и созданы, они вышли за рамки своего первоначального предназначения и стали мощными инструментами для выполнения множества разных задач.

многоразовый шаблон

Компоненты всегда предназначены для повторного использования, но некоторые шаблоны нецелесообразно реализовывать с помощью одного «простого» компонента, потому что для его настройки требуетсяpropsИх может быть слишком много или нужно пройтиpropsПередайте большую часть контента или других компонентов.

Слоты могут заключать в себе внешние HTML-теги или компоненты и позволяют размещать другие HTML или компоненты в именованном слоте, соответствующем именованному слоту.

Для первого примера начните с чего-то простого: кнопки. Допустим, наша команда использует Bootstrap. В Bootstrap кнопки обычно такие же, как и в основных“btn”Класс привязан к классу, определяющему цвет, например“btn-primary”. вы также можете добавитьsizeклассы, такие как'btn-lg'.

Для простоты предположим, что ваше приложение используетbtn,btn-primaryа такжеbtn-lg. Вы не хотите всегда писать эти три класса на кнопке, или вы не доверяете новичкам, чтобы они не забывали их записывать.

В этом случае можно создать компонент, который автоматически включает все три этих класса, но как разрешить настраиваемый контент? props непрактичны, потому что кнопки могут содержать различный HTML, поэтому вместо этого мы должны использовать слот.

<!-- my-button.vue -->
<template>
  <button class="btn btn-primary btn-lg">
    <slot>Click Me!</slot>
  </button>
</template>

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

<!-- 使用 my-button.vue -->
<template>
  <my-button>
    <img src="/img/awesome-icon.jpg"> 我是小智!
  </my-button>
</template>

Конечно, вы можете выбрать что-то большее, чем кнопка. Придерживаясь Bootstrap, давайте посмотрим на модальное окно:

<!-- my-modal.vue -->
<template>
<div class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <slot name="header"></slot>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
      <div class="modal-body">
        <slot name="body"></slot>
      </div>
      <div class="modal-footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </div>
</div>
</template>

Теперь используйте его:

<!-- 使用 my-modal.vue -->
<template>
  <my-modal>
    <template #header>
      <h5>大家最棒!</h5>
    </template>
    <template #body>
      <p>大家加油</p>
    </template>
    <template #footer>
      <em>大家好样的!</em>
    </template>
  </my-modal>
</template>

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

функция повторного использования

Компоненты Vue — это не только HTML и CSS. Они построены на JavaScript, так что тоже о функциях. Слоты полезны для создания функций один раз и использования их в нескольких местах. Вернемся к модальному примеру и добавим функцию, закрывающую модальное окно.

<!-- my-modal.vue -->
<template>
<div class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <slot name="header"></slot>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
      <div class="modal-body">
        <slot name="body"></slot>
      </div>
      <div class="modal-footer">        
        <slot name="footer" :closeModal="closeModal"></slot>
      </div>
    </div>
  </div>
</div>
</template>

<script>
export default {
  //...
  methods: {
    closeModal () {
      // 关闭对话框时,需要做的事情
    }
  }
}
</script>

Используя этот компонент, вы можетеfooterДобавьте кнопку, которая может закрыть модальное окно. Как правило, в случае режима Bootstrap можно поставитьdata-dismiss =“modal”Добавлено в кнопку, чтобы закрыть.

Но мы хотим скрыть определенные вещи Bootstrap. Поэтому мы передаем им функцию, которую они могут вызывать, чтобы пользователь не знал, что у нас есть что-то, использующее Bootstrap.

<!-- 使用 my-modal.vue -->
<template>
  <my-modal>
    <template #header>
      <h5>Awesome Interruption!</h5>
    </template>
    <template #body>
      <p>大家加油!</p>
    </template>
    <template #footer="{closeModal}">
      <button @click="closeModal">
        点我可以关闭烦人的对话框
      </button>
    </template>
  </my-modal>
</template>

нет компонента рендеринга

Наконец, возьмите то, что вы знаете об использовании слотов для передачи многократно используемых функций, удалите весь HTML и просто используйте слоты. В этом суть компонента без рендеринга: компонента, который предоставляет только функции без какого-либо HTML.

Сделать компонент действительно без рендеринга может быть немного сложно, так как это требует написанияrenderвместо использования шаблона для удаления зависимости от корневого элемента, но это не всегда может быть необходимо. Давайте рассмотрим простой пример, который начинается с шаблонов:

<template>
  <transition name="fade" v-bind="$attrs" v-on="$listeners">
    <slot></slot>
  </transition>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>

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

Да, Vue имеет встроенные компоненты без рендеринга. Этот конкретный пример взят из статьи Cristi Jora наМногоразовый переходв статье, показывающей простой способ создания компонентов без рендеринга, которые стандартизируютtransition.

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

<!-- promised.vue -->
<template>
  <span>
    <slot  name="rejected"  v-if="error" :error="error"></slot>
    <slot  name="resolved"  v-else-if="resolved" :data="data"></slot>
    <slot  name="pending"  v-else></slot>
  </span>
</template>

<script>
export  default {
  props: {
    promise:  Promise
  },

  data: () => ({
    resolved:  false,
    data:  null,
    error:  null
  }),  

  watch: {
    promise: {
      handler (promise) {
        this.resolved  =  false
        this.error  =  null

        if (!promise) {
          this.data  =  null
          return
        }

        promise.then(data  => {
          this.data  =  data
          this.resolved  =  true
        })
        .catch(err  => {
          this.error  =  err
          this.resolved  =  true
        })
      },
      immediate:  true
    }
  }
}
</script>

Что здесь происходит, приятель?Во-первых, обратите внимание, что этот компонент принимает параметр типа Promise. существуетwatchраздел, мониторpromiseменяется, когдаpromiseКогда происходит изменение, очистите состояние, затем вызовите then и перехватите промис, обновив состояние, когда промис будет успешным или неудачным.

Затем в шаблоне мы отображаем другой слот в зависимости от состояния. Обратите внимание, что мы не оставили его полностью без рендеринга, потому что нам нужен корневой элемент для использования шаблона. мы такжеdataа такжеerrorПередано в соответствующую область действия слота.

<template>
  <div>
    <promised :promise="somePromise">
      <template #resolved="{ data }">
        Resolved: {{ data }}
      </template>
      <template #rejected="{ error }">
        Rejected: {{ error }}
      </template>
      <template #pending>
          请求中...
      </template>
    </promised>
  </div>
</template>
...

мы будемsomePromiseПередано необработанным компонентам. затем подождите, пока он закончится, дляpendingслот, показывающий "Запрос...". В случае успеха отображается «Решено: соответствующее значение». В случае сбоя отображается сообщение «Отклонено: причина сбоя». Теперь нам больше не нужно следить заpromiseсостояние, потому что раздел вытягивается в свой собственный повторно используемый компонент.

Итак, что мы можем сделать, чтобы обойтиpromised.vueслот в? Чтобы удалить его, нам нужно удалитьtemplateраздел и добавляем в наш компонентrenderфункция:

render () {
  if (this.error) {
    return this.$scopedSlots['rejected']({error: this.error})
  }

  if (this.resolved) {
    return this.$scopedSlots['resolved']({data: this.data})
  }

  return this.$scopedSlots['pending']()
}

Этот Здесь нет ничего слишком сложного. мы просто используем некоторыеifблок, чтобы найти состояние, а затем вернуть правильную областьslot(пройти черезthis.$ scopedslot ['SLOTNAME'](…)) и передать соответствующие данные вslotобъем. Если вы не используете шаблоны, вы можете пропустить использование.vueрасширение файла путем преобразования JavaScript изscriptотмечай и вставляй.jsв файле. Это должно дать вам очень небольшой прирост производительности при компиляции этих файлов Vue.

Суммировать

Слоты Vue выводят разработку на основе компонентов на совершенно новый уровень, и, хотя в этой статье показано много отличных способов использования слотов, их гораздо больше. Добро пожаловать, чтобы оставить сообщение для обсуждения.

Ошибки, которые могут существовать после развертывания кода, нельзя узнать в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку логов.Кстати, всем рекомендую полезный инструмент мониторинга ошибок.Fundebug.

общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.