Cách sử dụng các plugins của Jquery trong ứng dụng VueJS một cách mượt mà
Bài đăng này đã không được cập nhật trong 4 năm
I. Giới thiệu.
Progressive framework là khái niệm khá mới, có thể hiểu thay vì như Full-featured framework hay Monolithic framework cung cấp tất cả mọi thứ cần có để xây dựng app trong một framework duy nhất, thì progresive framework lại chia thành các thành phần nhỏ khác nhau, và ta có thể dần dần lựa chọn các thành phần tham gia vào sao cho phù hợp. Vue.js là một trong số các progressive framework. Phần lõi của Vue.js tập chung chủ yếu vào phần View. Chúng ta có thể sử dụng mỗi lõi của Vue để tạo view hoặc CÓ THỂ cài THÊM các thành phần như vuex để quản lý state trong app hay vue-router cho SPA routing... hoặc là không dùng thêm. Sau đây mình xin giới thiệu 1 trick khá hay mà VueJS có thể làm được đó là:
Cách sử dụng các plugins của Jquery trong ứng dụng VueJS một cách mượt mà.
II. Vấn đề.
Hẳn là khi các bạn làm với các project áp dụng mấy framework kiểu như VueJS này thì một số thư viện cũng chưa hỗ trợ mà vẫn phải dùng thêm các plugins của jQuery đúng không nào?
Bình thường thì nếu bạn làm với ứng dụng Web kiểu Server-Side Rendering thì phần html đã được render ra khi người dùng load trang và chỉ cần áp dụng vài dòng code Javascript với Jquery là chạy ngay. Nhưng với các framework như VueJS thì cấu trúc DOM không được load ngay từ đầu nên ta không thể chạy các plugin của jQuery theo cách thông thường.
Ở đây mình xin demo 1 trường hợp sử dụng plugin select2 của Jquery để chạy trong ứng dụng VueJS.
III. Giải pháp.
Ta sẽ tạo ra 1 component và wrap nó lại.
<script type="text/x-template" id="template-select2">
<select class="vue-select2">
<option v-for="option in options"
:value="option.key"
:selected="option.key=== selected">{{option.value}}</option>
</select>
</script>
<script>
Vue.component('vue-select2', {
template: '#template-select2',
props: ['options', 'selected']
});
</script>
Component này sẽ có 2 props là options là list options để select và selected nếu muốn set 1 option nào đã được select.
Để làm được ta cần phải tìm hiểu 1 chút về life cycle của VueJS nhé.
Như các bạn thấy trong ảnh thì đến đoạn mounted là thời điểm mà Vue render html và replace vào cấu trúc DOM và đây chính là cơ hội để mình có thể chạy plugin select2. Và thời điểm thứ 2 ta cần quan tâm là lúc component chuẩn bị xóa đi khỏi DOM đó là beforeDestroy – đây là thời điểm tốt để các bạn xóa tất cả các sự kiện trên component đó đồng thời hủy select2 chạy trên component đó.
Vue.component('vue-select2', {
template: '#template-select2',
props: ['options', 'selected'],
model: {
prop: 'selected',
event: 'change'
},
mounted: function() {
$(this.$el).select2();
},
beforeDestroy: function() {
$(this.$el).off().select2('destroy');
}
});
Xong rồi đó, component đã có thể chạy được ngay. Nhưng vẫn còn một vấn đề nữa đó là bạn cần phải cập nhật sự thay đổi lên parent component chứ nhỉ. Để làm được điều đó ta bắt sự kiện change của select đó rồi dùng $emit để đẩy sự kiện cho thằng cha.
mounted: function() {
var vm = this;
$(this.$el).select2();
$(this.$el).on('change', function(e) {
vm.$emit('change', vm.$el.value);
});
},
Sau đó ở thằng cha bắt sự kiện @change để cập nhật trạng thái option đã được select (trong demo mình dùng tính kiểu two-way binding để chuyền ngược lại cho thằng cha luôn).
IV. Kết quả.
Xong rồi đó, mình sẽ thêm 1 số tính năng nữa để demo khi thằng cha thêm option hoặc thay đổi option đang được select thì thằng con cũng cập nhật được trạng thái của nó.
html:
<div id="app">
<h1>{{title}}</h1>
<div class="selected">
Selected: {{selected}}
</div>
<div class="select-wrapper">
<vue-select2 :options='select2' v-model="selected"></vue-select2>
</div>
<button type="button" @click="addOption">Add option</button>
<button type="button" @click="randSelect">Select random</button>
</div>
<script type="text/x-template" id="template-select2">
<select class="vue-select2">
<option v-for="option in options"
:value="option.key"
:selected="option.key=== selected">{{option.value}}</option>
</select>
</script>
js:
(function($, Vue) {
Vue.component('vue-select2', {
template: '#template-select2',
props: ['options', 'selected'],
model: {
prop: 'selected',
event: 'change'
},
mounted: function() {
var vm = this;
$(this.$el).select2();
$(this.$el).on('change', function(e) {
vm.$emit('change', vm.$el.value);
});
},
updated: function() {
$(this.$el).val(this.selected);
$(this.$el).trigger('change');
},
beforeDestroy: function() {
$(this.$el).select2('destroy');
}
});
new Vue({
el: '#app',
data: function() {
return {
title: 'Select2 - Vuejs',
selected: 'microsoft',
select2: [
{key: 'apple', value: 'Apple'},
{key: 'google', value: 'Google'},
{key: 'microsoft', value: 'Microsoft'}
]
};
},
methods: {
addOption: function() {
var now = new Date();
this.select2.push({key: now.getTime(), value: now.getTime()});
},
randSelect: function() {
var length = this.select2.length;
var rand = Math.floor(Math.random() * length);
this.selected = this.select2[rand].key;
}
}
});
})(jQuery, Vue);
VI. Kết luận
Mình xin tổng kết lại nhé. Ở đây chỉ có 2 bước quan trọng là:
- Chọn thời điểm component được thêm vào DOM để chạy plugin của Jquery và thời điểm để hủy các sự kiện khi component đó bị hủy đi.
- Tìm sự kiện thay đổi trạng thái của component con để cập nhật lên compnent cha để biết sự thay đổi.
Quá đơn giản phải không nào. Mình cũng bắt đầu thích VueJS vì sự tương thích của nó với các plugin của jQuery vì jQuery nó đã quá to rồi và hệ sinh thái của nó quá lớn nên thời gian này mình vẫn còn phụ thuộc vào nó rất nhiều trong khi các thư viện hỗ trợ cho VueJS còn chưa nhiều. Nói chung là tuyệt cmn vời )
All rights reserved