目次
はじめに
高さ可変のMasonryを作る事になりました。
加えてカテゴリーでフィルターできるようにして欲しいとのことで、目ぼしいMasonryライブラリが見つからず、やむを得ず一部自作することにしました。
フィルター付きのリスト部分をVue.jsで作り、MasonryをjQueryに担当させることにしました。
全部Vue.jsにしたかったのですが、高さが可変という条件があるので、Vue.jsのみで対応ができませんでした。
Vue.jsは事前に高さを取得することができませんからね。
そこでjQueryを使って、Vue.jsのマウント後にMasonryレイアウトすることにしました。
【動画サイズ:1.8MB】
環境
この記事は、以下の管理人の検証環境にて記事にしています。
| vue.js | 2.6.10 |
| jQuery | 1.11.0 |
| waterfall-ligh | 1.3.1 |
導入
管理人が行った、動作確認サンプルを実装するために、以下の手順でソースコードを導入していきます。
このサンプルでは、フィルター付きのMasonryレイアウトを実装します。
step
1ライブラリの呼び出し
今回はサンプルのデザイン用にBootstrapを使用します。
Masonryレイアウトは、waterfall-light というjQueryのライブラリを使用します。
<!-- Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <!-- Vue.js--> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script> <!-- jQuery --> <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script> <script src="https://code.jquery.com/jquery-migrate-1.2.1.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/waterfall-light.min.js"></script>
step
2JavaScript
mountedとupdated時にMasonryレイアウトを行わせます。
mountedは、マウントしてすぐのタイミングでMasonryレイアウトにします。
updatedは、リストの更新をした時に、再度Masonryレイアウトさせます。
new Vue({
el: '#app',
data: {
isShow: false,
checked: [],
category: [
{no:1, title:'category:1'},
{no:2, title:'category:2'},
{no:3, title:'category:3'},
{no:4, title:'category:4'},
{no:5, title:'category:5'},
],
items: [
{id:1, category:1, text:'Some quick example text to bue bulk of the cards content.'},
{id:2, category:5, text:'Some quick example text to build on the card title and make up tntent.'},
{id:3, category:2, text:'Some quick example text to build on the card title and mak title and make up title and make up title and make up e up the bulk of the cards content.'},
{id:4, category:4, text:'Some quick example text to build on the card title and makthe cards content.'},
{id:5, category:2, text:'Some quick example text ulk of the cards content.'},
{id:6, category:3, text:'Some quick example text to build on the card title and make up the bulk of the c title and make up title and make up title and make up ards content.'},
{id:7, category:4, text:'Some quick example text to build on the card title and make u title and make up title and make up p the bulk of the cards content.'},
{id:8, category:3, text:'Some quick example text to build on the card title and make up the bulk of the cards content.'},
{id:9, category:1, text:'Some quick example text to build on the card title and make up the bulk of the cards content.'},
{id:10, category:4, text:'Some quick example text to build on the card title and make up the bulk of th title and make up e cards content.'},
{id:11, category:3, text:'Some quick example text to build on the card title and make up the bulk of the cards content.'},
{id:12, category:2, text:'Some quick example text to build on the card title and make up th title and make up title and make up title and make up e bulk of the cards content.'},
]
},
computed: {
getItems: function(){
let self = this;
return this.items.filter(function(item){
return (self.checked.length === 0 || self.checked.indexOf(item.category) !== -1);
});
}
},
mounted:function() {
let self = this;
$('#box').waterfall({
gap: 10,
gridWidth: [0,400,600,800,1200],
refresh: 0
});
setTimeout(function(){
self.isShow = true;
},0);
},
updated:function(){
$('#box').waterfall({
gap: 10,
gridWidth: [0,400,600,800,1200],
refresh: 500
});
}
});
step
3HTML
BootstrapベースのClassを設定していきます。
v-show="isShow" を設定して、jQueryのMasonryが起動するまでの、一瞬だけ映るぐちゃぐちゃなレイアウトを隠しておきます。
<main id="app" class="flex-shrink-0">
<div class="container">
<div class="row mt-4 mb-4 justify-content-lg-center bg-light p-2 rounded">
<div class="text-center p-4">
<div class="form-check form-check-inline" v-for="item in category">
<input class="form-check-input" type="checkbox" :value="item.no" v-model="checked" >
<label class="form-check-label" for="flexCheckDefault"> {{item.title}}</label>
</div>
</div>
</div>
<div id="box" v-show="isShow">
<div v-for="(item, index) in getItems" class="card" ref="waterfall" style="width: 180px;">
<svg class="bd-placeholder-img card-img-top" width="100%" height="180" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#868e96"></rect><text x="50%" y="50%" fill="#dee2e6" dy=".3em">Image cap {{item.id}}</text></svg>
<div class="card-body">
<h5 class="card-title">Card title {{item.id}}</h5>
<p class="card-text">category:{{item.category}}</p>
<p class="card-text">{{item.text}}</p>
</div>
</div>
</div>
</div>
</main>
デモ
See the Pen Vue.jsとjQueryでフィルター付きのウォーターフォールレイアウトを実装する by カバの樹 (@kabanoki) on CodePen.dark