vue.js

Vue.jsのView ModelにjQueryプラグインを統合する

More than 1 year has passed since last update.


はじめに

Vue.jsいいですよ、Vue.js。

シンプルでパワフルです。

AngularJSと較べて学習コストが半端なく低い。

直感的にDOM操作を行えます。

同じくMVVMを基盤にするKnockoutJSよりもシンプルに

書けます。

日本語の情報が充実してきているので、まだまだ

ブレイクする可能性が多分にあると思っています。

公式サイトのガイド・APIリファレンスが有志の方のおかげで

日本語にも対応しているので、クライアントJSにあかるい方が

いれば、即採用可能な状況になってきています。


View ModelへのjQueryプラグイン組込み

1.0.xまでは、jQueryプラグインをディレクティブとしてラップし、

jQueryプラグインを適用する要素にディレクティブを独自属性と

して追加することでView ModelにスマートにjQueryプラグイン

を統合できます。

2.0.xからは、jQueryプラグインを適用する要素をコンポーネント

としてラップし、jQueryプラグインを適用する要素のかわりに

コンポーネントを独自タグとして利用することで、View Modelに

スマートにjQueryプラグインを統合できます。

1.0.xでは、ディレクティブではなくコンポーネントとしてラップする

ことも可能です。

2.0.xでも、、jQueryプラグインをディレクティブとしてラップし、

jQueryプラグインを適用する要素にディレクティブを独自属性と

して追加することでView ModelにスマートにjQueryプラグイン

を統合することは可能です。v2.xはv1.xとはディレクティブetc

の挙動が異なりますので、注意が必要です。

Vue.js 2.0でtwoWayなカスタムディレクティブを実装する方法

http://d.hatena.ne.jp/chi-bd/20161022/1477129270

上記手法を取らず、View Modelの外側から直接

jQueryプラグインを適用することも可能ですが、

その場合、v-repeat等で動的に追加したDOMノード等に

対してjQueryプラグインを適用できません。


組込み例

bootstrap-tokenfieldを上記の手法でView Modelに

組み込んでいます。

bootstrap-tokenfield

http://sliptree.github.io/bootstrap-tokenfield/

1.View Modelへの単純な組込み

v2.0

[component]

http://jsdo.it/asip2k25/6yES

[directive]

http://jsdo.it/asip2k25/mUHn

v1.0

<div id="form">

<input id="text-content" v-tokenfield="content3" type="text">
<p>
<button id="btn-change" v-on:click="on_click">Change Content by JS</button>
</p>
<p>
<button id="btn-log" v-on:click="on_click2">Check VM.content</button>
</p>
<p>{{content2}}</p>
</div>

v0.10,0.11

<div id="form">

<input id="text-content" v-tokenfield="content3" type="text">
<p>
<button id="btn-change" v-on="click: on_click()">Change Content by JS</button>
</p>
<p>
<button id="btn-log" v-on="click: on_click2()">Check VM.content</button>
</p>
<p>{{content2}}</p>
</div>

v1.0, v1.1

$(function(){

Vue.directive('tokenfield',{
twoWay: true,
bind: function(value){
var self = this;
$(this.el).tokenfield();
$(this.el).on('tokenfield:editedtoken',function (e) {
self.set($(this).tokenfield("getTokensList", ','));
}).on('tokenfield:createdtoken', function(e){
self.set($(this).tokenfield("getTokensList", ','));
}).on('tokenfield:removedtoken', function(e){
self.set($(this).tokenfield("getTokensList", ','));
});
},
update: function(value){
$(this.el).tokenfield('setTokens',value);
}
});

var vm = new Vue({
el: '#form',
data: {
content2: '',
content3: ''
},
methods: {
on_click: function () {
this.content3 = 'hi';
},
on_click2: function () {
this.content2 = this.content3;
}
}
});

});

v1.0: http://jsdo.it/asip2k25/ogZC

v0.11: http://jsdo.it/asip2k25/uiyv

v0.10

