20201127のvue.jsに関する記事は16件です。

Codeignater3を使ったMPAサイトからNuxt.js+Vueへのサイトリニューアル

はじめに

 Vue.js(CDN版)を採用したPHP動的サイトから、Nuxt.js+Vueを使ったいわゆるSPAサイトへのリニューアルを敢行した。

経緯と歴史

 最初は、フレームワークを使わないサイトとして設計したが、のちにSmatryを採用し、Viewとロジックを分離した第二世代をリリース。その後、Codeignater3を採用し、本格的にPHPフレームワークを採用した第三世代と進化していったが、リプレースの切っ掛けはいずれも機能拡張を繰り返し、いずれも 現状に限界を感じよりモダンな技術を採用していった経緯がある 。

今回は何が限界だったのか

Vueライブラリの複雑化

 当初はJqueryを採用していたが、Vue.jsの導入に合わせライブラリが複雑化し、バージョンアップへの不安と煩雑さがつきまとうことになった。

痒いところに手が届かないフレームワークとViewのカスタマイズの煩雑化

 UIフレームワークとして採用していたMaterializeはVue前提ではないため、開発を進めるにつれCSSをカスタマイズを行う面が多くなり、フレームワークのメリットが少なくなるとともに、CSSの開発に多くの時間が取られることになった。

更新手順およびViewの煩雑化・複雑化

 ページが複雑化するに伴い、PHPのinclude機能で使い回すView画面がスパゲティ化するようになり、速度向上で導入したPWAのServiceWorkerのバージョンを手作業で書き換えるなどの更新の手間が極めて煩雑になりつつあった。

ベストプラクティスな技術を試したい

 こうした状況が重なり、最新のフロントエンドのベストプラクティスとも言える技術で再構築を検討することとなった。当初はログインシステムの関係からVue-Cliのみを導入し、MPAのままの構築を行う事も検討したが、ユーザーへのID・パスワードの再設定のデメリットを考慮しても、Firebase Authenticationを採用した方が、セキュリティ面やプログラミング・維持などあらゆる場面でメリットがあると判断。Nuxt.js+VueによるSPAを採用することとなった。

開発

バックエンド

 SPAとなれば、必然的にフロントとバックエンドが分離されるが、リニューアル前より無限スクロールを採用していたことから部分的にCodeignaterにAPIを実装し、axiosを用いた非同期通信で情報を取得ていたこともあり、開発時間短縮のために、バックエンドは引き続きCodeignaterを改良およびリファクタリングしてそのまま採用することとなった。

フロントエンド

 Vue3およびTSの採用については現時点では見送ることとして、Webにサンプルなどのドキュメントが豊富なVue2.6.11とJSを採用した。
UIフレームワークはvuetifyを採用。最初はとっつきにくかったけど、高機能でデザインの完成度が高いので慣れてしまえば本当に楽。最初からコンポーネント至高なので、こちらも楽だが、無秩序にやってしまうとまたスパゲティになるので注意したい。

開発

 10月頭に開発がスタートをして、形になるリリースまで1ヶ月半。細かな機能追加と調整に二週間程度で完成することになった。

感想

 今回のリニューアルは技術的に本当に勉強になりましたし、サイトの管理と開発が本当に楽になりました。フロントとバックを分離した疎結合化は精神的にも楽になった感があります。Nuxt.jsは現時点でのベストプラクティス的な技術ではありますが、技術的に未熟で採用できないという事情はあるにしろ、基礎を習得しないと応用はできないとはいえ、随分と遠回りした印象もあります。これまでは煩雑な保守管理に時間を浪費していましたが、今後のページはペラ1でも無い限りNuxt.jsファーストで行きたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】checkboxでclickイベントが反応しない

checkboxをチェックした時のイベントは、

change イベントで発生する。

clickでは反応しないので注意。

<b-form-checkbox id="hoge-label" v-model="hoge.fuga" @change="hogeFunction">hogefuga</b-form-checkbox>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue-multiselectのカスタマイズ方法

概要

Vue-multiselectはセレクトボックスを簡単に実装できる便利なVueライブラリです。
複数選択や自動補完など一般的にセレクトボックスに求められる機能はほぼ全て実現できます。
ここでは公式サイトを元にVue-multiselectのカスタマイズ方法の一部を紹介します。

基本の使い方

スクリーンショット 2020-11-27 4.33.37.png

上図のようにシンプルな単一選択のセレクトボックスは以下のコードで実装できます。
なおCDNを利用するとVue-multiselectを簡単に試せます。

See the Pen RwGwBaO by shi-ma (@shi-ma) on CodePen.

optionsプロパティには選択肢に設定したい配列を指定します。

custom-labelプロパティに関数を指定すると、その返り値が選択肢として表示されるラベルとなります。
optionsが連想配列で各キーのバリューを組み合わせたラベルを作りたい時などは非常に便利です。
一つのキーのバリューのみをラベルとして表示したいときは、代わりにlabelプロパティを使いlabel=countryというような書き方ができます。

