少し長くなってしまい申し訳ないのですが、宜しければお付き合いください。
現在Vue.jsを使って、以下のコードで複数あるアコーディオンの開閉を一度に行う「toggleAll」メソッドを定義しています。
アコーディオンはこのコンポーネントからpropsでdataを渡し、子コンポーネントである<AccordionComponent>内でv-forを使いレンダリングしているものです。
html
1<section> 2 <div class="skills-box"> 3 <h3>My Skills</h3> 4 <div class="show-box"> 5 <p>Click the item <span>or</span></p> 6 <a class="show-all" v-on:click="change(); toggleAll()"> <!-- この部分です --> 7 {{ toggleMessage }} 8 <i class="fas fa-sort"></i> 9 </a> 10 </div> 11 <AccordionComponent v-bind:skills="skills"></AccordionComponent> <!-- 子コンポーネント --> 12 </div> 13 <router-link to="/" class="move"><i class="fas fa-angle-left"></i> BACK</router-link> 14</section>
JavaScript
1import AccordionComponent from '../components/Accordion.vue' 2export default { 3 name: 'Skills', 4 data() { 5 return { 6 skills: [ 7 {id: 1, name: 'HTML・CSS', bgColor: 'orangered', show: false, description: `text`}, 8 {id: 2, name: 'Sass', bgColor: 'hotpink', show: false, description: `text`}, 9 {id: 3, name: 'JavaScript', bgColor: 'gold', show: false, description: `text`}, 10 {id: 4, name: 'Vue.js', bgColor: 'mediumseagreen', show: false, description: `text`}, 11 {id: 5, name: 'Firebase', bgColor: 'orange', show: false, description: `text`}, 12 {id: 6, name: 'PHP', bgColor: 'steelblue', show: false, description: `text`}, 13 {id: 7, name: 'Git・Github', bgColor: 'black', show: false, description: `text`}, 14 {id: 8, name: 'webpack', bgColor: 'skyblue', show: false, description: `text`}, 15 ], //skills 16 toggleMessage: 'Show all' 17 } 18 }, 19 methods: { 20 change: function() { 21 if(this.toggleMessage === 'Show all') { 22 this.toggleMessage = 'Close all' 23 } else { 24 this.toggleMessage = 'Show all' 25 } 26 }, 27 toggleAll: function() { 28 for(let skill of this.skills) { 29 if(this.toggleOpen === 'Show all') { 30 skill.show = true 31 } else { 32 skill.show = false 33 } 34 } // for of 35 }, 36 }, 37 components: { 38 AccordionComponent 39 } 40}
各アコーディオンの開閉は上記の配列「skills」内のオブジェクトが各々持っている「show」の真偽値によって管理しているのですが、「toggleAll」はその「show」全ての真偽値を一斉に切り替えるメソッドです。
しかしこのコードですと、下記のgifのように、仮に全て手動でアコーディオンを開けた場合、一度意味のないtogglleAllを実行しなければなりません。(勝手にClose allには切り替わってくれないため)
そのため、配列skills内のshowの真偽値を監視して、全ての「show」がtrueまたはfalseになった時に「toggleMessage」の値を変更したいと考えております。
とりあえず真偽値が全てtrueまたはfalseだった時に「toggleMessage」を変更する、という処理を行うコードは下記のように考えたのですが、これをどう正しく動く形でVueの算出プロパティ等に反映してよいか分からずに困っています。
公式のリファレンスにも中にこのように複数の関数を入れ込む方法が載っておらず、エラーになってしまい私のスキルでは解決できないため手詰まりになってしまっています。
JavaScript
1let toggleMessage = 'Show all'; 2 3const skills = [ 4 {id: 1, name: 'item1', show: true}, 5 {id: 2, name: 'item2', show: true}, 6 {id: 3, name: 'item3', show: true} 7]; 8 9const checkTrue = skills.every(value => value.show === true ); 10const checkFalse = skills.every(value => value.show === false ); 11 12if(checkTrue === true) { 13 toggleMessage = 'Close all'; 14} else if(checkFalse === true) { 15 toggleMessage= 'Show all'; 16}
そして何より、この一連の単純な動作のために3つに分けてここまでグチャグチャと書かなければいけないのか、ということも我ながら疑問に思っています。
もし、もっと効率の良い方法があれば教えていただけると幸いです。
JavaScriptの基礎が少し怪しいため、分かりづらいコード・質問になってしまい本当に申し訳ありませんが、何卒お力添えをよろしくお願いいたします。
※追記です
下記のコードをコンポーネント内に追加いたしました。
JavaScript
1updated: function() { 2 alert('updated') 3 const checkTrue = this.skills.every(value => value.show === true ) 4 const checkFalse = this.skills.every(value => value.show === false ) 5 if(checkTrue === true) { 6 this.toggleMessage = 'Close all' 7 } else if(checkFalse === true) { 8 this.toggleMessage = 'Show all' 9 } 10},
しかし思い通りの挙動にはなっておらず、どうやらアコーディオンの開閉ではアラートが表示されなかったので、そのタイミングでは処理は行われていないようです。
試しに「toggleAll」メッソドを実行してみると、アラートが表示されました。
公式で「仮想DOMが再描画されたタイミング」とあったので、「v-show」で行っていたアコーディオンの開閉を「v-if」に変えてみたりもしたのですが、処理は実行されませんでした。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/07/11 06:59 編集
2019/07/11 06:33 編集
2019/07/11 07:20 編集
2019/07/11 09:18 編集
2019/07/11 11:44
2019/07/11 11:46