カテゴリーアーカイブ Vue

著者:杉浦

【Vue.js】デフォルト値による簡易な引数で呼び出せる柔軟なコンポーネント

 Vue.jsではしばしばカスタムHTMLタグとも言える程、小さな部品を作りたくなります。例えばform中の入力欄です。簡易に作るのであれば次の様にlabelとinputに必須属性とユーザ向けの多少の文言をつけるのみです。

<label for="login_username">ユーザ名</label>
<input
  id="login_username"
  type="text"
  name="username">

 実際にはこれにデザインが加わります。

<div class="row">
  <div class="col-md-12">
    <div class="form-group row">
      <label
        class="col-md-3 col-form-label text-md-right"
        for="login_username">ユーザ名</label>
      <input
        id="login_username"
        type="text"
        class="col-md-9 custom-control-input"
        name="username">
    </div>
  </div>
</div>

 Vue.jsを用いるならば、inputタグのvalueと何かしらの変数を同期させたくなるでしょう。動的なバリデーション、警告を追加もするでしょう。

<div class="row">
  <div class="col-md-12">
    <div class="form-group row">
      <label
        class="col-md-3 col-form-label text-md-right"
        for="login_username">ユーザ名</label>
      <div class="col-md-9">
        <input
          id="login_username"
          v-model="vModelValue"
          type="text"
          class="custom-control-input"
          name="username"
          @input="validation()">
       <div
          v-show="isValidationErr"
          class="text-black-50">{{ localValidationErrMsg }}</div>
      </div>
    </div>
  </div>
</div>

 シンプルなtype=”text”でこれです。inputタグの属性に凝ると更にvalue、placeholder、required、typeがnumberならばstep、max、minなどが増えます。これはたかだか一つの入力欄でありフォーム全体を考えた場合、inputタグセットが十個近く並んだりもします。素のHTMLコードのままその様なものを記述した場合、可読性が落ちてしまい開発も保守もやり難くなってしまいます。Vue.jsでコンポーネントとしてまとめることでとりあえずの解決を図ります。

 上のJSFiddleでコンポーネントを用いているHTMLコードは18行程です。実際はコンポーネント定義をHTMLコードと別の1ファイルにまとめるため、コンポーネント定義部はカウントしていません。上述した20行程のinputタグ周りを重ねて書くよりよっぽど楽になりました。
 コンポーネントを用いることで記述は楽になりましたが、全てtype=”text”で様々な属性が全くないinputタグセットでしかなく、柔軟性が犠牲になっています。属性を指定するための引数を増やすことによってもっと柔軟なコンポーネントにします。柔軟にするうえで気を付けることに、呼び出し側で不要なコードが増えない様することがあります。コンポーネントを呼び出すための引数にデフォルト値を与えることによってこれを実現します。

 inputタグの効果が多彩になりました。メールアドレスは\や日本語の様なメールアドレスに含まれることのない文字を打つと、その文字を消して警告を表示します。コードのHTMLを見て頂けばわかる通り引数がinputタグの属性の大部分をカバーする様になっています。それだけ大量の引数が用意されているにもかかわらず、コンポーネント呼び出しが短くまとまっているのがデフォルト値の効果です。

<input
 :value="value"
>
/** 省略 */
props:{
  value: {type: String, default: null},
}

の様に記述するとコンポーネント呼び出し時に引数valueを指定しない場合、value=nullとなりHTMLコード上でもvalue属性は指定されなかったことになります。これと同じ様ことを他の属性にも適用することで大量の引数を用意しつつも、呼び出しを簡単にしています。
 実際のコーディングではンポーネントの定義を1ファイルにまとめる単一ファイルコンポーネントの仕組みを用います。これにより、JSFiddleで表示しているなかなかリッチな画面を作るHTMLコードは次の様にまとまります。

<div id="app">
  <form-input
    label="ユーザ名"
    id="edit_username"
    name="username"
    placeholder="例:浜松 太郎"></form-input>
  <form-input
    label="メールアドレス"
    id="edit_mail"
    name="mail"
    type="mail"
    validation-template="mail"></form-input>
  <form-input
    label="番号"
    id="edit_number"
    name="number"
    type="number"
    value="0.53"
    max="1" min="0" step="0.01"></form-input>
  <form-input
    label="色"
    id="edit_color"
    name="color"
    type="color"
    value="#F0115F"></form-input>
</div>
  • この記事いいね! (0)
著者:杉浦

Vue.jsの配列監視

 Vue.jsはJavaScriptのフレームワークで、目玉の機能として変数の値の変化に同期して画面上の描画を変更する機能があります。変数の変化は変数の監視機能で実現されていますが、オブジェクトや配列のプロパティをどこまで監視するかという問題があります。JavaScriptである以上prototypeと付き合っていく必要があり、再帰的にプロパティを見ることはprototypeを大量に見ることにつながり計算量的な問題が発生します。
 Vue.jsではいくつかの配列用のメソッドを上書きすることによって監視を実現しています。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

リストレンダリング — Vue.js#配列の変化を検出より引用

 このため

a[a.length + 1] = 1;

 の様にするよりも

a.push(1);

の様に配列操作メソッドを使うことが推奨されます。
 上記のリストには配列中のある値を変更するためのメソッドが存在しません。加えてVue.jsはプロパティの変更を検知しません。

a[0] = 1;// Vue.jsは変数aが変化したことに気づかない

 このような時には