custom-labellabelは必須プロパティではありませんが、optionsが単なる配列でなく、連想配列の場合は設定しないと要素がそのまま表示されてしまいます。

スクリーンショット 2020-11-27 4.03.57.png

Events

Vue-multiselectにはイベントプロパティが用意されており、ユーザーの操作をトリガーにして関数を実行することが可能です。

イベントプロパティ一覧

プロパティ名 トリガー
@input this.valueの値が変わる
@select 選択肢を選ぶ
@remove 複数選択の時に選択を取り消す
@search-change 検索クエリが変更される
@tag タグが追加される
@open ドロップダウンが開かれる
@close ドロップダウンが閉じられる

@removeの利用例

See the Pen Untitled2 by shi-ma (@shi-ma) on CodePen.

例えば複数選択をオン(multiple="true")にして@removeプロパティを上記のように設定すると、選択を取り消した時にアラートが表示されます。

ezgif-3-08752ffc97a4.gif

自動補完

Vue-multiselectはデフォルトで自動補完機能がオンになっており、オフにしたい時はsearchableプロパティをfalseにします。
この自動補完はlabelプロパティの値(custom-labelプロパティを指定していればその値)を元に候補を絞っています。

もし独自の検索条件を設定したい場合はカスタマイズできます。

カスタマイズ例

See the Pen VwKwBMN by shi-ma (@shi-ma) on CodePen.

internal-searchプロパティをfalseにするとVue-multiselectの内部検索エンジンがオフになり、optionsを自由に設定できるようになります。

@search-changeに指定した関数は検索クエリに変更がある度に実行され、さらに関数の第一引数には検索クエリが入ります。これを利用し、optionsをフィルタリングするような関数を書けば、検索クエリが変わる度にoptionsが更新されるようになり、自動補完機能を代替できます。

ezgif-1-51043d6a0877.gif

終わりに

Vue-multiselectは用途に合わせてカスタマイズできる余地が大きいライブラリです。
ここでは現時点で日本語での説明が比較的少ない機能を紹介しましたが、Vue-multiselectには面白いカスタマイズ方法がまだまだあります。
Vueでセレクトボックスを実装するときはぜひVue-multiselectをお試しください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

セレクトボックスライブラリ「Vue-multiselect」のカスタマイズ方法

概要

Vue-multiselectはセレクトボックスを簡単に実装できる便利なVueライブラリです。
複数選択や自動補完など一般的にセレクトボックスに求められる機能はほぼ全て実現できます。
ここでは公式サイトを元にVue-multiselectのカスタマイズ方法の一部を紹介します。

基本の使い方

スクリーンショット 2020-11-27 4.33.37.png

上図のようにシンプルな単一選択のセレクトボックスは以下のコードで実装できます。
なおCDNを利用するとVue-multiselectを簡単に試せます。

See the Pen RwGwBaO by shi-ma (@shi-ma) on CodePen.

optionsプロパティには選択肢に設定したい配列を指定します。

custom-labelプロパティに関数を指定すると、その返り値が選択肢として表示されるラベルとなります。
optionsが連想配列で各キーのバリューを組み合わせたラベルを作りたい時などは非常に便利です。
一つのキーのバリューのみをラベルとして表示したいときは、代わりにlabelプロパティを使いlabel=countryというような書き方ができます。

custom-labellabelは必須プロパティではありませんが、optionsが単なる配列でなく、連想配列の場合は設定しないと要素がそのまま表示されてしまいます。

スクリーンショット 2020-11-27 4.03.57.png

Events

Vue-multiselectにはイベントプロパティが用意されており、ユーザーの操作をトリガーにして関数を実行することが可能です。

イベントプロパティ一覧

プロパティ名 トリガー
@input this.valueの値が変わる
@select 選択肢を選ぶ
@remove 複数選択の時に選択を取り消す
@search-change 検索クエリが変更される
@tag タグが追加される
@open ドロップダウンが開かれる
@close ドロップダウンが閉じられる

@removeの利用例

See the Pen Untitled2 by shi-ma (@shi-ma) on CodePen.

例えば複数選択をオン(multiple="true")にして@removeプロパティを上記のように設定すると、選択を取り消した時にアラートが表示されます。

ezgif-3-08752ffc97a4.gif

自動補完

Vue-multiselectはデフォルトで自動補完機能がオンになっており、オフにしたい時はsearchableプロパティをfalseにします。
この自動補完はlabelプロパティの値(custom-labelプロパティを指定していればその値)を元に候補を絞っています。

もし独自の検索条件を設定したい場合はカスタマイズできます。

カスタマイズ例

See the Pen VwKwBMN by shi-ma (@shi-ma) on CodePen.

internal-searchプロパティをfalseにするとVue-multiselectの内部検索エンジンがオフになり、optionsを自由に設定できるようになります。

@search-changeに指定した関数は検索クエリに変更がある度に実行され、さらに関数の第一引数には検索クエリが入ります。これを利用し、optionsをフィルタリングするような関数を書けば、検索クエリが変わる度にoptionsが更新されるようになり、自動補完機能を代替できます。

ezgif-1-51043d6a0877.gif

終わりに

Vue-multiselectは用途に合わせてカスタマイズできる余地が大きいライブラリです。
ここでは現時点で日本語での説明が比較的少ない機能を紹介しましたが、Vue-multiselectには面白いカスタマイズ方法がまだまだあります。
Vueでセレクトボックスを実装するときはぜひVue-multiselectをお試しください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel × Vue.jsでハマった簡単なエラー

ターミナルで下記の様に表示された際は、このエラーの上で右クリック+許可するだけ

ESLint is disabled since its execution has not been approved or denied yet. Use the light bulb menu to open the approval dialog. 

google先生に頼りすぎていたせいか、思考力が低下していた。気をつけよう・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vee-validateで他のフィールド値も含めてバリデーションする方法

始めに

フォームのバリデーションで、他のフィールド値と関連したバリデーションをしたいことがあると思います。


+ 最低値から最大値の範囲
+ 開始日から終了日の範囲

vee-validateでは@名前でValidationProviderの名前を探してその値を入れて渡すことができるため、それでチェックすることが可能です。

@名前でパラメータを渡す方法
ValidationObserver
  //- 他のValidationProviderで設定したnameから値を参照する
  ValidationProvider(
    rules="max_value:@max"
    v-slot="{ errors }"
  )
    input(
      v-model="$data.minValue"
      type="number"
    )
    .error {{ errors[0] }}
  //- nameを設定しておく
  ValidationProvider(
    name="max"
    rules=""
  )
    input(
      v-model="$data.maxValue"
      type="number"
    )

https://logaretm.github.io/vee-validate/advanced/cross-field-validation.html#targeting-other-fields

これでバリデーションはできるようになりましたが、エラー文言をもう一方の入力フィールドに伝えることができません。なので、エラー文言の表示のやり方を工夫する必要があります。

image.png

ここではエラーの表示方法についていくつか案を出したので参考にしてもらえれば幸いです。

バリデーション結果をdataに持って表示する方法

一番単純なのは手動でバリデーションして、その結果をdataに持つやり方です。vee-validateの自動でバリデーションするメリットを潰してしまいますが、これが一番愚直な方法だと思います。

バリデーション結果をdataに持って表示する方法
<template lang="pug">
ValidationObserver
  div
    ValidationProvider(
      ref="provMin"
      rules="min_value:0|max_value:@max"
      v-slot="{ errors, invalid }"
    )
      input(
        v-model="$data.min"
        :class="{ '-error': invalid }"
        type="number"
      )
    ValidationProvider(
      name="max"
      ref="provMax"
      rules="max_value:10"
      v-slot="{ errors, invalid }"
    )
      //- 両方のエラーのスタイルを当てる場合はref経由でエラーのルールを調べる必要がある(あるいはdataで持っておくか)
      input(
        v-model="$data.max"
        :class="{ '-error': invalid || ($refs.provMin && !!$refs.provMin.failedRules.max_value) }"
        type="number"
      )
  .error {{ $data.errorMessage }}
</template>

<script>
export default {
  data() {
    return {
      min: 0,
      max: 10,
    };
  },
  created() {
    this.$watch(
      () => [this.$data.min, this.$data.max],
      async () => {
        await this.$nextTick();
        // バリデーションしてから結果を代入する
        await this.$refs.provMin.validate();
        await this.$refs.provMax.validate();
        this.$data.errorMessage = this.$refs.provMin.errors[0] || this.$refs.provMax.errors[0];
      }
    );
  },
};
</script>

PortalVueで表示場所を移動する

DOMの場所は変えませんが、PortalVueを使って最終的に表示位置を移動する方法です。手動でバリデートを実行する必要は無くなりましたが、エラー文言を1つだけにする場合はPortalを使うタイミングを調整する必要があるので少し手間です。

PortalVueで表示場所を移動する
<template lang="pug">
ValidationObserver
  div
    ValidationProvider(
      ref="provMin"
      rules="min_value:0|max_value:@max"
      v-slot="{ errors, invalid }"
    )
      input(
        v-model="$data.min"
        :class="{ '-error': invalid }"
        type="number"
      )
      //- エラーの時だけportalを通す
      template(v-if="invalid")
        Portal(to="error")
          div {{ errors[0] }}
    ValidationProvider(
      name="max"
      ref="provMax"
      rules="max_value:10"
      v-slot="{ errors, invalid }"
    )
      input(
        v-model="$data.max"
        :class="{ '-error': invalid || ($refs.provMin && !!$refs.provMin.failedRules.max_value) }"
        type="number"
      )
      //- 前のバリデーションが通っている時だけportalを通す
      template(v-if="invalid && ($refs.provMin && $refs.provMin.flags.valid)")
        Portal(to="error")
          div {{ errors[0] }}
  .error
    PortalTarget(name="error")
</template>

一つにまとめたコンポーネントを使う

