※Vue始めて3か月くらいです。
とりあえず作ったものを下記リンクに置いておく。
ソースは下記に置いておく。JSなら動くのでgithubio便利。
gologius.github.io/test/PULLDOWN_SAMPLE at master · gologius/gologius.github.io · GitHub
リンク先を見るのが面倒な人向けにGIFも貼っておく
なぜ作ったのか
- 3階層、4階層以降に対応したサンプルがなかった(気がする)
- 超適当に調べたが、微妙にやりたいこととずれたものだった(気がする)
- こんなんサイトちゃんと見なくても自力実装できるわwwwww(所感)
感想
1
HTMLはそこそこ綺麗かなと思いました
<div id="pulldown"> <div v-for="(choices,layer) in selectable_items"> <div v-bind:id="'layer' + layer" v-show="choices.length >= 1"> <h2>第{{layer+1}}階層</h2> <select v-bind:id="'pd-'+ layer" v-model="selected_stack[layer]"> <option v-for="item in choices" v-bind:value="item.id"> {{item.name}} </option> </select> </div> </div> </div> <script src="pulldown.js"></script>
2
現状の選択に紐づく選択肢をJSでフィルターして渡してるんだけど、 HTML側のフィルターで頑張るべきなのか、JS側で頑張るべきなのか、ライブラリの思想としてどっちがいいのかがよくわからない
//現状のユーザー選択(selected_stack)に対して、表示すべき選択肢を取得 selectable_items: function () { var results = []; var layer = 0; for (layer = 0; layer <= this.selected_stack.length; layer++) { //上位層の選択結果を取得 before_selected_id = '' if (layer >= 1 ) { before_selected_id = this.selected_stack[layer-1]; } //該当層かつ、上位層の選択肢に合致するもののみ抽出 layer_result = MENU_M.filter(function (value) { return value.layer === layer && value.before_id === before_selected_id; }); results.push(layer_result); } return results; },
3
JS側が汚い。初期化処理とかキモイ。watch使っているんだけど謎ラッパーかまさないとListの検知ができない
computed: { //watch関数をまともに動作させるためのラッパー //参考:https://qiita.com/haruyanagi17/items/d74c0b9546719ff88c63 watch_selected_stack: function () { return Object.assign({}, this.selected_stack); // ディープコピーしたものを返す }, }, watch: { //選択肢が入力された際の動作定義 watch_selected_stack: function (newval, oldval) { //変更箇所を検知 var update_flag = false; var layer = 0; for(layer=0; layer < this.selected_stack.length; layer++){ //変更箇所より後の選択肢は初期化する if(update_flag) { this.selected_stack[layer] = ''; } //変更されている箇所があれば、フラグを立てる if (newval[layer] !== oldval[layer]) { update_flag = true; } } }, }
今後
もうちょいきれいに書く方法探しますわ