$(function(){

Vue.directive('tokenfield',{
bind: function(value){
var self = this;
$(this.el).tokenfield();
$(this.el).on('tokenfield:editedtoken',function (e) {
self.vm.$set(self.key,$(this).tokenfield("getTokensList", ','));
}).on('tokenfield:createdtoken', function(e){
self.vm.$set(self.key,$(this).tokenfield("getTokensList", ','));
}).on('tokenfield:removedtoken', function(e){
self.vm.$set(self.key,$(this).tokenfield("getTokensList", ','));
});
},
update: function(value){
$(this.el).tokenfield('setTokens',value);
}
});

var vm = new Vue({
el: '#form',
data: {
content2: '',
content3: ''
},
methods: {
on_click: function () {
this.content3 = 'hi';
},
on_click2: function () {
this.content2 = this.content3;
}
}
});

});

http://jsdo.it/asip2k25/uH7M

2.v-repeatのあるView Modelへの組込み

v2.0

[component]

http://jsdo.it/asip2k25/IFV6

[directive+component]

http://jsdo.it/asip2k25/28zg

v1.0

<div id="form">

<div v-for="row in contents">
<input type="text" class="tag-editor" v-tokenfield="row.content3" >
<p>
<button id="btn-log" v-on:click="on_click2(row)">Check VM.content</button>
</p>
<p>{{row.content2}}</p>
</div>
<p>
<button id="btn-change" v-on:click="on_click">Add Content by JS</button>
</p>
</div>
</div>

v1.0,0.11

$(function(){  

Vue.directive('tokenfield',{
twoWay: true,
bind: function(value){
var self = this;
$(this.el).tokenfield();
$(this.el).on('tokenfield:editedtoken',function (e) {
self.set($(this).tokenfield("getTokensList", ','));
}).on('tokenfield:createdtoken', function(e){
self.set($(this).tokenfield("getTokensList", ','));
}).on('tokenfield:removedtoken', function(e){
self.set($(this).tokenfield("getTokensList", ','));
});
},
update: function(value){
$(this.el).tokenfield('setTokens',value);
}
});

var vm = new Vue({
el: '#form',
data: {
contents: [
{
content2: '',
content3: 'wi'
},
{
content2: '',
content3: 'fi'
}
]
},
methods: {
on_click: function () {
vm.contents.push({
content2:'',
content3:''
});
},
on_click2: function(row){
row.content2 = row.content3;
}
}
});

});

v1.0: http://jsdo.it/asip2k25/2emh

v0.11: http://jsdo.it/asip2k25/6cjc

$(function(){  

Vue.directive('tokenfield',{
bind: function(value){
var self = this;
$(this.el).tokenfield();
$(this.el).on('tokenfield:editedtoken',function (e) {
self.vm.$set(self.key,$(this).tokenfield("getTokensList", ','))
}).on('tokenfield:createdtoken', function(e){
self.vm.$set(self.key,$(this).tokenfield("getTokensList", ','))
}).on('tokenfield:removedtoken', function(e){
self.vm.$set(self.key,$(this).tokenfield("getTokensList", ','))
});
},
update: function(value){
$(this.el).tokenfield('setTokens',value);
}
});

var vm = new Vue({
el: '#form',
data: {
contents: [
{
content2: '',
content3: 'wi'
},
{
content2: '',
content3: 'fi'
}
]
},
methods: {
on_click: function () {
vm.contents.push({
content2:'',
content3:''
});
},
on_click2: function (row) {
row.content2 = row.content3;
}
}
});

});

http://jsdo.it/asip2k25/itmx


最後に

組込み例の詳しい解説は書きません。

簡単なので、頑張って?理解してください。

v2.0に対応しました。v2.0用のコードでは、ディレクティブから

コンポーネントによるラップに変更しています。

組込み例にv2.0対応ディレクティブ版を追記しました。

v-repeatのあるView Modelへの組込みでは、ディレクティブを

コンポーネントでラップしています。

レッツ・トライ、Vue.js。