今まで見たやり方はrefを使ったり少しトリッキーなことをしたりするので扱いづらかったと思います。なので今度はもうシンプルに入力範囲フォームという一つのコンポーネントを作ってしまい、それをバリデーションするという方法です。
凄くシンプルになりましたが、この場合は片方だけバリデーションするということができなくなります。

一つにまとめたコンポーネントを使う
<template lang="pug">
ValidationObserver
  ValidationProvider(
    rules="range_value:0,10"
    v-slot="{ errors }"
  )
    //- 一つのコンポーネントにまとめる
    InputRange(
      v-model="$data.range"
      :errorMessage="errors[0]"
    )
</template>

終わりに

以上が他のフィールド値も含めてバリデーションする方法でした。どれも一長一短があると思いますが、最後に説明した一つにまとめたコンポーネントを使うのがスッキリしているのかなと思いました。
最後にサンプルコードを共有しますので、興味がある方は是非見てください。

https://codesandbox.io/s/fushuparametanobaridesiyonshinobiaoshifangfanojiantao-6nhxm?file=/src/App.vue

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vuetifyでもっと早く知りたかったこと

はじめに

プログラミング未経験のわたしが初めて UI framework を利用するにあたって、「もっと早く知っておけば!」と思った情報をまとめておきます。

大前提

v-app の中で使用してください。
公式:Application service

See the Pen vuetify needs v-app by msickpaler (@msickpaler) on CodePen.

Grid System

Vuetify.js 2.2 の GridSystem について
この記事見ればだいたい分かります。特に v-container, v-row, v-col についてはこちらを参照してください。

v-navigation-drawer(サイドバー)

メインコンテンツと被ったとき

その時は、メインコンテンツを v-main で囲ってください(Vuetify 使うと決まったらすぐにやっておくべき)。
ちなみにv-snackbarやv-dialogなどが何かと被ったときはcssのv-indexを使って前に出してもokです。

See the Pen navigation without <v-main> by msickpaler (@msickpaler) on CodePen.

なんか表示崩れたとき

サイドバーが原因なら、app プロップス使えば直ります。

See the Pen navbar without app props by msickpaler (@msickpaler) on CodePen.

ユーザーアイコンを一番上に置きたいとき

上ならprepend、下ならappendを指定すればok

See the Pen navbar prepend by msickpaler (@msickpaler) on CodePen.

breakpoint

めちゃくちゃ便利。
公式:Display Breakpoints
以下はサイドバーの例で

  • md 以上の大きさで常時表示
  • sm 以下でトグル式
  • xs 以下でトグル式かつ下から表示

が切り替えられます。

See the Pen toggle by display size by msickpaler (@msickpaler) on CodePen.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】Nuxt実践編:パンくずリストを作ろう

? この記事はWP専用です
https://wp.me/pc9NHC-S8

前置き

スクリーンショット-2020-11-16-20.01.56.png

今回はパンくずリストを作成します?
すごくシンプルに、
コンポーネント作成のコツを
簡単に理解できるので
ぜひやってみてください✨?

構成

アトミックデザイン

⬇️アトミックデザインや
分け方についてはこちら

他にもいくつか書いているので
ブログ内で検索してみてください?

パンくずリストはナビの役割なので
templatesに入れています??

また、パンくずリストは
ヘッダーに入れたりするのが基本ですが、
今回は表示ができれば良いので
index.vueでimportしてもらえればOKです?‍♀️

file
components/
--| templates/
----| navs
------| NavBread.vue

pages/
--| index.vue

使用するもの

CSS

NavBread.vue
fontsize: 12px;
color: rgba(0, 134, 231, 0.8);

paddingは大体で良いです?

⬇️横並びはFlexboxにしましょう!
【Nuxt.js】Nuxt実践編:Flexboxを使おう!

template

ABOUTページを開いている状態で、
TOPへのリンクをしてください?

また、画像はSVGを使用してみましょう!
できる方はSVGコンポーネントを作成しましょう?‍♀️
https://iconmonstr.com/arrow-25-svg/

Let's try!

まずは答えを見ずにやってみましょう♪

答え

? 続きはWPでご覧ください?
https://wp.me/pc9NHC-S8

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】Nuxt実践編:Flexboxを使おう!

? この記事はWP専用です
https://wp.me/pc9NHC-TP

前置き

Frame-15 (1).png

CSSでよく使う
flexプロパティを使ってみましょう?
横並びや中央揃えが
簡単にできるものですね?

時と場合によりますが
floatより便利で高頻度で使います?

⬇️こんな感じで使います❣️

index.vue
display: flex;
justify-content: space-between;
align-items: center;

MDN: CSS フレックスボックスレイアウト

FlexboxとはFlexible Box Layout Moduleのことで、
その名の通りフレキシブルで簡単にレイアウトが組めちゃう素敵ボックスです。
日本語対応!CSS Flexboxのチートシートを作ったので配布します

今までNuxtメインで
肝心のHTML,CSSを
あまりやっていなかったので
少しずつやっていきます??‍♀️

作る物

Frame-16.png

