複雑なv-ifに負けないために.pdf

B8403d102456248570005ee7fb2ba0f7?s=47 philomagi
September 19, 2019

 複雑なv-ifに負けないために.pdf

B8403d102456248570005ee7fb2ba0f7?s=128

philomagi

September 19, 2019
Tweet

Transcript

  1. 複雑なv-ifに負けないために 1 @Philomagi 2019/09/19@Yumemi.vue #1 #yumemi_vue

  2. 発表者 @Philomagi • 主にフロントエンド主体のWEB系エンジニア • ScalaとTypescriptとRubyが好き ◦ Rubyは最近、公私共に若干疎遠 • PHPは中々縁が切れない悪友

    ◦ 最近は、「然程悪いやつでもないな」と思い始めてる 2
  3. 今回のお題 3

  4. v-if 4

  5. v-if =「表示条件」 5

  6. 6 <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else> fuga

    </div> </div> </template>
  7. 7 <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else> fuga

    </div> </div> </template>
  8. v-ifを使うことで、 条件に応じて表示を変えられる 8

  9. 簡単!便利! 9

  10. 10 <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else> fuga

    </div> </div> </template>
  11. <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else> fuga </div>

    </div> </template> 11 1. hoge/fuga の他に、piyoという表示もしたい 2. fugaを表示する条件を追加してほしい 3. hogeでもfugaでも無い場合に、 piyoを表示したい
  12. 12 <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else-if="shouldShowFuga"> fuga

    </div> <div v-else> piyo </div> </div> </template>
  13. 13 <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else-if="shouldShowFuga"> fuga

    </div> <div v-else> piyo </div> </div> </template>
  14. 条件の追加も簡単! 14

  15. おしまい 15

  16. おしまい 16

  17. ご清聴ありがとうございました 17 しばらく後・・・

  18. 18 <template> <div> <div v-if="shouldShowHoge"> hoge </div> <div v-else-if="shouldShowFuga"> fuga

    </div> <div v-else-if="shouldShowPiyo"> piyo </div> <div v-else-if="shouldShowXXX"> xxx </div> <div v-else-if="shouldShowYYY"> yyy </div> <div v-else-if="shouldShowZZZ"> zzz </div>
  19. 19 <script> export default { data() { return { shouldShowHoge:

    /**/, shouldShowFuga: /**/, shouldShowPiyo: /**/, shouldShowXXX: /**/, shouldShowYYY: /**/, shouldShowZZZ: /**/, /* 以下略 */ } }, } </script>
  20. 20 <script> export default { data() { return { shouldShowHoge:

    /**/, shouldShowFuga: /**/, shouldShowPiyo: /**/, shouldShowXXX: /**/, shouldShowYYY: /**/, shouldShowZZZ: /**/, /* 以下略 */ } }, } </script> 実際のプロジェクトでは • computedによる計算が必要だったり • 処理の中で状態が書き換えられたり 「条件」と「表示」の関係が さらに複雑になってくる
  21. 出てくる問題 表示の条件が複雑になると 21

  22. 表示の条件が複雑になると • htmlもjsも肥大化する 出てくる問題 22

  23. 出てくる問題 表示の条件が複雑になると • htmlもjsも肥大化する ◦ テストが大変 23

  24. 出てくる問題 表示の条件が複雑になると • htmlもjsも肥大化する ◦ テストが大変 ◦ 影響範囲を把握しづらく、修正しにくい 24

  25. どうにか解決したい 25

  26. 問題を整理する 何故html/jsが肥大化するのか? 26

  27. 問題を整理する 何故html/jsが肥大化するのか? • 条件分岐がたくさん有るから • 条件毎に表示すべき内容が違うから 27

  28. 問題を整理する 何故html/jsが肥大化するのか? • 条件分岐がたくさん有るから • 条件毎に表示すべき内容が違うから 「条件」と「表示」を、 一つにまとめてしまってはどうだろう? 28

  29. 「条件」が決まれば「表示」も一意に定まる 「条件」と「表示」を一つにする 29

  30. 「条件」が決まれば「表示」も一意に定まる なら、「条件」と「表示」は 常にセットにして扱った方が便利なのでは? 「条件」と「表示」を一つにする 30

  31. 「条件」が決まれば「表示」も一意に定まる なら、「条件」と「表示」は 常にセットにして扱った方が便利なのでは? 「条件」と「表示」の対応関係を 1つのオブジェクトで表現してみる 「条件」と「表示」を一つにする 31

  32. 具体的にコードでは? 32

  33. 33 1. 「条件-表示の対応」を表すIFを定義する import { VueConstructor } from 'vue' export

    interface ShowImageSpec { readonly shown: VueConstructor isSatisfiedBy (param: ShowImageSpecParam): boolean }
  34. 34 1. 「条件-表示の対応」を表すIFを定義する import { VueConstructor } from 'vue' export

    interface ShowImageSpec { readonly shown: VueConstructor isSatisfiedBy (param: ShowImageSpecParam): boolean } 「表示」を表すプロパティ定義
  35. 35 1. 「条件-表示の対応」を表すIFを定義する import { VueConstructor } from 'vue' export

    interface ShowImageSpec { readonly shown: VueConstructor isSatisfiedBy (param: ShowImageSpecParam): boolean } 「条件」を表すメソッド定義
  36. 36 2. コンポーネントを作る <template> <img alt="Vue logo" src="../../assets/logo.png"> </template>

  37. 37 3. 条件/表示の対応オブジェクトを実装する import { ShowImageSpec, ShowImageSpecParam } from '../show-image-spec'

    import VueComp from '../../../frame-work/Vue.vue' export default class ShowVueSpec implements ShowImageSpec { readonly shown = VueComp isSatisfiedBy (param: ShowImageSpecParam ): boolean { return param.framework === 'Vue' } }
  38. 38 3. 条件/表示の対応オブジェクトを実装する import { ShowImageSpec, ShowImageSpecParam } from '../show-image-spec'

    import VueComp from '../../../frame-work/Vue.vue' export default class ShowVueSpec implements ShowImageSpec { readonly shown = VueComp isSatisfiedBy (param: ShowImageSpecParam ): boolean { return param.framework === 'Vue' } } 「表示」の内容
  39. 39 3. 条件/表示の対応オブジェクトを実装する import { ShowImageSpec, ShowImageSpecParam } from '../show-image-spec'

    import VueComp from '../../../frame-work/Vue.vue' export default class ShowVueSpec implements ShowImageSpec { readonly shown = VueComp isSatisfiedBy (param: ShowImageSpecParam ): boolean { return param.framework === 'Vue' } } 「表示」の内容 「表示」されるべき条件
  40. 40 4. オブジェクトから「表示」を得る get frameworkView (): VueConstructor { const appliedSpec:

    ShowImageSpec = applyWithDefault( new ShowKoujichuSpec(), [ new ShowVueSpec(), new ShowHogeSpec() ] ) return appliedSpec.shown } 「表示」を取得
  41. 41 5. 得た「表示」を適用する <div> <h2>好きなjsのフレームワークは?</h2> <component :is="frameworkView" /> </div>

  42. 42 5. 得た「表示」を適用する <div> <h2>好きなjsのフレームワークは?</h2> <component :is="frameworkView" /> </div>

  43. 43 5. 得た「表示」を適用する <div> <h2>好きなjsのフレームワークは?</h2> <component :is="frameworkView" /> </div>

  44. 44 5. 得た「表示」を適用する <div> <h2>好きなjsのフレームワークは?</h2> <component :is="frameworkView" /> </div> is属性にVueConstructorを渡すと、

    そのVueコンポーネントをレンダリングしてくれる!
  45. 45 https://jp.vuejs.org/v2/guide/components.html

  46. 46 https://jp.vuejs.org/v2/guide/components.html

  47. サンプルアプリ (スライドのdescriptionに記載) 47

  48. 「条件」に対する考え方 48

  49. コンポーネントだけで頑張らない 49 • Vue.jsのSingle File Componentは便利だけど、 その中で全て完結させる必要は無い • 「表示」について複雑な条件やルールが有るなら、 それも立派な「ロジック」と考えた方が良い

    • OOPのテクニックを使えば、コンポーネントも より柔軟かつシンプルにできる
  50. フロントにも「ロジック」は有る 50 • 「表示」はコンポーネントに、 「ロジック」は専門のモジュールに任せる • 責務・関心を適切に分割しよう

  51. まとめ • 複雑な表示条件はコンポーネントだけで頑張ら ず、「ロジック」として独立させる • OOPのテクニックを使うことで より柔軟なコンポーネントにできる • 責務と関心を適切に分離する 51

  52. ご清聴ありがとうございました 52