Не стоит использовать jQuery и Vue.js в одном интерфейсе. Не делай этого, если можешь этого избежать.
Но вы, вероятно, читаете это не потому, что хотите использовать jQuery и Vue вместе, а потому, что должны это делать . Возможно, клиент настаивает на использовании определенного плагина jQuery, который вы не успеете переписать для Vue.
Если вы внимательно относитесь к тому, как вы это делаете, вы можете безопасно использовать jQuery и Vue вместе. В этой статье я собираюсь продемонстрировать, как добавить плагин jQuery UI Datepicker в проект Vue.
И чтобы немного похвастаться, я даже собираюсь отправить данные между этим плагином jQuery и Vue!
Посмотрите, как это работает в этом JS Bin .
jQuery UI Datepicker
Проблема с использованием jQuery и Vue вместе
Почему это потенциально опасно?
Vue — это завистливая библиотека в том смысле, что вы должны позволить ей полностью владеть патчем DOM, который вы ей даете (определяется тем, что вы передаете el
). Если jQuery вносит изменения в элемент, которым управляет Vue, скажем, добавляет к чему-либо класс, Vue не будет знать об этом изменении и собирается пойти дальше и перезаписать его в следующем цикле обновления.
Решение: используйте компонент в качестве оболочки
Зная, что Vue и jQuery никогда не собираются делить часть DOM, мы должны сказать Vue оцепить область и передать ее jQuery.
Использование компонента для переноса плагина jQuery выглядит следующим образом:
- Мы можем использовать ловушки жизненного цикла для настройки и удаления кода jQuery.
- Мы можем использовать интерфейс компонента для связи с остальной частью приложения Vue через реквизиты и события.
- Компоненты могут отказаться от обновления с
v-once
Настройка jQuery UI Datepicker
Очевидно, что вам нужно сначала включить библиотеки jQuery и jQuery UI в ваш проект. После того, как они у вас есть, DatePicker просто требуется input
элемент для присоединения к:
JavaScript
1
Date: <input id="datepicker"/>
Затем его можно создать, выбрав его и вызвав метод:
JavaScript
xxxxxxxxxx
1
$('#datepicker').datepicker();
Компонент Datepicker
Чтобы сделать наш компонент datepicker, шаблон будет следующим input
:
JavaScript
xxxxxxxxxx
1
Vue.component('date-picker', function() {
2
template: '<input/>'
3
});
4
new Vue({
6
el: '#app'
7
});
8
<div id="app">
10
Date: <date-picker></date-picker>
11
</div>
Примечание. Этот компонент должен быть не более чем оболочкой для плагина. Не испытывайте судьбу и не сообщайте ему какие-либо свойства данных или используйте директивы или слоты.
Создание виджета
Вместо того, чтобы давать наш input
идентификатор и выбирать его, мы можем использовать его this.$el
, так как каждый компонент может получить доступ к своему собственному корневому узлу. Корневой узел, конечно же, будет input
.
Затем мы можем обернуть опорный узел в селектор JQuery , чтобы получить доступ к datepicker
методу, то есть $(this.$el).datepicker()
.
Обратите внимание, что мы используем mounted
хук жизненного цикла, поскольку this.$el
он не определен, пока компонент не смонтирован.
JavaScript
xxxxxxxxxx
1
Vue.component('date-picker', function() {
2
template: '<input/>',
3
mounted: function() {
4
$(this.$el).datepicker();
5
}
6
});
Срывать
Чтобы демонтировать средство выбора даты, мы можем использовать аналогичный подход и использовать хук жизненного цикла. Обратите внимание, что мы должны использовать, beforeDestroy
чтобы убедиться, что наш input
объект все еще находится в DOM и поэтому может быть выбран (он не определен в destroy
хуке).
JavaScript
xxxxxxxxxx
1
Vue.component('date-picker', {
2
template: '<input/>',
3
mounted: function() {
4
$(this.$el).datepicker();
5
},
6
beforeDestroy: function() {
7
$(this.$el).datepicker('hide').datepicker('destroy');
8
}
9
});
Pass Config с реквизитом
Чтобы сделать наш компонент многоразовым, было бы неплохо разрешить настраиваемую конфигурацию, например указание формата даты с помощью свойства конфигурации dateFormat
. Мы можем сделать это с props
:
JavaScript
xxxxxxxxxx
1
Vue.component('date-picker', {
2
template: '<input/>',
3
props: [ 'dateFormat' ],
4
mounted: function() {
5
$(this.$el).datepicker({
6
dateFormat: this.dateFormat
7
});
8
},
9
beforeDestroy: function() { }
10
});
11
<div id="app">
13
<date-picker date-format="yy-mm-dd"></date-picker>
14
</div>
Позволяя jQuery обрабатывать обновления
Допустим, вместо того, чтобы передавать свою dateFormat
опору в виде строки, вы сделали ее data
свойством корневого экземпляра, то есть:
JavaScript
xxxxxxxxxx
1
var vm = new Vue({
2
data: {
3
4
dateFormat: 'yy-mm-dd'
5
}
6
});
7
<div id="app">
9
<date-picker date-format="dateFormat"></date-picker>
10
</div>
Это будет означать, dateFormat
что это будет свойство реактивных данных. Вы можете обновить его значение в какой-то момент жизни вашего приложения:
JavaScript
xxxxxxxxxx
1
// change the date format to something new
2
vm.dateFormat = 'yy-dd-mm';
Так как dateFormat
реквизит является зависимостью mounted
хука компонента datepicker, его обновление вызовет повторную визуализацию компонента. Это не было бы круто. jQuery уже настроил ваш DatePicker на input
и теперь управляет им с помощью своих собственных пользовательских классов и прослушивателей событий. Обновление компонента приведет к input
замене, и, таким образом, настройки jQuery будут немедленно сброшены.
Нам нужно сделать так, чтобы реактивные данные не могли вызвать обновление в этом компоненте.
v-раз
v-once
Директива используется для кэширования компонента в том случае, если она имеет много статического контента. Это фактически делает компонент отказаться от обновления.
Это на самом деле идеально подходит для использования с нашим компонентом плагина, так как Vue будет эффективно игнорировать его. Это дает нам некоторую уверенность в том, что jQuery будет беспрепятственно контролировать этот элемент в течение жизненного цикла приложения.
HTML
xxxxxxxxxx
1
<div id="app">
2
<date-picker date-format="yy-mm-dd" v-once></date-picker>
3
</div>
Передача данных из jQuery в Vue
Было бы довольно бесполезно иметь средство выбора даты, если бы мы не могли получить выбранную дату и использовать ее где-то еще в приложении. Давайте сделаем так, чтобы после выбора значения оно выводилось на страницу.
Мы начнем с предоставления нашему корневому экземпляру date
свойства:
JavaScript
xxxxxxxxxx
1
new Vue({
2
el: '#app',
3
data: {
4
date: null
5
}
6
});
7
<div id="app">
9
<date-picker date-format="yy-mm-dd" v-once></date-picker>
10
<p>{{ date }}</p>
11
</div>
Виджет выбора onSelect
даты имеет обратный вызов, который вызывается при выборе даты. Затем мы можем использовать наш компонент для выдачи этой даты через пользовательское событие:
JavaScript
xxxxxxxxxx
1
mounted: function() {
2
var self = this;
3
$(this.$el).datepicker({
4
dateFormat: this.dateFormat,
5
onSelect: function(date) {
6
self.$emit('update-date', date);
7
}
8
});
9
}
Наш корневой экземпляр может прослушать пользовательское событие и получить новую дату:
JavaScript
xxxxxxxxxx
1
<div id="app">
2
<date-picker @update-date="updateDate" date-format="yy-mm-dd" v-once></date-picker>
3
<p>{{ date }}</p>
4
</div>
5
6
new Vue({
7
el: '#app',
8
data: {
9
date: null
10
},
11
methods: {
12
updateDate: function(date) {
13
this.date = date;
14
}
15
}
16
});
Благодаря этому Stack Overflow отвечает за вдохновение.