前置きにあった画像の
カード部分です?

ネイルデザインの
カードをイメージしてます?❤️
四角◾️には画像が入ります。
ネイルの名前と画像、
紹介文とタグ、
ネイリストの他の作品も一覧で見る?
といった感じにしています。

⬇️リンク先
ボタンを押すとネイリストのネイル一覧
同じくカードを押すしてもネイル一覧
タグを押すとタグに該当するデザインの一覧

構成

では構成を考えていきましょう??
まずはディレクトリ 、コンポーネントから。

? 続きはWPでご覧ください?
https://wp.me/pc9NHC-TP

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue.js 小数点が省略されたが、表示させたい!(例えば、10->10.0で表示したい)

jsは整数の場合、小数が自動的に省略されたことがついに気づきました。

例えば、10ではなく、10.0で画面で表示したい場合、
postmanでPrettyだと、10で表示しています。「あれ?」と思って、Rawで確認すると、10.0になっています。

vue.jsでどうやって10.0で表示できるの?
色々調べて、下記のコードでできた!

// 負でない整数場合、小数一桁「0]を補足する
var getFloatStr = function (num) {
        if (!/\./.test(num)) {
          num += '.0'
        }
        num = num.match(/\d+\.\d{1}/)[0]
        // console.log(num)
        return num
      }

スクリーンショット 2020-11-27 13.27.04.png

コードの全文

<template>
    <b-card header="結果" bg-variant="light" class="text-center" style="margin-bottom:10px;">
       <b-card-text>
          <div>
          <input style="display:none" type="text" v-model="childrenMessage">
            <element-table
              ref="table"
              :data="data"
              :columns="columns"
              />
            </div>
      </b-card-text>
    </b-card>
</template>
<script>

export default {
  props: ['message'],
  data () {
    return {
      childrenMessage: '',
      columns: [
        [
          {
            title: '順位',
            field: 'ranking'
          },
          {
            title: '点数',
            field: 'score'
          },
          {
            title: '名前',
            field: 'name'
          },
          {
            title: 'メモ',
            field: 'memo'
          }
        ]
      ],
      data: []
    }
  },
  created () {
    this.childrenMessage = this.message
  },
  watch: {
    message (val) {
      const result = this.message

      const arrResult = []
      const objResult = {}

      // 負でない整数場合、小数一桁「0]を補足する
      var getFloatStr = function (num) {
        if (!/\./.test(num)) {
          num += '.0'
        }
        num = num.match(/\d+\.\d{1}/)[0]
        // console.log(num)
        return num
      }
      for (var i = 0; i < result.length; i++) {
        objResult['ranking'] = result[i]['ranking']
        objResult['score'] = getFloatStr(JSON.stringify(result['score']))
        objResult['name'] = result[i]['name']
        objResult['memo'] = result[i]['memo']
        arrResult.push(objResult)
      }
      this.data = arrResult
    }
  }
}
</script>

参考先:
1、js 输入int类型数字后自动在后面加.00,输入double型保留小数点后两位

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue で script で算出した数値・文字列を CSS で利用したい

後で修正します。ポイントは CSS変数をDOMに動的に当てる ところです。
ここに気づけずけっこうハマりました。。。

<template>
  <div class="test" :style="styles">
    <input v-model="color" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue';

export default Vue.extend({
  data() {
    return {
      color: 'black',
    };
  },
  computed: {
    styles() {
      return {
        '--color': this.color,
      };
    },
  },
});
</script>

<style lang="scss" scoped>
$size: 10px;

.test {
  --color: black;  // ここは必ず指定
  color: var(--color);
  font-size: $font-size; // もちろん SCSS の変数とも併用できます。
}
</style>

Options API だけでなく、 Class API でも動作します。もちろん、 Nuxt でも OK です。
安全性のために、 以下の2点は必ず実施してください。

  • デフォルト値の設定(万が一 computed が壊れた等して値が飛んでこなかったら事故に繋がります)
  • SASS系なら対象のスコープを限りなく狭めて使う(想定外の影響を避けてください)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】Nuxt番外編:
アトミックデザインにおけるフォルダの分け方と
サンプル集

? この記事はWP専用です
https://wp.me/pc9NHC-MQ

前置き

コンポーネントの分類の仕方についてと
少しですがサンプルコード集です??

この要素はどこ❓
molecules❓
それともorganisms❓
なんて時にチェックしてください✅?

フォルダ分けはアトミックデザインを推奨しています。
Atomic Designとは

サンプルコードもあるので
コンポーネントの命名や
中身の構成などの参考にも
お役立てください❤️

コードを書き始める前のチェックリストを
見ておくと尚良いと思います✨?

分け方

アトミックデザインに基づく分け方

アトミックデザイン は、
要素の大きさや機能ごとに
ファイルを分けるやり方です✨?

それに乗っ取って分けていますが、
確実な正解・ルールは存在しないので
あくまでも私たちの分け方として
参考にしてくださいね♪

それぞれ、
どの階層のコンポーネントを
読み込んでもOKです?‍♀️

