Несколько полезных трюков во 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: