Pro Yearly is on sale from $80 to $50! »

Vue コンポーネント実装パターン

Dc5be06c50fdfe681913540a3effdcc8?s=47 seya
May 22, 2018

Vue コンポーネント実装パターン

v-meetup vol.7 でのLT資料です。

Dc5be06c50fdfe681913540a3effdcc8?s=128

seya

May 22, 2018
Tweet

Transcript

  1. Vueίϯϙʔωϯτ࣮૷ύλʔϯ Controlled Component & Transparent Wrappers

  2. ࣗݾ঺հ ໊લ: seya ձࣾ: BizReach झຯ: GraphQL

  3. Controlled Component

  4. v-model ศརͰ͢ΑͶ <input type="text" v-model="text" /> <button>{{ text }}</button>

  5. Ͱ΋ಠࣗͰఆٛͨ͠ίϯϙʔωϯτʹ v-model ࢖͍͍ͨ৔߹͸Ͳ͏͢Ε͹͍͍Ͱ͠ΐ͏ʁ <form> <toggle-button v-model="toggled" /> </form> ←͜Ε࡞Γ͍ͨ <template>

    <span class="toggle" role="checkbox" tabindex=“0" aria-checked="false" ></span> </template> ↓͜Μͳײ͡Ͱॻ͍ͯ ↓ ͜Μͳײ͡ʹ v-model ࢖͍͍ͨɻΠϕϯτϋϯυϥ౉ͯ͠͝ʹΐ͝ʹΐͱ͔ͨ͘͠ͳ͍ɻ
  6. v-model ͸ :value ͱ @input ͷ ૊Έ߹ΘͤͰͰ͖͍ͯΔ <input type="text" v-model="text"

    /> <input type="text" :value="text" @input="$emit('input', $event.target.value)" /> ྫ͑͹ ͸ ͱಉ͡
  7. ͳͷͰࢠڙͷํͰ͸͜Μͳײ͡Ͱॻ͍ͯ͋͛ͯ <template> <span class="toggle" role="checkbox" tabindex="0" @click="toggle" :aria-checked="value.toString()" ></span> </template>

    <script> export default { props: ['value'], methods: { toggle() { this.$emit('input', !this.value); } } }; </script>
  8. ਌ͷํͰ͸ v-model ॻ͍ͯ͋͛Δ͚ͩͰ <form> <toggle-input v-model="someFlag" /> </form>

  9. ಈ͘ʂ

  10. ͪͳΈʹ value ͱ ˏinput ͷͱ͜ʹͪΌΜͱ໊લ ͚͍ͭͨ৔߹͸ model ϓϩύςΟΛ࢖͑͹ՄೳͰ͢ <script> export

    default { model: { prop: 'toggled', event: ‘toggle' }, props: [‘toggled'], methods: { toggle() { this.$emit('toggle', !this.toggled); } } }; </script>
  11. Transparent Wrappers

  12. ͖ͬ͞ͷํ๏Ͱಠࣗͷ input ࡞Δ <template> <input :value="value" @input="$emit('input', $event.target.value)" /> </template>

  13. ͦͯ͠਌Ͱ͸͜ͷཁૉʹϑΥʔΧε͕͔͔ͬͨΒͳʹ͔ ͠Β࣮ߦ͍ͨ͠ͱ͢Δɻ (inputҎ֎ͷͱ͜ΖʹΦʔόʔϨΠ͔͚Δͱ͔) <template> <form> <custom-input @focus.native="showOverlay" /> </form> </template>

  14. label΋Ұॹʹ͢Δͱ…ಈ͔ͳ͍ʂʂʂ @focus.native ͸ϧʔτͷཁૉΛର৅ʹ͢ΔͨΊ Input ͷϑΥʔΧε͸र͑ͳ͍ɻ ͔ͱݴͬͯଞͷࢦఆͷํ๏΋ͳ͍ɻ٧Μͩɻ <template> <label> {{ label

    }} <input :value="value" @input="$emit('input', $event.target.value)" /> </label> </template>
  15. JOQVUʹΠϕϯτϦεφʔ ͕͍͍ͭͯͳ͍ͳΒ JOQVUʹΠϕϯτϦεφʔΛ͚ͭΕ͹ ͍͍͡Όͳ͍ Transparent Wrappers

  16. $listeners ͰΠϕϯτϦεφʔΛऔಘͰ͖ΔͷͰɺͦΕΛ಺෦ ͷ input ʹ౉ͯ͋͛͠Δɻ <template> <label> {{ label }}

    <input :value="value" v-on="listeners" /> </label> </template> <script> computed: { listeners() { return { ...this.$listeners, input: event => this.$emit('input', event.target.value) } } } </script>
  17. ͋ͱ͸ @focus.native Λ @focus ʹͯ͋͛͠Ε͹ <template> <form> <custom-input :label=“hoge” @focus="showOverlay"

    v-model="text" /> </form> </template>
  18. ಈ͘ʂʂʂ

  19. PlaceholderΛ౉͍ͨ͠৔߹͸ʁ <template> <form> <custom-input placeholder=“text" :label="hoge" @focus="showOverlay" v-model="text" /> </form>

    </template>
  20. ࢀߟ: https://jp.vuejs.org/v2/api/#inheritAttrs

  21. inheritAttrs Λ false ʹͯ͠ v-bind ʹ $attrs Λ౉ͤ͹OK <template> <label>

    {{ label }} <input :value="value" v-on="listeners" v-bind="$attrs" /> </label> </template> <script> export default { inheritAttrs: false, // ଞͷ΍ͭ } </script>
  22. ݁࿦ Controlled Component + Transparent Wrapper = ωΠςΟϒཁૉͬΆ͘ѻ͑Δಠࣗͷίϯϙʔωϯτ͕࡞ΕΔʂ

  23. ࠷ޙʹ ࣮͸υΩϡϝϯτʹ͞Βͬͱॻ͍ͯ͋Δ

  24. Ջ͕͋ͬͨΒυΩϡϝϯτಡ΋͏ʂ

  25. ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