atoms

UIの最小要素。
button, icon, inputなど。

タイトルのh1と、
サブタイトルのpでセットの場合なんかも
1つのまとまりなのでatomsへ?

molecules

atomsを2, 3つ貼り付けたような物?
ul > li のliや
formに入れるlabelつきのinputなど。

organismがformやulなどの
まとまりなので
それを分解した要素です?

InputDefault.vueを
atomで作っていた場合はimportし、
作っていない場合は
FormItemInput.vueで
直接inputを使ってもOKです⭕️

organisms

formやulなど、
ある程度のまとまり。
modalの中身もココ?

templates

modalやnav, Header, Footer
sectionなどの大きなまとまり?

atoms

スクリーンショット-2020-10-23-9.30.02.png

? 続きはWPでご覧ください?
https://wp.me/pc9NHC-MQ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】Vue Router基礎編:params, queryを使ってページ遷移

? この記事はWP専用です
https://wp.me/pc9NHC-eI

前置き

とっても便利なparams, queryについてご紹介?
同じコンポーネントを見せたいけど、
カテゴリごとにURLだけを変えたい…
一覧ページからソートして表示させたい…
そんな時に便利です♪

params, queryについて
いくつかに分けて書きます✍️
router-linkが分かれば簡単です?
まだ不安な方のためにも
複数の書き方で記載しました?

params, queryの違い

まずはURLを見るのが
分かりやすいと思います?

localhost:3000/param/param?query=123

パスパラメーター(param)

?より前の部分、省略できない

クエリパラメーター(query)

?以降の部分、省略できる

directoryとの関係①

localhost:3000/project123
projectごとにURLを変更
表示ページは同じでコンポーネントで表示分け

file
pages/
--| _id/
-----| index.vue

directoryとの関係②

localhost:3000/events?today=true
events/index.vueの中で
today=trueでソートをかけて表示

file
pages/
--| events/
-----| index.vue

eventsは絶対省略できないですね。
pages/events/index.vueに
行けなくなってしまいます。

?today=trueは省略しても
ソートが外れるだけなので
ページはきちんと表示されます♪

メリット

? 続きはWPでご覧ください?
https://wp.me/pc9NHC-eI

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxt.jsのhead内にSEOに必要なmeta情報を追加する

eycatch01.png

Nuxt.jsでSEOに必要なmetaタグの情報を入れていく方法を紹介します。:point_up_tone1:

metaタグとは?

Webサイトのページ情報を検索エンジンに伝えるtagのことです。
metaタグを入力することでこのページはこんな情報を持っていますよということを伝えることができます。
※今回SEO対策が必要なのでSSRを想定しています。

想定されるHTML

今回は下記のようなHTMLを出力することを目標とします。

  • 基本的なmeta要素 + titleタグ
  • OGPに必要なタグ
  • TwitterやFacebookなどSNSに必要なタグ

これらについて解説していきます。

<!DOCTYPE html>
<html lang="ja" prefix="og: http://ogp.me/ns#">
  <head>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- 基本属性 -->
    <title>タイトル</title>
    <meta name="description" content="ディスクリプション">
    <meta name="keywords" content="キーワード">

    <!-- OGPタグ -->
    <meta property="og:site_name" content="サイト名" >
    <meta property="og:type" content="サイトのタイプ">
    <meta property="og:url" content="ページURL">
    <meta property="og:title" content="ページタイトル">
    <meta property="og:description" content="ディスクリプション">
    <meta property="og:image" content="OGP画像URL"> 

    <!-- SNS用 -->
    <meta property="fb:app_id" content="App-ID">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@Twitter">

  </head>

  <body>
  -------- 省略 --------
  </body>
</html>

メタタグの使い方について知りたい方はこちらの記事をどうぞ
metaタグの使い方
OGPを設定しよう!SNSでシェアされやすい設定方法とは?

SSRモードに設定

新規作成ならSPASSR/SSGの選択ができるのでSSR/SSGを選択。

すでにNuxtを作成済みならuniversal(SSR)モードに設定してください。
SPAモードではページごとのmeta反映されません。(させる設定もありますがここでは割愛させていただきます。)

nuxt.config.js
module.exports = {
  mode: 'universal',
  ...
}

nuxt.config.jsにmeta要素を追加

Nuxtでは全体に使うmeta要素をnuxt.config.jsのhead内に記述します。
※1 faviconやCDNの読み込みなどもこちらから行えますが今回はSEOに必要な要素だけ記述しています。
※2 meta要素が重複する場合、先頭にhidを入れておかないとエラーになります。

nuxt.config.js
export default {
  head: {
    htmlAttrs: {
      lang: 'ja',
      prefix: 'og: http://ogp.me/ns#'
    },
    titleTemplate: '%s - ' + 'タイトル',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'サイトの説明' || '' },
      { hid: 'keywords', name: 'keywords', content: 'キーワード1,キーワード2,キーワード3' },

      { hid: 'og:site_name', property: 'og:site_name', content: 'サイト名' },
      { hid: 'og:type', property: 'og:type', content: 'サイトのタイプ' },
      { hid: 'og:url', property: 'og:url', content: 'サイトURL' },
      { hid: 'og:title', property: 'og:title', content: 'サイトタイトル' },
      { hid: 'og:description', property: 'og:description', content: 'サイトの説明' },
      { hid: 'og:image', property: 'og:image', content: 'サイトURL' },

      { hid: 'fb:app_id', property: 'fb:app_id', content: 'App-ID' },
      { hid: 'twitter:card', name: 'twitter:card', content: 'summary_large_image' },
      { hid: 'twitter:site', name: 'twitter:site', content: '@Twitter' }

    ],
  },
}

htmlAttrsで言語設定、prefixでOGPを使いますよと宣言します。
titleTemplateで全ページに「ページ名 - タイトル」を出力させます。%sの部分がそれぞれのページで設定したタイトルが表示されます。

Topページの設定

headタグの中の要素は下記のように記述します。
titleTemplatenullすることでnuxt.config.jsで設定したものを反映させずにすみます。
そしてtitleにTopページのタイトルを入力をすることでtitleタグに表示することができます。
※これを設定しておかないと「タイトル名 - タイトル名」のようになり重複してしまいます。

pages/index.vue
<template>
  <main>
    <h1>サイトタイトル</h1>
  </main>

</template>

<script>
export default {
  head: {
    titleTemplate: null,
    title: 'サイトタイトル'
  }
}
</script>

各ページごとの設定

Topページ以外の書き方です。
nuxt.config.jsで設定したtitleTemplateの機能を使います。
head内のtitle,metaに内容を追加することで反映されます。

pages/about.vue
<template>
  <main>
    <h1>各ページのタイトル</h1>
  </main>

</template>

<script>
export default {
  head: {
    return {
      title: 'ページ名',
      meta: [
        { hid: 'description', name: 'description', 'ページの説明' },
        { hid: 'keyword', name: 'keyword', 'ページのキーワード' },
        { hid: 'og:type', property: 'og:type', 'article' },
        { hid: 'og:title', property: 'og:title', content: 'ページ名' },
        { hid: 'og:description', property: 'og:description', content: 'ページの説明' },
        { hid: 'og:url', property: 'og:url', content: 'https://hogehoge.com/about' },
        { hid: 'og:image', property: 'og:image', content: 'https://hogehoge.com/img/ogp/about.jpg' },
      ],
    }
  }
}
</script>

dataに情報をまとめる

dataに情報をまとめることでogp用のタグのtitleやdescriptionなどを使い回せることができます。

pages/about.vue
<script>
export default {
  data () {
    return {
      meta: {
        title: 'ページ名',
        keyword: 'キーワード'
        description: 'ページの説明',
        type: 'article',
        url: 'https://hogehoge.com/about',
        image: 'https://hogehoge.com/img/ogp/about.png',
      },
    }
  },
  head: {
    return {
      title: this.meta.title,
      meta: [
        { hid: 'description', name: 'description', this.meta.description },
        { hid: 'keyword', name: 'keyword', this.meta.keyword },
        { hid: 'og:type', property: 'og:type', this.meta.type },
        { hid: 'og:title', property: 'og:title', content: this.meta.title },
        { hid: 'og:description', property: 'og:description', content: this.meta.description },
        { hid: 'og:url', property: 'og:url', content: this.meta.url },
        { hid: 'og:image', property: 'og:image', content: this.meta.image },
      ],
    }
  }
}
</script>

Mixinを作成し共通化する

下層ページに毎回同じことを書くのであればMixin化をすることで使い回せることができます。

assetsフォルダ内にmixinsフォルダを作成

assetsフォルダにmixinsフォルダを作成します。そのなかにmeta.jsファイルを作ります。
先程作ったhead内のソースをそのままもってきます。

assets/mixins/meta.js
export default {
  head: {
    return {
      title: this.meta.title,
      meta: [
        { hid: 'description', name: 'description', this.meta.description },
        { hid: 'keyword', name: 'keyword', this.meta.keyword },
        { hid: 'og:type', property: 'og:type', this.meta.type },
        { hid: 'og:title', property: 'og:title', content: this.meta.title },
        { hid: 'og:description', property: 'og:description', content: this.meta.description },
        { hid: 'og:url', property: 'og:url', content: this.meta.url },
        { hid: 'og:image', property: 'og:image', content: this.meta.image },
      ],
    }
  }
}

下層ページでの使い方

import Meta from '~/assets/mixins/meta'をscriptのあとに追加し、
export default内にmixins: [Meta]を追加します。
head ()は削除します、

pages/about.vue
<template>
  <main>
    <h1>各ページのタイトル</h1>
  </main>

</template>

<script>
import Meta from '~/assets/mixins/meta'

export default {
  mixins: [Meta],
  data () {
    return {
      meta: {
        title: 'ページ名',
        keyword: 'キーワード'
        description: 'ページの説明',
        type: 'article',
        url: 'https://hogehoge.com/about',
        image: 'https://hogehoge.com/img/ogp/about.png',
      },
    }
  }
}
</script>