vm.$set(/** 変更対象元の配列やオブジェクト */vm.items, /** インデックスやプロパティ名 */indexOfItem, /** 変更後の値 */newValue)

 の様にvm.$set()なるVue.jsにこの変数は変更したと通知するメソッドで値を変更することになります。
 原因はわかりませんでしたが、これでもなお画面が変化しないことがありました。このような時には

vm.$forceUpdate();

なる強制再描画メソッドを呼び出します。このメソッドの再描画は特徴的で、呼び出したコンポーネントとその子コンポーネントでのみ再描画をします。とにかく更新したい時には、大本の親コンポーネントにvm.$forceUpdate()を実行するイベントを設定して子コンポーネントから発火させる方法が望ましいでしょう。

  • この記事いいね! (0)
著者:杉浦

HSL表記によって色を自然に変化させる

 色の表記の定義である色空間には様々なものがありますよく聞くものに赤青緑の三原色を用いたRGB、それに加えて透明度を足したRGBAがあります。他にも印刷で使われるCMYK(Cyan, Magenta, Yellow, Key plate)やLab色空間、XYZ表色系など目的に合わせて多くのものが作られています。HSLはその中の一つでHLSとも呼ばれ色相(Hue)、輝度(Lightness)、彩度(Saturation)の3値から定義される色空間です。HLSの値の大雑把な意味は次です。

  • 色相:色味を0~360度の範囲の角度で表す。0度は赤で、その反対側に位置する180度は赤の反対色にあたる青緑。すなわち、反対色を見つけるのも容易。色相についてはHSVと同じ。
  • 彩度:HSVとは違い、純色から彩度が落ちるということは、すなわち灰色になっていくという考え方に基づいている。
  • 輝度:明度100%を純色とし、そこからどれだけ明るさが失われるかを示すHSVとは違い、輝度0%を黒、100%を白とし、その中間(50%)を純色とする。50%以下はHSVの明度を示し、50%以上はHSVの彩度を示すと考えると分かりやすいだろう。

HLS色空間 – Wikipediaより引用

 紹介するHSLの主な利点は二つです。まず第一にCSSのオプションとして直接指定できます。次の様にhsl(hue, ssaturation, lightness)を指定するのみで大変楽です。

style="background-color: hsl(90deg, 100%, 50%);

CSS を使った HTML の要素への色の適用 – HTML: HyperText Markup Language | MDN #HSL_functional_notation
– CSS: カスケーディングスタイルシート | MDN #HSL_colors
 わざわざ変換式を実装してRGBに変える必要も、RGB上でややこしい計算をする必要もありません。
 第二は自然で多彩な色の変化を簡単に表せることです。次のJSFiddleはHSL方式とRGB方式それぞれで箱の中の色を変えるコードの実装です。

 色相の下に彩度、輝度が引っ付いているイメージで簡単に色を決定することができると思います。RGBでは赤緑青から離れる程どうやって思いついた色を作るのかてこずるでしょう。
 HSLがRGBに比べて特に便利なのがある色からある色への変化です。同時刻にある色になる様に三値をそれぞれ一次関数的に変化させるのみできれいな色の変化を実現できます。

  • この記事いいね! (0)
著者:杉浦

Vue.jsでVue.js向けに開発されていないライブラリを用いる

 Vue.jsはwebページを部品化してコーディングすることを目的としたJavaScriptのフレームワークです。単一コンポーネントの仕組みを用いたVue.jsのコード例の多くは(少なくとも私の読んだコードでは)次の様になっています。

// コンポーネント定義用Vue.jsコード
<template>
  // Vue.jsと連携するHTMLコード
</template>

<script>
export default {
  name: 'hoge',
  // prop:{}とかdeta(){return {hogehoge}}とかmethods:{}とかVue.jsと連携するためのプロパティ
};
</script>

<style scoped>
  // このコンポーネント内でのみ適用されるcss
</style>
// コンポーネント読み込み用JavaScriptコード
window.$ = window.jQuery = require('jquery');
// 色々グローバルで使うライブラリ

window.Vue = require('vue');

Vue.component('hoge', require('./hoge.vue').default);

const app = new Vue({
  el: '#app',
});

 自分はVue.jsで使うことを前提にしていないライブラリはJavaScript側2、3行目の様に色々読み込むものだと思っていました。一方でこのようなやり方はグローバル汚染がひどく、重要なごく一部のライブラリ以外を読み込んだ場合あっという間にバグが生まれるとも思っていました。実際はそのようなことをせずともよく、次の様に記述することで管理しやすくライブラリを用いることができました。

<template>
  // Vue.jsと連携するHTMLコード
</template>

<script>
import 'fuga';
import foo from 'foo';

// Vue.jsに依らない静的処理
const bar = foo.bar();

export default {
  name: 'hoge',
  // importしたライブラリや変数barを用いたVue.jsと連携するコード
};
</script>

<style scoped>
  // このコンポーネント内でのみ適用されるcss
</style>

 <script>タグの先頭に記述するだけです。<script>タグの内部ならばVue.jsがいい感じにスコープを作ってくれるのでグローバル汚染を気にせず好き勝手できます。
 <script>export default {で始めて、}</script>で終わらなければならないという風に思い込んでいましたがVue.jsにその様な縛りはなく、実際はかなり自由に記述できました。

  • この記事いいね! (0)