[vue]用component來包裝jquery的plugin
前言
因為有同事剛開始學習vue,原有網站都是一些jquery或一些jquery的元件,在不想改變很大的外觀之外,又想要達成vue.js的功能,然後我就發現因為不懂vue,所以會用很奇怪的方式來想辦法達成這樣的需求,接下來首先我想說明一下如何讓vue和jquery互動起來。
首先我使用到的是jquery ui的datepicker來示例,其實vue可以很容易的跟jquery配合在一起,我們可以把vue包在document.ready裡面,以確保jquery已經開始運作了
<body>
<link href="https://code.jquery.com/ui/jquery-ui-git.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-git.js"></script>
<script src="https://code.jquery.com/ui/jquery-ui-git.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<input id="date1" type="test" v-model="model.date" />
<input type="button" value="add" @click="submit"/>
</div>
<script>
$(function(){
let vue=new Vue({
el:'#app',
data:{
model:{
date:''
}
},
methods:{
submit:function(){
console.log(this.model.date)
}
},
created:function(){
$('#date1').datepicker()
}
})
})
</script>
</body>
但其實我們只要在created裡面就可以使用jquery了,並不需要使用document.ready包起來,因為vue總會是比原生的生命週期晚一點點
<body>
<link href="https://code.jquery.com/ui/jquery-ui-git.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-git.js"></script>
<script src="https://code.jquery.com/ui/jquery-ui-git.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<input id="date1" type="test" v-model="model.date" />
<input type="button" value="add" @click="submit" />
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
model: {
date: ''
}
},
methods: {
submit: function () {
console.log(this.model.date)
}
},
created: function () {
$('#date1').datepicker()
}
})
</script>
</body>
如果我們想要改成國字的顯示,可能就會改成如下
<body>
<link href="https://code.jquery.com/ui/jquery-ui-git.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-git.js"></script>
<script src="https://code.jquery.com/ui/jquery-ui-git.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<input id="date1" type="test" v-model="model.date" />
<input type="button" value="add" @click="submit" />
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
model: {
date: ''
}
},
methods: {
submit: function () {
console.log(this.model.date)
}
},
created: function () {
var ops = {
dayNames: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
dayNamesMin: ["日", "一", "二", "三", "四", "五", "六"],
monthNames: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
monthNamesShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
prevText: "上月",
nextText: "次月",
weekHeader: "週",
showMonthAfterYear: true,
dateFormat: "yy-mm-dd"
}
$('#date1').datepicker(ops)
}
})
</script>
</body>
但是請想像一下如果我們在很多頁面都用到的話,這些設定值散落各處,一想都會覺得非常的悲慘,如果有一天又要改format的話,這樣子我們不就要全部找出來哪個地方有用到datepicker,全部修改完畢,接著我們來包成元件解決這個問題吧
把jquery ui的plugin包裝成component
<body>
<link href="https://code.jquery.com/ui/jquery-ui-git.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-git.js"></script>
<script src="https://code.jquery.com/ui/jquery-ui-git.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<datepicker v-model="model.date"></datepicker>
<datepicker v-model="model.date1"></datepicker>
<input type="button" value="add" @click="submit" />
</div>
<script>
Vue.component('datepicker', {
props: ['value'],
template: '<input type="text" />',
mounted: function () {
let vm = this
$(this.$el).datepicker({
dayNames: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
dayNamesMin: ["日", "一", "二", "三", "四", "五", "六"],
monthNames: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
monthNamesShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
prevText: "上月",
nextText: "次月",
weekHeader: "週",
showMonthAfterYear: true,
dateFormat: "yy-mm-dd",
onSelect: function (date) {
vm.$emit('input', date) //注意一下裡面的this是jquery對象的部份,所以定義一個vm變數代表vue的實體
}
})
}
})
let vue = new Vue({
el: '#app',
data: {
model: {
date: '',
date1: ''
}
},
methods: {
submit: function () {
console.log(this.model.date)
console.log(this.model.date1)
}
}
})
</script>
</body>
因為我們包成component了,也就不用再需要id的編號了,可以在畫面放多個元件,而且也不用管id是要命名什麼了,此示例有興趣可以至(http://jsbin.com/savigewoli/edit?html,output)改動測試看看。
動態決定config的設定
其實做法取決於設計者的做法,不過這邊的做法只是示例,比較正確來說應該是只有需求改變的時候,再設定特定的props,不要為了預測需求而去浪費時間過度假設,而如果我們設定的細項越細的話,當然就也可以設定還有說明註解寫得更清楚,讓使用者可以了解component有什麼props可以用。
<body>
<link href="https://code.jquery.com/ui/jquery-ui-git.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-git.js"></script>
<script src="https://code.jquery.com/ui/jquery-ui-git.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<datepicker v-model="model.date" :option="option"></datepicker>
<datepicker v-model="model.date1"></datepicker>
<input type="button" value="add" @click="submit" />
</div>
<script>
Vue.component('datepicker', {
props: ['value', 'option'],
template: `<input type="text" />`,
mounted: function () {
var vm = this
let option = {}
if (!this.option) {
option = {
dayNames: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
dayNamesMin: ["日", "一", "二", "三", "四", "五", "六"],
monthNames: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
monthNamesShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
prevText: "上月",
nextText: "次月",
weekHeader: "週",
showMonthAfterYear: true,
dateFormat: "yy-mm-dd",
onSelect: function (date) {
vm.$emit('input', date)
}
}
} else {
option = this.option
option.onSelect=function(date){
vm.$emit('input', date)
}
}
$(this.$el).datepicker(option)
}
})
let vue = new Vue({
el: '#app',
data: {
model: {
date: '',
date1: ''
},
option: {
dateFormat: "mm-dd"
}
},
methods: {
submit: function () {
console.log(this.model.date)
console.log(this.model.date1)
}
}
})
</script>
</body>
可以直接至此測試看看(http://jsbin.com/levewilaqa/edit?html,output)
結論
雖然vue已經提供了非常多的元件了,但是如果你還需要其他原本jquery的,或者你需要操作到dom的方式,來自訂一些元件的話,一定得要包裝成元件,才是比較好和正確的方式,盡量不要在vue的程式碼裡面操作dom對以後維護來說都會更好。