Несколько полезных трюков во Vue.js
Перевод статьи A few handy Vue.js tricks
1. Проброс всех props'ов из родительского компонента в дочерний компонент
Если вы разрабатываете приложения на Vue.js, то в какой-то момент вы наверняка напишите компонент, который будет «обернут» вокруг другого компонента. Так называемый компонент-обертка будет часто принимает все props'ы, которые также принимает компонент, который он оборачивает. Затем вы захотите «пробросить» все эти props'ы в завернутый компонент. Вместо этого:
<template> <child-component :someprop1="someprop1" :someprop2="someprop2" :someprop3="someprop3" :someprop4="someprop4" ... /> </template>
вы можете просто пробросить все props'ы компонента-обертки в оборачиваемый компонент, выполнив это:
<template> <child-component v-bind="$props"/> </template>
2. Гарантия того, что два компонента принимают одинаковые props'ы
Этот трюк может быть скомбинирован с трюком №1. Теперь, когда известно, как перенаправить все props'ы в обернутый компонент, можно задаться вопросом: как убедиться в том, что компонент-обертка принимает все те же props'ы, что и обернутый компонент? В компоненте-обертке, можно написать что-то вроде этого:
<template> <child-component v-bind="$props"/> </template> <script> import ChildComponent from '@/components/ChildComponent' export default { props: { someProp1: String, someProp2: String, someProp3: String, // и т.д. } } </script>
Этот подход имеет некоторые недостатки. Одним из этих недостатков является то, что если вы переписываете ChildComponent и, возможно, добавляете или удаляете props'ы, вам также придется вносить изменения в компонент-обертку. Другим недостатком является дублирование кода и, как правило, плохая эстетика кода. К счастью, есть очень простое решение этой проблемы:
<template> <child-component v-bind="$props"/> </template> <script> import ChildComponent from '@/components/ChildComponent' export default { props: { ...ChildComponent.options.props } } </script>
3. Отправка всех event listener'ов родительского компонента в дочерний компонент
Вам не нужно этого делать, если дочерний компонент, которому вы хотите передать event listener'ы, находится в корне родительского компонента, так как он по умолчанию получает все event listener'ы. Однако, если это не так, как в следующем примере, вы можете сделать это:
<template> <div> ... <child-component v-on="$listeners"/> ... </div> </template>
4. Красивый синтаксис слотов
Начиная с Vue 2.6, для именованных слотов появилось сокращение, как, например, для событий: @click
вместо v-on:click
. Если у вас, к примеру, есть компонент <my-table>
, в котором есть именованный слот row
, в котором есть slot-prop с именем item
, то мы можем передать ему кусок шаблона и получить доступ к prop'су item
следующим образом:
<template> ... <my-table> <template #row="{ item }"> /* some content here. You can freely use 'item' here */ </template> </my-table> ... </template>
5. Динамические аргументы директивы
Возможно, это самая впечатляющая и мощная функция, предлагаемая Vue 2.6: динамическая передача аргументов директивы компоненту. Предположим, у вас есть компонент <my-button>
. По некоторым причинам, иногда вы хотите прослушать событие click
, а в других случаях вы хотите прослушать dblclick
. Вы можете решить это с помощью динамических директив, таких как:
<template> ... <my-button @[someEvent]="handleSomeEvent()"/> ... </template> <script> ... data() { return { ... someEvent: someCondition ? 'click' : 'dblclick' } }, methods: { handleSomeEvent() { // do something } } ... </script>
Динамические event listener'ы - это только одна из многих вещей, которые вы можете сделать. Так же вы можете применить тот же шаблон к динамическим атрибутам HTML, props'ам и многому другому!
6. Динамический атрибут src в изображении
Это частый случай, когда вам нужно отобразить локально сохраненное изображение, путь которого хранится в переменной или в свойстве какого-либо объекта. Хотя для этого есть несколько решений, я предпочитаю использовать функцию require
, который поставляется webpack'ом. Предположим, что в data
вашего компонента Vue есть объект, который выглядит следующим образом:
data() { return { company: { name: 'CashMoney Inc.', logo: 'cashmoneylogo.png' } } }
Путь к изображению, которое вы хотите отобразить, хранится в свойстве logo
объекта company
. В этом примере мы будем иметь ввиду то, что все наши изображения находятся по пути src/assets
. Так же у нас существует подпапка с названием logos
, которая содержит в себе несколько изображений логотипов. Таким образом, полный путь к нашему изображению будет: src/assets/logos/cashmoneylogo.png
.
Из всего этого следует, что в <template>
вашего компонента вы должны создать тег <img>
и динамически пробросить данные в значение атрибута src
:
<template> ... <img :src="require(`@/assets/logos/${company.logo}`)"/> ... </template>
Несколько вещей, которые мы рассмотрим:
- Путь, который передается в функцию
require
, является шаблонной строкой`…`
. Таким образом, вы можете аккуратно вставить переменную, используя${...}
вместо конкатенации строки с помощью оператора + - Функция
require
не будет работать с полностью динамическим путем, поскольку webpack'у, во время сборки проекта, нужно знать о том, какие файлы нужно подтягивать. В пути к файлу вы должны указать статическую часть пути (@/assets/logos/
). После чего webpack объединит все файлы, которые соответствуют этому пути*. Вот почему в нашем примере часть пути@/assets/logos
жестко запрограммирована. Кстати,@
по сути означает «относительно папкиsrc
» (alias). Вы можете использовать его независимо от того, где находится файл, который вы ищите, и я настоятельно рекомендую использовать его вместо объявления уродливых путей в относительной форме, например./../../../
. Еще одно преимущество: если вы когда-нибудь решите переместить свой компонент / файл куда-нибудь еще, то путь, обозначенный с помощью@
останется рабочим.
* Примечание: это может повлиять на производительность, так как во время сборки приложения, webpack возьмет все файлы из указанного вами пути папки. Если это так, убедитесь, что ваш путь содержит в себе как можно меньшее количество файлов или посмотрите возможные варианты оптимизации, предлагаемые webpack'ом.
Послесловие
Подписывайся на нас в социальных сетях:
Vue.js
Nuxt.js
Наши друзья uWebDesign: