20200214のvue.jsに関する記事は12件です。

vueで出会う「$」について

vue.jsを扱っていると、時々「$」に出会います。
例えば

db.collection("twits").doc(this.$props.id),

これは何なのかわからなかったので調べました。

https://tutorialmore.com/questions-266496.htm

その他でも説明されていますが、これはvueが元々持っているネイティブのプロパティを使う場合に必要となるものです。

props というプロパティは元々vueに備わっているものなので、 $ が必要ということです。

ちなみに main.js にある $mount は、elプロパティと同じことを行うことができるメソッドです。
$mount は引数を取り、テンプレートをマウントしたい要素を決めることが可能です。

また一つ学びました。

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

vue-routerで親子間でのイベント処理

概要

vue-router使用時の「子→親」あるいは「子1→子2」のイベント渡しの記述方法について自分用メモ

:warning:ソースコードは簡略化したもので、ちゃんとテストしていないので動かないかも

サンプルコード

this.$router.app.$on を扱うのがポイント。それ以外は通常のイベントバスのやり方と同じ。

主要な部分

app.js
//(前略)
const app = new Vue({
    router, // これが「ルーターインスタンスを root インスタンスに router オプションとして」かな?
    el: '#app',
    render: h => h(App)
});

親コンポーネント

parent.vue
<template>
    <div>  
        <child1></child1>
        <child2></child2>
    </div>
</template>

<script>
// 子2つを配置するのみ
import component_child1 from './child1.vue'
import component_child2 from './child2.vue'

export default {
    components: {
      'child1': component_child1,
      'child2': component_child2
    }
};
</script>

子コンポーネント(2つ)

目標とする動作は下記。

  1. child1でボタンを押すと test_method_child1 が実行される。
  2. test_method_child1 内で test_event_global がスローされ、child1は非表示。
  3. child2でイベントの解除(重要、後述。参考資料を参照。)
  4. child2ではイベントを test_event_globaltest_event_child2 としておく。
  5. child2でイベントを受け取ったら、v-on:test_event_child2test_method_child2 が実行。
  6. child2が表示され、Hello Worldが見える。
child1.vue
<template>
    <div v-show="visible_child1">
       <button v-on:click="test_method_child1">Run Test</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            visible_child1 : true  // 表示/非表示制御
        };
    },
    methods: {
        test_method_child1() {
            this.visible_child1 = false;
            // イベントバスを this.$router.app として、イベントをスロー
            this.$router.app.$emit('test_event_global');
        }
    }
}
</script>
child2.vue
<template>
    <div v-on:test_event_child2="test_method_child2" v-show="visible_child2">
       Hello world !!
    </div>
</template>

<script>
export default {
    data() {
        return {
            visible_child2 : false // 表示/非表示制御
        };
    },
    mounted() {
        // イベントバスを this.$router.app として、コンポーネントのイベントに紐づけている
        this.$router.app.$off('test_event_global');
        this.$router.app.$on('test_event_global', this.test_event_child2);
    },
    methods: {
        test_method_child2() {
            this.visible_child2 = true;
        }
    }
}
</script>

注意点

解除が行われない、というより .$off をしないと蓄積するようです

ページ遷移してcreatedやmountedが何度も呼ばれると、そのたびに蓄積されてしまうらしい。
( beforeDestroyかdestroyedの中で解除すればいいのかな )


上記は例。$onでメソッドを直接叩くこともできるはず。
表示/非表示みたいなことを実現するだけならv-onは取ってしまって

child2.vue
<div v-show="visible_child2">
(中略)
this.$router.app.$on('test_event_global', this.test_method_child2);

とすることも。

参考資料

  1. Vue Router / API リファレンス
  2. Vue.js のグローバルイベントバスでの親子間以外の通信と vue-router
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ユーザー目線のVueコンポーネント実装

この記事について

Vueを開発・運用してアプリケーションの規模が段々増えてきました。

チームの人員も増やしていく中で慣れていないエンジニアがコンポーネントの実装に関わるというケースが増えてきて、どんなデータ構造やアクション定義を作るのが良いのか悩んでいるケースを見受けるようになりました。

今回は自分がコンポーネントを実装する時に考えていることを簡単に紹介しておきます。

コンポーネントはユーザーに最も近いコード

コンポーネント思考で実装していくと、ユーザーと近い距離に居るコードは各コンポーネント郡になります。言い換えるとコンポーネントとユーザーは密接な関係にあり、お互いの共通認識が合っていることが望ましいということになります。

利用するユーザーの思い浮かべるデータ構造や行動と実装されたコードの変数や関数が同じであるということです。つまりコンポーネントを使うユーザー側の気持ちがわからなければコンポーネントの実装も困難ということです。

サンプルです。

<template>
  <div>
    ...何かしらのコンテンツ

    <button @click="toggleFavorite">
      <template v-if="favorite">
        いいね!を解除
      </template>

      <template v-else>
        いいね!する
      </template>
    </button>
  </div>
</template>

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

export default Vue.extend({
  data() {
    return {
      favorite: false
    }
  },
  methods: {
    toggleFavorite() {
      this.favorite = !this.favorite
    }
  }
})
</script>

何かしらのコンテンツに対していいね!したりするサンプルです。この実装には2つの問題点があります。

  • ユーザーにとってはいいね!なのにコード上ではお気に入りという変数名になっている
  • いいね!を変更する処理がコード上では同一の関数で定義されている

どちらも動作上は問題ありません。バグもありません。ですが後々の機能追加や変更などで破壊的変更をする必要が出てしまうコードで良いコードとは言えません。何故ならユーザーの行動原理から外れている実装だからです。

ユーザー側の名称でデータ構造を定義

favorite をいいね!として扱う場合、機能追加で「お気に入りを追加したい」と言われた時にどうでしょうか? favorite2 と定義してやり過ごすことはできますが、今後コードを見た人が混乱してしまうと思います。

古くから運用しているサービスになると歴史上データベースやAPIが favorite になっているケースがあります。サンプルではバックエンドと連携していませんが、こういったアプリケーションのサービス内の名称とユーザー側の名称が違う問題はそのままコンポーネントの実装にまで影響してしまうケースが多くあります。

統一することが理想ですがデータベースごと名称の変更を全て反映するのは規模によっては難しいです。でも差異を無くしておくことはできます。

フロントエンドは比較的変更がやりやすい分類なのでこういったものは先にフロントエンド側で吸収しておくことで、機能追加や改善・インフラ整備の時に役立つことになるでしょう。

ユーザーの行動に沿った関数を定義

toggleFavorite という関数は効率的です。ですがユーザーの意思とは連動していません。

極端な例ですが、例えば「誤動作を避ける為にいいねする時だけ確認のアラートをして欲しい」といったユーザーの要望を反映する時にどうでしょうか?両方の機能を内包している為、片方のアクションに対して何か付加価値を付け足す時に拡張しにくいと感じませんか?

ユーザーにとって「いいね!する」という行動と「いいね!を解除する」という行動は全く別の意思から行われるアクションです。こういったユーザーの行動ごとに特殊な処理を挟むケースはフロントエンドではとても多いです。経験上Vuexでステート管理すると更に複雑化していきます。

「関数は最低限の方が...」「HTML上では同じ場所にあるボタンなのに...」と思うこともあるかもしれません。ですが、あくまでアプリケーションは利用するユーザーの為に動くべきであり、機能追加や変更もユーザーの行動結果から発生していくものです。

修正後のコードです。

<template>
  <div>
    ...何かしらのコンテンツ

    <button v-if="like" @click="unlikeContent">
      いいね!を解除
    </button>

    <button v-else @click="likeContent">
      いいね!
    </button>
  </div>
</template>

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

export default Vue.extend({
  data() {
    return {
      like: false
    }
  },
  methods: {
    likeContent() {
      this.like = true
    },
    unlikeContent() {
      this.like = false
    }
  }
})
</script>

コンポーネントの実装 = ユーザーの意思

この考え方はテストケースも作成しやすい利点があります。

toggleFavorite は現実のユーザーの行動と反しています。 likePostunlikePost を実行してデータ構造をチェックする方がよりユーザーの行動に近いテストケースになると思います。

同じようにバグの発生源を特定する上でも有効です。問い合わせなどのユーザーの行った行動がそのまま再現手順に近くなり、関連するデータやメソッドに対してデバッグを行えば見つかりやすくなります。

実装上ではとても小さなことですが、こういった考えが規模の大きくなったアプリケーションにおいて効果的になっていきます。まずはユーザーの気持ちになって脳内でコンポーネントを操作するイメージを掴むことが大事です。

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

【Nuxt.js】Vuex基礎編:コードをスッキリさせよう

前置き

Happy Valentine❤️?
ということで(?)本日はVuex!
3つに分けて書きます✍️
・vuexとは何か
・メリットは
・簡単な使い方

公開予定日を過ぎ、
申し訳ございません?‍♀️
自社開発アプリを進めておりました?

Vuexとは

状態管理のライブラリです。
って言ってもイメージ沸かないので…

簡単に言うとデータ保存ができるもの
・ログイン情報が
 ページ遷移後も保持されたり、
・APIのデータ引っ張ってきて保存とか、
・methodsに何度も同じ処理書かずに済む
とかとか。
$emitも何回も書かなくていいし楽!
とにかく楽!!!そんな感じです。

状態保持をするのでstoreに書きます✍️

メリット

上記の内容がそのままメリット
コードもまとまって楽ちんなのは
このあとの未使用・使用の比較
を見ていただければ分かります?

使い方

とにかくまずインストール

ターミナル
npm install vuex --save

https://vuex.vuejs.org/ja/installation.html

使い方(超簡単ver.)

vuex.gif

まずは分かりやすく
components使わず
pagesだけで完結させます。

store/index.js
export const state = () => ({
 counter: 0
})

export const mutations = {
 increase(state) {
   state.counter++
 },
 decrease(state) {
   state.counter--
 }
}
index.vue
<template>
 <div class="container">
   <button @click="increase">increase</button>
   <button @click="decrease">decrease</button>
   {{ $store.state.counter }}
 </div>
</template>

<script>
export default {
 methods: {
   increase () {
     this.$store.commit('increase')
   },
   decrease () {
    this.$store.commit('decrease')
   },
 },
}
</script>

??
今度はvuexを使用しない場合
それぞれの対応箇所が分かりますね。
・dataがstate
・methodsがmutations

index.vue
<template>
<div class="container">
  <button @click="increase">increase</button>
  <button @click="decrease">decrease</button>
  {{ counter }}
</div>
</template>

<script>
export default {
 data () {
   return {
     counter: 0,
   }
 },
methods: {
  increase () {
   this.counter++;
  },
  decrease () {
   this.counter--;
  },
},
}
</script>

使い方(Components使用ver.)

vuex.gif

作るものは全く同じです。
コンポーネント化するだけです!

?Point
・index.jsはバグるので新しいjsファイルを作成。
・そのため呼び出し方が変わります。
・gettersでstateの状態を取得する必要あり。

counter.js
export const state = () => ({
 counter: 0
})
export const mutations = {
 increase(state) {
   state.counter++
 },
 decrease(state) {
   state.counter--
 }
}
export const getters = {
 counter: state => {
   return state.counter
 }
}

Counter.vue(子コンポーネント)
ここで呼び出し方が
'ファイル名/定義した物' に変わります?

Counter.vue
<template>
<div class="container">
  <button @click="$store.commit('counter/increase')">increase</button>
  <button @click="$store.commit('counter/decrease')">decrease</button>
  {{ counter }}
</div>
</template>

<script>
export default {
 computed: {
   counter () {
     return this.$store.getters['counter/counter']
   },
 },
}
</script>

index.vue(親ページ)
親には何も書かず超スッキリ??

index.vue
<template>
 <div class="container">
   <Counter />
 </div>
</template>

<script>
import Counter from '~/components/Counter.vue';

export default {
 components: {
   Counter,
 },
}
</script>

??
vuexを使わないと
$emitとか親でどう処理するかとか
いちいち分けたり何度も書く必要が出てきます。

Counter.vue(子コンポーネント)
<template>
<div class="container">
  <button @click="$emit('increase')">increase</button>
  <button @click="$emit('decrease')">decrease</button>
  {{ counter }}
</div>
</template>

<script>
export default {
 props: {
   counter: Number
 },
}
</script>
index.vue(親ページ)
<template>
 <div class="container">
   <Counter
     :counter="counter"
     @increase="increase"
     @decrease="decrease"
   />
 </div>
</template>

<script>
import Counter from '~/components/Counter.vue';

export default {
 components: {
   Counter,
 },
 data () {
   return {
     counter: 0
   }
 },
methods: {
  increase () {
    this.counter++;
  },
  decrease () {
    this.counter--;
  }
},
}
</script>

記事が公開したときにわかる様に、
note・Twitterフォローをお願いします?
https://twitter.com/aLizlab

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

Vue v2.6.11のバグを発見

Vueのバグを発見しました。

PR: https://github.com/vuejs/vue/pull/11107

事象

async componentでv-if="false"を使うと、vueのvdom処理でエラーになる。

詳細はPRのテストコード参照。

原因

vdomでは、async componentはasyncPlaceholder(コメントノード + 補助データ)として扱われる。
v-if="false"はコメントノードとして扱われる (参考: https://github.com/vuejs/vue/issues/5117 )。

patch.jsのsameVNodeでは、async componentとコメントノードが同じと判定されてしまう(これが誤り)。

sameVNodeで同じと判定されると、patchVNode処理に入り、その中のasyncFactory.resolvedで、asyncFactoryがundefinedでエラーになる。

修正

sameVNodeでasync componentとコメントノードが同じと判定されないようにする。

メモ

data-server-renderedはルートにのみつくらしい。
hydrationするときに取り除くので、hydrationは一回のみ実行される。
hydrationのときにロードできないasync componentはasyncPlaceholderにされる(つまり、async component内部はhydrationの対象外になる)。

コードを見た感じ、hydrationのときにすでにresolveされているasync componentは通常のコンポーネントとほぼ同様に処理されるみたい。

感想

nuxtでパフォチューをやっているときに遭遇した。

セキュリティ懸念(誤ってキャッシュされるとか、リクエスト間で情報が漏れるとか)から、SSRでは認証が必要なデータは取得しないようにしている。
非ログインユーザーはSSRで完結するのでクライアント側でデータ取得しなくて良い。
ログインユーザーはクライアント側でデータ取得するが、今まではmount後にリクエストを開始していて遅かったので、mount前にリクエストを開始するようにした。
それでこのバグが発生。

最初、hydrationが行われる前にリクエストが返ってきて、SSRとクライアントのdom不整合かなと思ったが、データ更新を強制的にmount後や、mount後のnextTick後にしても発生する。

vue内部のresolvedでエラーになっていることがわかったので、vueのコードを検索したらpatch.jsを発見。

async componentがresolveされる前に、v-if="false"でvdom更新されるとエラーになることを発見。

結局、パフォチューで速くなったせいで、async componentのロードとデータ更新のタイミングが逆転してバグが発生したみたい。

自分のコードが原因だと思って1日くらいかかった。
これでvueのコントリビューターの肩書を得た。

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

Vue v2.6.11のバグを発見 (勘違いの可能性もあり)

Vueのバグを発見しました。 (勘違いの可能性もあり)

PR: https://github.com/vuejs/vue/pull/11107

事象

async componentでv-if="false"を使うと、vueのvdom処理でエラーになる。

詳細はPRのテストコード参照。

原因

vdomでは、async componentはasyncPlaceholder(コメントノード + 補助データ)として扱われる。
v-if="false"はコメントノードとして扱われる (参考: https://github.com/vuejs/vue/issues/5117)。

patch.jsのsameVNodeでは、async componentとコメントノードが同じと判定されてしまう(これが誤り)。

sameVNodeで同じと判定されると、patchVNode処理に入り、その中のasyncFactory.resolvedで、asyncFactoryがundefinedでエラーになる。

修正

sameVNodeでasync componentとコメントノードが同じと判定されないようにする。

感想

nuxtでパフォチューをやっているときに遭遇した。

セキュリティ懸念(誤ってキャッシュされるとか、リクエスト間で情報が漏れるとか)から、SSRでは認証が必要なデータは取得しないようにしている。
非ログインユーザーはSSRで完結するのでクライアント側でデータ取得しなくて良い。
ログインユーザーはクライアント側でデータ取得するが、今まではmount後にリクエストを開始していて遅かったので、mount前にリクエストを開始するようにした。
それでこのバグが発生。

最初、hydrationが行われる前にリクエストが返ってきて、SSRとクライアントのdom不整合かなと思ったが、データ更新を強制的にmount後や、mount後のnextTick後にしても発生する。

vue内部のresolvedでエラーになっていることがわかったので、vueのコードを検索したらpatch.jsを発見。

async componentがresolveされる前に、v-if="false"でvdom更新されるとエラーになることを発見。

結局、パフォチューで速くなったせいで、async componentのロードとデータ更新のタイミングが逆転してバグが発生したみたい。

自分のコードが原因だと思って1日くらいかかった。
これでvueのコントリビューターの肩書を得た。

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

Nuxt.js - Firebaseへのデプロイ & 独自ドメインの設定

deploy.png

Nuxt.jsで作成したSPAアプリケーションをFirebaseにデプロイする方法をいつも忘れるので、メモしておきます。

プロジェクトの追加

Firebaseへ行き、Googleアカウントでログイン後、コンソールに移動します。

"プロジェクトを追加"から、プロジェクトの追加を行います。

スクリーンショット 2020-02-14 13.07.05.png

スクリーンショット 2020-02-14 13.08.44.png

・Googleアナリティクスの設定

ここでは、とりあえず無効にしておきます。

有効にすると、アナリティクスアカウントの設定が必要です。

スクリーンショット 2020-02-14 13.10.38.png

これで完了です。

スクリーンショット 2020-02-14 13.12.45.png

firebase-tools

次に、firebase-toolsのインストールを行います。

$ npm install -g firebase-tools

インストール後、ログインします。

ブラウザが開くので、GoogleアカウントでログインすればOKです ;)

$ firebase login

デプロイしたいプロジェクトのディレクトリに移動し、init

$ firebase init

いくつかの質問があります。

今回はHostingを利用するので、スペースで選択し、Enter。

スクリーンショット 2020-02-14 13.25.10.png

次に、"Use an existing project" を選択します。

冒頭の「プロジェクトを追加」で追加した、プロジェクト名を選択します。

スクリーンショット 2020-02-14 13.29.14.png

"dist"と入力。

スクリーンショット 2020-02-14 13.32.53.png

SPAとして設定するかを聞かれます。

私は、SPAで作成しているので、yを入力します。

スクリーンショット 2020-02-14 13.34.39.png

これで設定は完了です!

Deploy

$ npm run generate
$ firebase deploy

完了すると、最後にURLが表示されるので、アクセスしてみます。

無事、Firebaseにデプロイすることができました :)