Nuxtでのmixinの使い方にかんしてはこちらの記事を参照
https://note.com/aliz/n/nb87adb4d4810

出力されるHTL

genarateしたときにこんな感じ出力されます。

index.html
<head>
  <title>ページタイトル</title>
  <meta data-n-head="ssr" charset="utf-8">
  <meta data-n-head="ssr" name="viewport" content="width=device-width,initial-scale=1">
  <meta data-n-head="ssr" data-hid="description" name="description" content="ページの説明">
  <meta data-n-head="ssr" data-hid="keywords" name="keywords" content="キーワード">
  <meta data-n-head="ssr" data-hid="og:type" property="og:type" content="airticle">
  <meta data-n-head="ssr" data-hid="og:url" property="og:url" content="https://hogehoge.com/about">
  <meta data-n-head="ssr" data-hid="og:title" property="og:title" content="ページタイトル">
  <meta data-n-head="ssr" data-hid="og:description" property="og:description" content="ページの説明">
  <meta data-n-head="ssr" data-hid="og:image" property="og:image" content="https://hogehoge.com/img/ogp/about.png">
  <meta data-n-head="ssr" data-hid="twitter:card" name="twitter:card" content="summary_large_image">
  <meta data-n-head="ssr" data-hid="twitter:site" name="twitter:site" content="@ACALL_JP">
 <!-- 省略 -->
</head>

以上でNuxt上でhead内にseoで必要なmeta情報を追加する方法でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VeturをインストールしてもEmmetが動作しない時の対処法

こんばんは
アロハな男、やすのりです!

今日は、Vue.jsでプログラミングしていく上で、必須級とも言われているVeturという拡張機能の.vueファイルでのEmmet動作がうまくいかず、解決するまでに時間がかかったので備忘録も兼ねて書いていこうと思います。

まず、結論から述べますと...

結論

拡張機能の設定画面でEmmetと検索して、下記画像のチェックボックスにチェックを入れると、TabボタンでのEmmet記法が有効化されます!!
スクリーンショット 2020-11-27 1.02.00.png

そもそもEmmet記法って?

Emmet記法とは、HTMLやCSSをコーディングしていく際にタグやプロパティの一部だけを入力するだけで、タグやプロパティを生成する為の記法です。

具体例をあげると、

例:div#test Tabキーを押すと → <div id='test'></div>

こんなふうにHTMLタグを作成できたり、

例:w100 Tabキーを押すと → width: 100px;

CSSのプロパティの記述が簡単にできたりします。

ただ、これは通常の.htmlファイル等だとTabキーを押さなくても、下記画像の様に変換先の候補が表示されていて、該当の候補を選択することで同じことが実現できていました。

スクリーンショット 2020-11-27 1.17.25.png

ですが、こと.vueファイルでは通常ではこの動作が適用されていませんでしたので使うことができませんでした。

Vetur

そこで登場するのが、冒頭でも紹介したVeturという拡張機能です。
↓英語になりますが、こちらにVeturの設定方法や拡張機能の説明が載っています。
https://vuejs.github.io/vetur/

VeturをVSCodeにインストールすることにより、拡張機能の中の1つとして.vueファイル内でのEmmet記法動作があります。

よし、それならこれをインストールすれば万事解決っ!!とはならず...

Image from Gyazo
この様にinputタグを作成しようとしてみても候補はおろか、Tabキーを押しても何も起きない状況でした...

『何か設定が必要なのかな...でも、いろんな人の記述を見てみてもVeturをインストールするだけで大丈夫って書いてあるし...』と八方塞がりな状態でした。

そんな中、下記のQiita記事を発見することができました!!
【高速コーディング】Emmetを使ってみよう!

この記事のおかげで設定の中のチェックボックスにチェックを入れることを知ることができました。

しかし

結果として、.vueファイルでもEmmet記法が使える様になりましたが、この様な設定をしないといけないとはVetur関連の記事を読んでも書いてはいませんでしたし、元々.htmlではEmmet記法を使用できていました...

これは私の環境下だけでの事象なのかどうなのか...ゆくゆくは原因を突き止めたいですね。

もし、私と同じ様な状況になった人は設定を今一度確認してみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue/Nuxt】Vercelへのリリースで環境変数を読み込ませた

VercelのEnvironment UIでの環境変数の設定は割愛します。

Vercelの操作はビビるくらい簡単なので、説明するより触った方が良いです。

また、VercelにリリースしたNuxt.jsのプロジェクトで環境変数を読み込ませるには、nuxt.config.jsにenvを設定すれば良かっただけの話でした。

nuxt.config.js
require('dotenv').config()
export default {
  modules: [
    "@nuxtjs/dotenv",
  ],
  dotenv: { path: process.cwd() },
  env: {
    API_KEY: process.env.API_KEY,
    API_URL: process.env.API_URL,
  },
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む