- Оригинальный адрес:Sliding In And Out Of Vue.js
- Оригинальный автор:Kevin Ball
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:LucaslEliane
- Корректор:Mcskiller, SevenOutman
Резюме: Одно из основных преимуществ Vue.js заключается в том, что он хорошо работает с другим кодом: то есть его не только легко встроить в другие приложения, но и легко обернуть во Vue код, не относящийся к Vue. В этой статье обсуждается второе преимущество Vue.js, в том числе три разных типа стороннего JavaScript и способы их встраивания в Vue.
Vue.js продемонстрировал очень впечатляющий рост использования за последние несколько лет.. Из малоизвестной библиотеки с открытым исходным кодом он превратился во второй по популярности интерфейсный фреймворк (после React.js).
Основная причина роста числа пользователей Vue заключается в следующем: Vue — этопрогрессивныйФреймворки — это позволяет вам разрабатывать части ваших страниц с помощью Vue.js без необходимости в полноценном одностраничном приложении. Также позволяет вам просто добавить тег script вместо использования полной системы сборки для запуска и работы.
Эта инкрементальная философия делает фрагментированную разработку Vue.js очень простой, без необходимости значительных архитектурных изменений. Однако одна вещь, которую часто упускают из виду, заключается не только в том, что Vue.js легче встроить в веб-сайты, написанные на других фреймворках.Встраивание другого кода в Vue.js также очень просто.. Хотя Vue контролирует DOM, он также резервирует выход, который позволяет другим JavaScript, не относящимся к Vue, управлять DOM.
В этой статье мы рассмотрим, что происходит, когда вы хотите использовать различные типы стороннего JavaScript и хотите встроить его в проект Vue, а затем представите несколько типов инструментов и методов, которые лучше всего подходят для встраивания в Vue. В конце рассмотрим недостатки этих методов и на что обратить внимание при принятии решения об их использовании.
В этой статье предполагается, что вы знакомы с Vue.js и концепциями компонентов и директив. Если вы ищете введение в Vue и эти концепции, ознакомьтесь с Сарой Драснер.introduction to Vue.js seriesилиОфициальная документация Vue.
Сторонние типы JavaScript
Мы ранжировали три основных типа стороннего JavaScript в порядке сложности:
DOM-независимая библиотека
Первая сторонняя библиотека JavaScript предоставляет только логические функции и не имеет прямого доступа к DOM, например, для времени обработки.moment.jsили для расширения возможностей функционального программированияlodashотносятся к этому типу.
Эти библиотеки легко интегрировать в приложения Vue, но есть несколько способов обеспечить разумный доступ. Эти библиотеки, как правило, предназначены для обеспечения функциональности служебных программ и совместимы с любым другим типом проекта JavaScript.
Библиотека улучшения элементов
Расширение элементов — это проверенный временем метод добавления дополнительных функций к элементам DOM. Например, это может помочь изображениям лениво загружатьlozadИли обеспечить входную фильтрацию для поля вводаVanilla Masker.
Эти библиотеки обычно воздействуют только на один элемент за раз, они могут манипулировать одним элементом, но не добавляют новые элементы в DOM.
Эти инструменты имеют четкую цель и очень просты для взаимодействия с другими решениями. Эти библиотеки часто вводятся в проекты Vue, чтобы не изобретать велосипед.
Компоненты и библиотеки компонентов
Эти инструменты большие и плотно обрамлены. НапримерDatatables.net,илиZURB Foundation. Эти библиотеки создают полноценный интерактивный компонент. Часто имеет несколько взаимодействующих элементов.
Эти библиотеки либо внедряют эти элементы непосредственно в DOM, либо ожидают высокого уровня контроля над DOM. Обычно они строятся с использованием других фреймворков или наборов инструментов (оба приведенных выше примера построены поверх jQuery).
Эти инструменты обеспечиваюточень широкийфункциональность, и заменить их другими инструментами без значительной модификации очень сложно, поэтому встраивание их в решение Vue имеет решающее значение для переноса большого приложения.
Как использовать во Вью
DOM-независимая библиотека
Интеграция библиотек, не зависящих от DOM, в проект Vue.js относительно проста. Если вы используете модули JavaScript, просто используйтеimport
илиrequire
Достаточно. Например:
import moment from 'moment';
Vue.component('my-component', {
//…
methods: {
formatWithMoment(time, formatString) {
return moment(time).format(formatString);
},
});
Если вы используете глобальный JavaScript, вам необходимо импортировать эту библиотеку перед вашим проектом Vue:
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js"></script>
<script src="/project.js"></script>
Другим распространенным подходом к многоуровневости является использование фильтров или методов для переноса функций в библиотеку для облегчения доступа к шаблонам.
вью фильтр
Вьюфильтр— это режим, позволяющий применять встроенное форматирование текста непосредственно в шаблоне. Пример приведен в документации, вы можете создать фильтр «заглавными буквами», а затем применить его к шаблону следующим образом:
{{myString | capitalize}}
При импорте библиотек, зависящих от формата, вы можете захотеть использовать их непосредственно в фильтрах. Например, если вы используетеmoment
Чтобы отформатировать дату в проекте и преобразовать ее в относительное время, мы можем создатьrelativeTime
фильтр.
const relativeTime = function(value) {
if (!value) return '';
return moment(value).fromNow();
}
Тогда мы можем использоватьVue.filter
чтобы добавить его глобально ко всем компонентам и экземплярам Vue:
Vue.filter('relativeTime', relativeTime);
или добавить его к использованиюfilters
Опции для конкретных компонентов:
const myComponent = {
filters: {
'relativeTime': relativeTime,
}
}
можешь попробоватьCodePenЗапустите этот код на: см. Smashing Magazine (@smashing-magazine) этого фрагмента кода:Интеграция с Vue: фильтр относительного времени.
Библиотека улучшения элементов
По сравнению с библиотеками, не зависящими от DOM, интеграция библиотек расширения элементов немного сложнее. Если вы не будете осторожны, Vue будет иметь перекрестный контроль с библиотекой, борясь за контроль над DOM.
Чтобы этого не произошло, вам нужно смонтировать библиотеки в жизненный цикл Vue, запустить эти библиотеки после того, как Vue завершит манипуляции с DOM, и должным образом обработать запускаемые Vue обновления.
Эти вещи можно делать внутри компонента, но, поскольку эти библиотеки обычно касаются только одного элемента, обертывание его в пользовательскую директиву является более гибким подходом.
Vue-директивы
Директивы Vue — это модификаторы, которые добавляют поведение элементам на странице. Vue уже предоставляет множество встроенных директив, с которыми вы уже знакомы, напримерv-on
,v-model
так же какv-bind
. и мы также можем создатьнастроитьДирективы для добавления какого-либо поведения к элементу — это именно то, чего мы хотим добиться.
Определение пользовательской директивы очень похоже на определение компонента; объект создается с помощью набора методов, соответствующих определенному хуку цикла объявления, и добавляется в глобальный код путем выполнения:
Vue.directive('custom-directive', customDirective);
или добавив внутри компонентаdirectives
object для локального добавления директив в компонент.
const myComponent = {
directives: {
'custom-directive': customDirective,
}
}
Ловушка директивы Vue
Директивы Vue имеют хуки для следующего, которые можно использовать для настройки поведения. Хотя можно использовать эти хуки в одной директиве, обычно в директиве используются только один или два таких хука. Эти хуки жизненного цикла являются необязательными, поэтому при их использовании выбирайте то, что вам нужно.
-
bind(el, binding, vnode)
: вызывается только один раз, когда директива впервые привязывается к элементу. Это хорошее место для единовременной настройки, но будьте осторожны, даже если элемент существует, он может быть не смонтирован в документе. -
inserted(el, binding, vnode)
: вызывается, когда связанный элемент вставляется в родительский узел. Это также не гарантирует, что элемент существует в документе, но означает, что если вам нужно обратиться к родительскому узлу, вы можете это сделать. -
update(el, binding, vnode, oldVnode)
: вызывается при обновлении VNode содержащего компонента, но нет гарантии, что другие дочерние элементы компонента будут обновлены, и значение этой директивы может измениться или не измениться. (можно сравнитьbinding.value
а такжеbinding.oldValue
для оптимизации ненужных обновлений). -
componentUpdated(el, binding, vnode, oldValue)
а такжеupdate
Очень похоже, но этот хук вызывается после того, как все дочерние элементы, содержащиеся в текущем узле, были обновлены. Если поведение вашей директивы зависит от пиров текущего узла (например,v-else
), тогда вы можете использовать этот хук вместоupdate
. -
unbind(el, binding, vnode)
а такжеbind
Точно так же этот хук срабатывает один раз тогда и только тогда, когда директива не привязана к элементу. Это отличное место для выполнения всего кода удаления.
Параметры этих функций следующие:
-
el
: элемент, к которому привязана директива; -
binding
: объект, содержащий информацию о параметрах и значениях команды; -
vnode
: виртуальный узел соответствующего элемента, созданный компилятором Vue; -
oldValue
: виртуальный узел до обновления будет использоваться только вupdate
а такжеcomponentUpdated
передается.
Дополнительную информацию можно найти наРуководство по пользовательским директивам Vueнайти в.
Ввести библиотеку Lozad в пользовательскую директиву
Давайте посмотрим на один с использованиемlozadПример введения: библиотека lozad — это библиотека отложенной загрузки, основанная на Intersection Observer API. Использовать API lozad легко: пройтиdata-src
заменить картинкуsrc
атрибут и передать селектор или элемент вlozad()
метод, а затем вызовите методobserve
Вот и все.
const el = document.querySelector('img');
const observer = lozad(el);
observer.observe();
Мы можем передать команду вbind
Хуки просты в реализации.
const lozadDirective = {
bind(el, binding) {
el.setAttribute('data-src', binding.value) ;
let observer = lozad(el);
observer.observe();
}
}
Vue.directive('lozad', lozadDirective)
При этом мы можем просто передать исходную строку вv-lozad
команда для преобразования изображения в ленивую загрузку:
<img v-lozad="'https://placekitten.com/100/100'" />
Этот фрагмент кода можно найти вCodePenПосмотреть в: см. Smashing Magazine (@smashing-magazine) этого фрагмента кода:Интеграция с Vue: директива Lozad, которая устанавливает только привязку.
Мы еще не закончили! Хотя это работает при начальной загрузке, будет ли Vue динамически изменять привязку, если значение исходной строки является динамическим? Это можно вызвать в CodePen выше, нажав кнопку «Поменять местами». Если мы реализуем только привязку, то когда нам нужно динамически изменить исходную строку,data-src
а такжеsrc
не будет изменяться динамически.
Для достижения этого эффекта необходимо увеличитьupdated
крюк:
const lozadDirective = {
bind(el, binding) {
el.setAttribute('data-src', binding.value) ;
let observer = lozad(el);
observer.observe();
},
update(el, binding) {
if (binding.oldValue !== binding.value) {
el.setAttribute('data-src', binding.value);
if (el.getAttribute('data-loaded') === 'true') {
el.setAttribute('src', binding.value);
}
}
}
}
Просто есть это! Наша директива теперь может запускать lozad при обновлении Vue. Окончательную версию можно просмотреть с помощью следующего фрагмента кода: см.CodePenНад Разрушительным Журналом (@smashing-magazine) этого фрагмента кода:Vue Integration: Директива Лозада с набором обновления.
Компоненты и библиотеки компонентов
Самый сложный сторонний JavaScript, который необходимо интегрировать, — это полный компонент или библиотека компонентов, которая должна контролировать всю область DOM. Эти инструменты хотят иметь возможность создавать, уничтожать и контролировать DOM.
Для этих библиотек лучший способ интегрировать их в Vue — это обернуть их в выделенный компонент и активно использовать функции жизненного цикла Vue для управления инициализацией, передачей данных, обработкой событий и обратными вызовами.
Наша цель — полностью абстрагироваться от деталей сторонних библиотек, чтобы другой код Vue мог взаимодействовать с нашими обернутыми компонентами так же, как с нативными компонентами.
Хуки жизненного цикла компонентов
Чтобы обернуть более сложные компоненты, нам нужно понять все хуки жизненного цикла, доступные в компоненте, эти хуки:
-
beforeCreate()
Вызывается перед созданием экземпляра компонента, используется редко, но полезен, если вам нужно что-то вроде интеграционного анализа. -
created()
Вызывается после создания экземпляра компонента, но до его монтирования в DOM, полезно, когда нам нужна однократная, независимая от DOM работа по настройке. -
beforeMount()
Вызывается перед монтированием компонента в DOM. (также редко используется) -
mounted()
Вызывается после монтирования компонента в DOM. Это наиболее часто используемая функция ловушки для библиотек, которым необходимо полагаться на DOM или предполагать, что DOM существует при вызове. -
beforeUpdate()
Вызывается, когда Vue собирается обновить шаблон рендеринга, используется редко, но одинаково полезен при интеграции аналитики. -
updated()
Вызывается, когда Vue закончил обновление шаблона. Подходит для любого процесса, который необходимо воссоздать. -
beforeDestroy()
Вызывается перед тем, как Vue выгрузит компонент. Это идеальное место, если нам нужно вызвать какие-либо методы уничтожения или выгрузки для сторонних компонентов. -
destroyed()
Вызывается, когда Vue закончил размонтирование компонента.
Оберните один компонент за раз, одна функция хука
Давайте посмотрим на популярныеjquery-multiselectбиблиотека. На Vue уже написано много компонентов с множественным выбором, но этот пример представляет собой хорошее сочетание: достаточно сложное, чтобы быть интересным, и достаточно простое, чтобы его можно было понять.
Чтобы реализовать оболочку стороннего компонента, вам сначала нужно использоватьmounted
крюк. Поскольку сторонние компоненты могут ожидать, что DOM существует до вызова сторонней библиотеки, сторонние компоненты необходимо инициализировать здесь.
Например, когда мы начали оборачивать jquery-multiselect, мы бы написали следующий код:
mounted() {
$(this.$el).multiselect();
}
ты сможешьCodePenОзнакомьтесь со следующим фрагментом кода в: See Smashing Magazine (@smashing-magazine) этого фрагмента кода:Интеграция с Vue: простая оболочка с множественным выбором.
Это выглядит довольно хорошо. Если нам нужно вызвать определенные методы при выгрузке, нам нужно добавитьbeforeDestroy
ловушку, но в этой библиотеке нет метода удаления, который нам нужно вызвать.
Обратный вызов преобразуется в событие
Следующее, что мы хотим сделать с этой библиотекой, — предоставить возможность уведомлять приложение Vue, когда пользователь выбирает параметр. библиотека jquery-multiselect черезafterSelect
так же какafterDeselect
функция для выполнения обратных вызовов, но это не подходит для Vue, мы позволяем этим обратным вызовам запускать события внутри. Мы можем просто обернуть функцию обратного вызова:
mounted() {
$(this.$el).multiSelect({
afterSelect: (values) => this.$emit('select', values),
afterDeselect: (values) => this.$emit('deselect', values)
});
}
Однако, если мы вставим регистратор в прослушиватель событий, мы обнаружим, что реальный Vue-подобный интерфейс не предоставляется. Каждый раз, когда мы выбираем или отменяем выбор, мы получаем список, значение которого изменилось, но чтобы быть более совместимым с Vue, мы должны сделать так, чтобы список запускал событие изменения.
У нас нет способа устанавливать значения, как Vue. Мы должны рассмотреть возможность использования этих инструментов, которые достигают чего-то вродеv-model
метод, такой какСобственный элемент выбора, предоставляемый Vue.
выполнитьv-model
Реализовать на компонентеv-model
, нам нужно реализовать две вещи: получитьvalue
свойство и установите для соответствующей опции значение Checked, а затем сработайте, когда опция будет изменена.input
событие и передать в новый массив.
Здесь нужно обработать четыре части: конкретное начальное значение, передать все изменения родительскому компоненту, обработать все изменения, полученные от внешних компонентов, и, наконец, обработать все изменения содержимого слота (список опций).
Давайте реализуем их один за другим.
- Инициализировать настройки через свойства
Во-первых, нам нужно позволить компоненту получить свойство, а когда мы его инициализируем, сообщить компоненту множественного выбора, какой из них выбрать.
export default {
props: {
value: Array,
default: [],
},
mounted() {
$(this.$el).multiSelect();
$(this.$el).multiSelect('select', this.value);
},
}
- Обработка внутренних изменений
Для обработки изменений, вызванных взаимодействием пользователя с элементом множественного выбора, мы можем вернуться к обратным вызовам, которые мы обсуждали ранее, но на этот раз все не так просто. Вместо того, чтобы просто передавать полученное значение, нам нужно учитывать исходное значение и то, что изменилось.
mounted() {
$(this.$el).multiSelect({
afterSelect: (values) => this.$emit('input', [...new Set(this.value.concat(values))]),
afterDeselect: (values) => this.$emit('input', this.value.filter(x => !values.includes(x))),
});
$(this.$el).multiSelect('select', this.value);
},
Эти функции обратного вызова кажутся немного громоздкими, поэтому давайте разберем их.
afterSelect
Метод объединяет только что выбранное значение с нашим существующим значением, но чтобы убедиться, что нет дубликатов, мы делаем это с набором (гарантированная уникальность). Затем деструктурируйте его, преобразуйте в массив.
afterDeselect
Метод просто отфильтровывает значение, которое в настоящее время не выбрано, из списка, чтобы передать новый список.
- Обработка обновлений, запускаемых извне
Что нам нужно сделать дальше, так этоvalue
Когда свойство будет обновлено, измените выбранное значение в пользовательском интерфейсе. Это включает в себя размещение свойствдекларативныйДоступно изменение перехода на множественный выборнеобходимоРазнообразие.最简单的方式是在value
Используйте наблюдателей на свойствах.
watch:
// don’t actually use this version. See why below
value() {
$(this.$el).multiselect('select', this.value);
}
}
Однако есть проблема! Поскольку запуск select также вызовет запуск нашегоonSelect
обработчик, таким образом используя обновленное значение. Если бы мы использовали такой простой наблюдатель, то застряли бы в бесконечном цикле.
К счастью для нас, Vue дает нам доступ как к старым, так и к новым значениям. Мы можем сравнивать и инициировать выбор только при изменении значения. Сравнение массивов может быть сложным в JavaScript, но для этого примера мы можем передатьJSON.stringify
сравнивать напрямую, так как наш массив на самом деле проще (поскольку объектов нет). Принимая во внимание, что нам также нужно отменить выбор опции, которая была удалена, наш окончательный наблюдатель выглядит следующим образом:
watch: {
value(newValue, oldValue) {
if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
$(this.$el).multiSelect('deselect_all');
$(this.$el).multiSelect('select', this.value);
}
}
},
- Показать внешнюю таблицу обновлений в слоте
У нас есть еще одна вещь, о которой нужно позаботиться: наш элемент множественного выбора использует значение параметра, переданное через слот. Если набор параметров изменится, нам нужно сообщить элементу множественного выбора об обновлении, иначе новые параметры не будут отображаться. К счастью, у нас есть простой API в обновлении компонента multiselect (refresh
функция и очевидный хук Vue). Это позволяет легко справиться с этой ситуацией.
updated() {
$(this.$el).multiSelect('refresh');
},
ты сможешьCodePenОзнакомьтесь с финальной версией этого компонента: см. Smashing Magazine (@smashing-magazine) этого фрагмента кода:Интеграция с Vue: обертка multiselect с v-моделью.
Недостатки и другие соображения
Теперь, когда мы увидели, как легко использовать сторонний JavaScript в Vue, пришло время обсудить недостатки этих подходов и когда их использовать.
влияние на производительность
Использование во ВьюНе делайтеОдним из основных недостатков стороннего JavaScript, написанного для Vue, является производительность, особенно при ссылках на компоненты, созданные с помощью других фреймворков и библиотек компонентов. Прежде чем пользователь сможет взаимодействовать с нашим приложением, браузеру потребуется загрузить и проанализировать дополнительный код JavaScript.
Например, если вы используете вышеуказанный компонент множественного выбора, вам необходимо импортировать весь код jQuery. Это заставляет пользователей загружать в два раза больше кода фреймворка, чем сейчас, только для такого компонента! Очевидно, что лучше использовать нативные компоненты Vue.js.
Кроме того, когда API, используемый третьими сторонами, сильно отличается от того, как объявлен Vue, вы можете обнаружить, что вашей программе требуется много дополнительного времени на выполнение. Кроме того, используя пример множественного выбора, нам приходилось обновлять весь компонент каждый раз, когда мы меняли значение слота (нужно просматривать много DOM), в то время как нативные компоненты Vue могут сделать обновления более эффективными с помощью виртуального DOM.
когда использовать
Использование сторонних библиотек может значительно сократить время разработки и часто означает, что вы можете использовать хорошо поддерживаемые и протестированные компоненты, которые вы еще не смогли собрать.
Для библиотек, которые не имеют больших зависимостей, особенно тех, которые не выполняют много манипуляций с DOM, нет причин отказываться от более общей библиотеки, чтобы использовать библиотеку, специфичную для Vue. Поскольку Vue может легко импортировать другой сторонний JavaScript, вам нужно только выбрать наиболее подходящий инструмент в соответствии с вашими функциональными потребностями и потребностями в производительности, и нет необходимости уделять особое внимание библиотекам, специфичным для Vue.
Для более широкой структуры компонентов существуют три основные ситуации, когда ее необходимо ввести:
- Прототип проекта: В этом случае потребность в скорости итерации намного превышает производительность пользователя; просто используйте то, что сделает вас более продуктивным.
- Миграция существующих сайтов: Если вам нужно перенести существующий сайт на Vue, вы можете использовать Vue, чтобы изящно обернуть ваши существующие вещи, чтобы вы могли постепенно извлекать старый код, не переписывая его по-крупному.
- Когда функциональность компонента Vue еще недоступна: Если вам нужно выполнить определенные или сложные требования, существует поддержка сторонних библиотек, но Vue еще не имеет определенных компонентов, обязательно рассмотрите возможность включения существующей библиотеки в Vue.
Некоторые существующие примеры
Первые два режима широко используются в экосистеме с открытым исходным кодом, поэтому есть много примеров, на которые можно ссылаться. Поскольку обертывание всего компонента является скорее временным решением/миграцией, мы не смогли найти столько внешних примеров, но есть некоторые существующие, которые я использовал по запросу клиента. Вот несколько простых примеров трех режимов:
- Vue-momentСодержит библиотеку moment.js и предоставляет серию фильтров Vue;
- Awesome-maskОбертывает библиотеку vanilla-masker и предоставляет инструкции по фильтрации ввода;
- Vue2-foundationОборачивает компоненты ZURB Foundation внутри компонентов Vue.
В заключение
Популярность Vue.js не собирается снижаться, а прогрессивная стратегия фреймворка завоевала большое доверие. Инкрементная стратегия означает, что люди могут постепенно приступать к использованию без необходимости масштабного переписывания.
Как видим, эта эволюция идет и в другом направлении. Точно так же, как вы можете встраивать Vue в другие приложения, вы также можете встраивать другие библиотеки внутрь Vue.
Нужна какая-то функциональность, которая еще не перенесена в компоненты Vue? Втяните его, заверните, и вы обнаружите, что оно стоит своих денег.
Дальнейшее чтение на SmashingMag:
- Replacing jQuery With Vue.js: No Build Step Necessary by Sarah Drasner
- Creating Custom Inputs With Vue.js by Joseph Zimmerman
- Hit The Ground Running With Vue.js And Firestore by Lukas van Driel
- Serverless Functions And Vue.js by Sarah Drasner (Video, SmashingConf NYC 2018)
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,товар,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.