スクリーンショット 2020-02-14 13.39.50.png

コードを追加したり、修正した場合には、再び以下のコマンドを打てばOKです ;)

$ npm run generate
$ firebase deploy

スクリーンショット 2020-02-14 15.14.05.png

独自ドメインの設定

Firebaseのコンソールページに行き、独自ドメインを設定したいプロジェクトを選択します。

次に、左サイドバーのHostingを選択。

スクリーンショット 2020-02-14 13.51.51.png

"カスタムドメインを追加"をクリック。

スクリーンショット 2020-02-14 13.55.36.png

あとは、お名前.comなどで取得したドメインを入力し、従えばOKです ;)

反映するのに、少し時間がかかると思います。

スクリーンショット 2020-02-14 13.58.05.png

説明不足だと感じた点や、変更点が出てきましたら、随時更新していきたいと思います。

この記事が参考になりましたら幸いです。

Thanks,
@ShogoMurakami

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

ハッシュタグで検索するWEBデザイン検索サービス「Lplove」をリリースしました

初めて投稿します。普段はQiitaをよく見ていて、つまづいた時にとても助かっています。ありがとうございます。

先ほどハッシュタグで検索するWEBデザイン検索サービス「LPlove」をリリースしました。リンクはこちらです(https://lp-love.com/)

temp.png

昨年11月から本格的に作り始めて、ほぼ3ヶ月で作りました。メインはFirebaseとNuxt。SSRで作っています。ドメインがroute53なのを除いて、残りは全部FIrebaseでできています。

仕事の合間を縫って一人で作りましたが、正直大変でした。たまに一人で全部作る方を見かけますが、こんなに大変なのかと思い知らされました。

このサービスは、普段デザインの仕事をしていて「デザインまとめサイトじゃ探すのが大変!」「かといってPinterestじゃ誰がこのデザインを良いと思っているのか分かりづらい」「もっとデザイン共有できないかな」と思って、ピンタレストとインスタの間を目指して作りました。

これから大きくしていく中で、デザイナーさんが探しやすい、共有しやすいサービスになれば良いと思います。

とりあえず、リリース直後なので不具合がたくさん出るだろうな、と不安でいっぱいですが、不具合見つけたらコメントでどんどん言ってもらえると本当に助かります!またデザイナーさんも「こんな機能が欲しい」などあったらどんどんください。めちゃくちゃ励みになります!

またちょっと休んだらこのサービスの作った過程やソースなどを随時公開していけたらと思います。

とりあえず、
Lplove(https://lp-love.com/)
をよろしくお願いします!

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

Vue/Nuxtで`is-active`みたいなclassを条件によって追加しようとしたら'v-bind' directives require an attribute value.と出る件

小ネタ。特に

  • NuxtでESLintを有効にし
  • CSSフレームワークをBulmaにして(is-activeとかのclass名をよく使うため)
  • ハイフン付きのis-activeとかのclassを 条件によって追加しようとすると

遭遇しやすいです。

require an attribute value. って言われてもわかりづらいよ!

Vue/Nuxtで条件によってHTMLのclassを動的に変更したい場合、 Vue.jsのドキュメント で紹介されていますが、

「HTMLクラスのバインディング」の例
<div v-bind:class="{ active: isActive }"></div>

そのとおりに is-active などのclassを追加しようとする次のエラーが発生します。

'v-bind' directives require an attribute value.

v-bindで失敗する例
<template>
  <div 
    :class="{ is-active: isDropdownShown }"
    class="dropdown" 
  >
...
</div>
</template>

「attribute valueを設定したはずなのにどうして…?」と考えてしまうとハマり始めます。

解決法: 追加しようとするクラス名をシングルクォーテーションで囲む

これだけです。class名に - が含まれている場合、そのままだとattribute valueとして認識されません。

追加しようとするクラス名をシングルクォーテーションで囲む
<template>
  <div 
    :class="{ 'is-active': isDropdownShown }"
    class="dropdown" 
  >
...
</div>
</template>

JavaScriptの識別子…Objectのkey…と考えると気づきやすいですね!

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

【JavaScript】Vue.js(Element UI)を使用している際に「async-validator」単体で使う場合のカスタムバリデーション実装方法

概要

Vue.js(Element (Element UI))を使用している場合に「async-validator」単体で使う実装方法例を少々

インストール(npm)

async-validator - npm

npm i async-validator

※筆者はElement (Element UI)(Vue.jsのコンポーネントライブラリ)を使用しているので別途インストールしなくても使える状況ですので単体でインストールしたことはないです

実装例

簡単なアカウント登録画面の例として以下のように実装してみました

form.vue
<template>
    <div class="form">
        <div class="text-center">アカウント登録</div>

        <input type="email" v-model="ruleForm.email" placeholder="メールアドレス*">
        <input type="password" v-model="ruleForm.password" placeholder="パスワード*">
        <input type="password" v-model="ruleForm.passwordConf" placeholder="パスワード(確認)*">

        <div class="text-center">
            <input type="button" @click="beforeSubmit" value="登録">
        </div>

    </div>
</template>

<script>
import schema from 'async-validator';

export default {
    data() {
        // カスタムバリデーション定義する場合はここに記述
        var validatePasswordConf = (rule, value, callback) => {
            if (value === '') {
                callback(new Error('パスワード(確認)を入力してください。'));
            } else if (value !== this.ruleForm.password) {
                callback(new Error('二つのパスワードが異なります。'));
            } else {
                callback();
            }
        };
        return {
            // フォーム用変数
            ruleForm: {
                email: '',
                password: '',
                passwordConf: '',
            },
            // バリデーションルール定義(項目毎)
            rules: {
                email: [
                    { required: true, message: 'メールアドレスを入力してください。', trigger: 'blur' },
                    { type: "email", message: '正しいメールアドレスを入力してください。', trigger: 'blur' },
                    { min: 1, max: 255, message: '1文字以上255文字以内で入力してください。', trigger: 'blur' }
                ],
                password: [
                    { required: true, message: 'パスワードを入力してください。', trigger: 'blur' },
                    { min: 1, max: 50, message: '1文字以上50文字以内で入力してください。', trigger: 'blur' }
                ],
                passwordConf: [
                    // 上記で定義したカスタムバリデーションを使用
                    { validator: validatePasswordConf, trigger: 'blur' }
                ],
            },
        }
    },
    methods: {
        beforeSubmit() {
            var validator = new schema(this.rules);
            validator.validate(this.ruleForm, (errors, fields) => {
                if(errors) {
                    // バリデーションエラー時
                    return alert(errors[0]["message"]);
                }
                // バリデーションパス
                return alert("登録しました");
            });
        },
    }
}
</script>

バリデーションのルール詳細は「async-validator」のREADMEとかを参考にしてください。

参考URL

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

Dark Sky APIで値を取ってきたらエラーがでる

問題

Vue.jsとFirebaseを使ってお天気アプリ作成中にDark Sky APIから値を取ってこようとしたら下記エラーがでた
スクリーンショット 2020-02-03 14.49.47.png

解決

urlの前にhttps://cors-anywhere.herokuapp.comをつける

weather-mixin.js
getTemperature() {
      this.$axios
        .get(
          "https://cors-anywhere.herokuapp.com/https://api.darksky.net/forecast/APIキー/37.8267,-122.4233",
          {}
        )
        .then(result => {
          console.log("結果", result);
          this.temperature = Temperature.create(result);
          console.log("temp", this.temperature);
        })
        .catch(error => {
          console.log(error);
        });
    }

スクリーンショット 2020-02-13 19.00.39.png

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

[JavaScript] スプレッド構文

See the Pen リストにリストの追加 by mykysyk (@mykysyk) on CodePen.

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