19
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.js #2Advent Calendar 2018

Day 11

Vue.js UIフレームワークに学ぶコンポーネントの作り方

Last updated at Posted at 2018-12-11

※非デザイナ出身のエンジニア向けです。

#UI フレームワークの数々
webデザイナ不在のプロジェクトではエンジニアの皆様はbootstrapのようなCSSフレームワークを使って構築することが多いとおもいます。

vue.js向けにも
bootstrapをもとにしたbootstrap-vue
bulmaをもとにしたbeefyなどがあります

マテリアルデザインに準拠し、日本語ローカライズも進んでいるVuetify
そしてフルスクラッチで多機能なelement-ui

いずれも使用頻度の高い入力フォームやテーブル、モーダルダイヤログなどを
コンポーネント単位で簡単に実装できます。

#elementのソースを見る
必要な部品単位で利用することができ、
CSSデザインのカスタマイズも容易なelement-uiを元に設計を見てみましょう

よく使われるボタンコンポーネントの例です。
element-ui button
ドキュメントはこのようになっており、
size, typeなどの各属性値を設定することで汎用的に多機能なボタンコンポーネントになっています。

qiita.html
<el-button size="small" type="success">小さい正常系のボタン</el-button>

それを実現するソースをみてみましょう
https://github.com/ElemeFE/element/blob/dev/packages/button/src/button.vue

テンプレート部

qiita.html
<template>
  <button
    class="el-button"
    @click="handleClick"
    :disabled="buttonDisabled || loading"
    :autofocus="autofocus"
    :type="nativeType"
    :class="[
      type ? 'el-button--' + type : '',
      buttonSize ? 'el-button--' + buttonSize : '',
      {
        'is-disabled': buttonDisabled,
        'is-loading': loading,
        'is-plain': plain,
        'is-round': round,
        'is-circle': circle
      }
    ]"
  >
    <i class="el-icon-loading" v-if="loading"></i>
    <i :class="icon" v-if="icon && !loading"></i>
    <span v-if="$slots.default"><slot></slot></span>
  </button>
</template>

js部


  export default {
    name: 'ElButton',

    inject: {
      elForm: {
        default: ''
      },
      elFormItem: {
        default: ''
      }
    },

    props: {
      type: {
        type: String,
        default: 'default'
      },
      size: String,
      icon: {
        type: String,
        default: ''
      },
      nativeType: {
        type: String,
        default: 'button'
      },
      loading: Boolean,
      disabled: Boolean,
      plain: Boolean,
      autofocus: Boolean,
      round: Boolean,
      circle: Boolean
    },

    computed: {
      _elFormItemSize() {
        return (this.elFormItem || {}).elFormItemSize;
      },
      buttonSize() {
        return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
      },
      buttonDisabled() {
        return this.disabled || (this.elForm || {}).disabled;
      }
    },

    methods: {
      handleClick(evt) {
        this.$emit('click', evt);
      }
    }
  };

propsの設定がドキュメントどおりにバリデートしてあり、型定義されています。
computedを使って、デフォルトサイズをform単位でのサイズ設定を可能にしてあります。
loadingがtrueならdisabled状態になり、loadingコンポーネントを呼び出しています。

このようにuiフレームワークには汎用性の高いコンポーネントを作る際に参考になるノウハウが詰まっています。

今回は時間の都合で最もシンプルなボタンの例だけでしたが、date-pickerなど高機能なUIでは
vueのmixinの利用方法や、共通部分の分離と再利用など実践的で複雑な内容を学ぶことができます。

先週末から体調不良で予定の1/3ほどの内容しか書けていませんが、今年のvue.jsアドベントカレンダー
なんとか日付が変わる前に投稿できました。

19
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?