- 投稿日:2021-01-01T23:02:08+09:00
Vue.jsで非同期処理関数を作る方法
皆さんこんにちは!!!
今回はVue.jsで非同期処理関数を作る方法をご紹介します!
めちゃめちゃ簡単なので、ぜひ学習の参考にしてください。
それでは説明していきます。
Promiseを用いて関数を作成
今回はTimeoutの関数を非同期処理で行います。
Vue.jsで非同期処理関数を作成する際は、宣言時にPromiseを利用するのではなく、返り値として利用します。
App.vue<script> export default{ methods: { sleep(mesc) { return new Promise((resolve) => { setTimeout(resolve, mesc) }) } }, } </script>エラー対処
Vue2.x系を使っている方は下記のようなエラーが出ると思います。(出ない方はスルーして結構です)
error: npm i core-js/fn/promiseこのエラーの対処の仕方は、僕が書いた記事core-jsの依存関係エラー(core-js/~/~)対処法を参考にして頂くと、恐らく解決できます。解決できない場合はコメント欄にてご報告をお願いします。
以上、「Vue.jsで非同期処理関数を作る方法」でした!
めちゃめちゃ簡単♪
良ければ、LGTM、コメントお願いします。
また、何か間違っていることがあればご指摘頂けると幸いです。
他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!
Thank you for reading
- 投稿日:2021-01-01T22:58:27+09:00
vueで親コンポーネントで非同期通信が完了してから子コンポーネントでの通信を行いたい
vue3で親コンポーネントで非同期処理が終わってから子コンポーネントの処理を行いたい時のメモ
結論
親コンポーネントの処理が終わったらv-ifで子コンポーネントを有効にする。
親.vue<template> <子コンポーネント v-if="mount"/> </template> <script lang="ts"> export default { setup() { const mount = ref<boolean>(false) 親コンポーネントの非同期処理().then(() => mount.value = true) return { mount } } } </script>その他
・v-showは表示されていないだけでコンポーネントは生成されるため、非同期処理の完了を待たずに実行される。
・Vue3の新機能suspense
を使うとv-showと同じような動作となる。
・setup関数をasyncにして非同期処理をawaitにすると表示されない(親コンポーネントでsuspenseを使う必要がある?)
- 投稿日:2021-01-01T17:00:52+09:00
とりあえずMacでVueの環境を整えてみた
スタンドアロン版のVue.js devtoolsをmacに入れていくメモ。
なおNode.JSのインストールまでは
MacにNode.jsをインストール
を参考にさせていただいています。必要なこと
1.Homebrewのインストール(済)
2.nodebrewのインストール
3.Node.jsのインストール
4.Vue.js devtoolsのインストールHomebrew
HomebrewはMacでのソフトウェアや拡張機能の管理を行うパッケージマネージャです。便利です。
Homebrewのインストールについては
Homebrewのインストール
を参照してます。環境
開始段階の環境として
・mac OS Catalina 10.15.7
・Homebrew 2.7.1
はインストール済みです。nodebrewのインストール
・インストール
ターミナルを開いてnodebrewをインストールしていきます。
ターミナル コマンドbrew install nodebrew・確認
インストールできたか確認してみます。
ターミナル コマンドnodebrew -vターミナル 結果nodebrew 1.0.1 Usage: nodebrew help Show this message nodebrew install <version> Download and install <version> (from binary) nodebrew compile <version> Download and install <version> (from source) nodebrew install-binary <version> Alias of `install` (For backward compatibility) nodebrew uninstall <version> Uninstall <version> nodebrew use <version> Use <version> nodebrew list List installed versions nodebrew ls Alias for `list` nodebrew ls-remote List remote versions nodebrew ls-all List remote and installed versions nodebrew alias <key> <value> Set alias nodebrew unalias <key> Remove alias nodebrew clean <version> | all Remove source file nodebrew selfupdate Update nodebrew nodebrew migrate-package <version> Install global NPM packages contained in <version> to current version nodebrew exec <version> -- <command> Execute <command> using specified <version> Example: # install nodebrew install v8.9.4 # use a specific version number nodebrew use v8.9.4こんな感じでツラツラと出てきたらOKです。
Node.jsのインストール
・インストール
今回はとりあえず最新版をインストールしようと思います。
ターミナル コマンドnodebrew install-binary latestターミナル 結果Fetching: https://nodejs.org/dist/v15.5.0/node-v15.5.0-darwin-x64.tar.gz ######################################################################## 100.0% Installed successfully・有効化
最新版をそのまま有効化していきます。
ターミナル コマンドnodebrew use latestターミナル 結果use v15.5.0今回はインストールされている最新版がv15.5.0だったので、これでOKです。
・パスを通す
ターミナルから起動できるようにパスを通します。
ターミナル コマンドecho 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile確認のためターミナルで以下のコマンドを実行します。
ターミナル コマンドnode -vターミナル 結果v15.5.0先程有効化したv15.5.0が表示されました。
これでNode.jsのインストールは完了です。Vue.js devtoolsのインストール
・インストール
最後に本命のVue.js devtoolsをインストールしていきます。
引き続きターミナルで以下のコマンドを実行します。ターミナル コマンドnpm install -g @vue/devtoolsなんやかんや出てきます。
ターミナル 結果added 201 packages, and audited 202 packages in 21s 6 packages are looking for funding run `npm fund` for details found 0 vulnerabilities・起動
インストールできたようなので、動作確認していきます。
ターミナル コマンドvue-devtools・結果
- 投稿日:2021-01-01T15:22:08+09:00
Laravel + Inertia + Vueで簡単にAPI実装する
はじめに
2021年明けましておめでとうございます!
2020年は色々あり、コロナに翻弄された年でした。
この逆境に立ち向かい、社会に貢献されているすべての皆様に敬意を表させて頂きます。
恐らく2021年も、変わらずな環境下であると思われますが…皆様同様に私も負けじと頑張ります。さて…PHPerの皆様、Laravel8をガンガンお使いでしょうか?
Laravel8では、Laravel JetstreamというUIライブラリが用意されており、簡単にアプリケーションを作ることができるようになりましたね。
このJetstreamは、以前から似たようなものがありましたが、より簡単に作ることができるようになりました。
CSSをBootstarpからTailwind CSS に変更しており、より柔軟にCSSを使いUIを作ることができます。
さらに、実装においては、Livewireを用いてBladeを利用するか、Inertia.jsを用いてVueを利用するかを選択することができます。
Laravel8を触ってから、Inertiaを初めて知ったのですが、非常に理にかなった思想で便利だったので、そのInertiaについて書こうと思います。Inertiaとは?
Inertiaは、「Modern Monolith(モダン モノリス)」という事を謳っています。
マイクロサービスが広まる中、モノリシックは時代錯誤な気がしますよね。
フロントエンド + バックエンドの構成では、APIを設計し実装し、フロントではそれを呼び出して描写する…これを書くAPI毎に毎回書くわけで、よく考えればこれは冗長ではないでしょうか?
Inertiaはその「毎回書くこと」をライブラリで吸収して、実装を簡単にするためのライブラリです。
API設計は必要ありません、APIの呼び出しも必要ありません。
変数やルーティングは、バックエンドの実装をもとにフロントエンドの変数のアサインやルーティングを作成してくれます。
フロントエンド + バックエンドの構成でありながら、サーバーサイドテンプレートを扱うように(モノリシックであるかのように)、 実装が可能です。
なので、ModernでありながらMonolithなもの、というわけです。実装サンプル
routes/web.php
<?php use Illuminate\Support\Facades\Route; // 通常のroutingです。 Route::resource('/user','App\Http\Controllers\UserController');UserController.php
<?php namespace App\Http\Controllers; use App\Models\User; use Inertia\Inertia; class UserController extends Controller { public function index() { // Inertia::renderを呼び出す事で、どのコンポーネントに対して // どの変数をセットするかをここできめ、vueにも反映させることができます。 return Inertia::render( 'User/Index', ['users' => User::all()] ); } // show // create // store // edit // update // destroy }resources/js/Pages/User/index.vue
<template> <layout title="Users"> <div v-for="user in users" :key="user.id"> <inertia-link :href="`/users/${user.id}`"> {{ user.name }} </inertia-link> <div>{{ user.email }}</div> </div> </layout> </template> <script> import Layout from '../Shared/Layout' export default { components: { Layout, }, /* Controllerで指定した変数をpropsで受け取るため、同じ変数名を指定します。 IFはInertiaにおまかせです。 */ props: { users: Array, }, } </script>vue側でのルーティングは、Vue Routerを使わずに、Inertia側で受け持ちます。
その為、this.$route.params等は使えず、laravel側からパラメータは受け渡すことになります。
* vueを触っていると使えるのが当たり前だと思っており、使えず若干ハマりました…。まとめ
実装サンプルのように、APIのレスポンス時も、フロントで受け取る側もいつもの記述は必要がないことがわかります。
実はコンポーネントの設計もある程度もInertiaの設計に引っ張られる為、構成が整っていいかもしれません。
デメリットとしては、ブラックボックス化してしまう事くらいでしょうか。
ただフレームワーク自体もある程度ブラックボックス化しているわけで、それと同じようなものだと考えれば、気にならないくらいのレベルです。
メリットとしては、「バックエンドテンプレートと似たような感じでVueを使える」「APIやりとりのコードが極端に減る」等です。是非、モダンモノリスなライブラリ「Inertia」を使って見てください。
それでは今年も頑張りましょう!
- 投稿日:2021-01-01T14:26:52+09:00
【Vue.js】Vuexで双方向バインディング(v-modelを使いたい!)
はじめに
Vuexでv-modelを使いたいなぁ、ブラウザバックしたときに入力値が保持されるといいなぁ、と思ったときに実装した内容を残しておきます。
ここでは検索フォームを例に取り上げますが、フォーム入力全般に応用できると思います。
環境
vue @2.6.12
vue-router @3.4.9
vuex @3.6.0双方向算出プロパティを使う
store.js に関連の処理を書く
まずは、store.js(またはそれに準ずる処理が書かれている場所)に以下のような処理を用意します。ここでは、
keyword
というstateを例に取り上げます。store.jsexport default new Vuex.Store({ state: { // 1 keyword: '' }, getters: { // 2 keyword: state => state.keyword }, mutations: { // 3 setKeyword: function(state, keyword) { state.keyword = keyword }, }, actions: { // 4 getKeyword: function({ commit }, keyword) { commit('setKeyword', keyword) }, } })それぞれの役割
1) Vuexのstoreにv-modelで扱いたいstateを用意する。
2. gettersでstate.keywordの値を取得できるようにする。
3. mutationsでstateの値を書き換えられるようにする。
4. actionsでmutationsを呼び出せるようにする。2)gettersはもとの値を書き換えることがありません。ここでは読み取り専用であることを明示するために、あえてgettersを介し
this.$store.getters.keyword
で値を参照できるようにしています。もちろんthis.$store.state.keyword
としてstateから値を参照することもできます。3)stateの値を変更する処理です。stateの値を変えるときはmutationsを介して変更するようにします。stateを変更する処理が他のコンポーネントに書かれていると管理が煩雑になるためです。
4)さらに3のmutationsをcommitするための処理を書いています。他のコンポーネントからは、このactionsをdispatchすることで処理を行います。もちろんmutationsを直接commitしても問題ありません。
書き方はさまざまありますので、プロジェクト全体のルールに従うのが良いでしょう。
computedをgetとsetに分ける
次に実際に使用したいコンポーネントに移ります。
ここでは、inputタグのv-modelにkeyword
を用意しました。search.vue<input type="text" v-model="keyword">次にcomputedに記述していきます。getとsetに分けて次のように書くことで、読み取りと書き込みの両方を実現できます。
computed: { keyword: { get() { return this.$store.getters.keyword }, set(value) { this.$store.dispatch("getKeyword", value); } } }getはstoreから値を読み取る処理、setは値が変更されたときに実行する処理です。setの引数に、イベントが起こったときの値が入ります。
さきほど、actionsに設定したgetKeyword
を呼び出して、引数にvalueを渡すことでstateの値を書き換える処理を行っています。以上で、Vuexでも、v-modelを扱えるようになります。
さいごに
本稿で取り上げたのは、Vuex公式でフォームの扱いの項目で説明されている内容に基づきます。公式で丁寧に説明がなされているものの該当箇所のみでは全体像がわからないため、関連するコードを記事としてまるっとまとめておきたいと思いました。
- 投稿日:2021-01-01T10:51:02+09:00
Vue.jsでちょっとハマったtips
下記構成でハマったこと。
- vue-cliで初期化
- vue-router導入
- axios導入
vue.jsはvue3
ハマったこと
- 別コンポーネントの
methods
を呼び出す方法# BlogContents.vue <script> import MicroCms from '@/components/MicroCms.vue' export default { name: 'Blog', mounted () { MicroCms.methods.getBlog() # この記法じゃないと呼び出せない } } </script> # MicroCms.vue <script> import axios from 'axios' export default { name: 'MicroCms', methods: { getBlog: function () { axios.get( // 処理 ) } } }
BlogContents.vue
からMicroCms.vue
のgetBlog()
を呼ぶ際に下記の記法だと取得できなかった。MicroCms.getBlog()この記法だと
getBlog()
はfunctionじゃないから見つからない的なエラーが出力される。
- 投稿日:2021-01-01T00:58:48+09:00
vue.js コンポーネントでDialogを作ってみる
Vue.js コンポーネントでDialogを作ってみる
vueでDialog(MessageBox的な?)コンポーネントを作ってみました。
まずは公式のマナーをおさらい
コンポーネントへデータを渡す際には
プロパティ経由でデータを渡す必要があり、逆に子コンポーネント側から親コンポーネントにデータを伝える場合、
カスタムイベント経由で伝える必要があります。でもDialog的な部品って
たとえばC#だと
DialogResult result = MessageBox.Show("メッセージ","タイトル",MessageBoxButtons.YesNoCancel); if(result== DialogResult.Yes){ //Yesを押したとき・・・ }たとえばjavascriptだと
if( window.confirm( "メッセージ" )){ //Yesを押したとき・・・ }って使いたいですよね?
vue3で作ってみた
まずはダイアログ本体のコンポーネント
vue-dialog.vue<script lang="ts"> import { defineComponent, PropType} from "vue"; import { DialogData } from "@/component/vue-dialog/vue-dialog.ts"; export default defineComponent({ props: { data: { type: Object as PropType < DialogData > , default: () => new Object() }, }, setup(props, { emit }) { const cancel = () => { if (props.data.dialogOption.cancel.isShow) { props.data.cancelClick(); } }; return { props, cancel } }, }); </script> <template> <div class="dialogContainer" :class="{'closed':!props.data.isShow,'isShowCancel':props.data.dialogOption.cancel.isShow}" :style="{'z-index': props.data.zindex}"> <div class="dialogBackGround" v-show="props.data.isShow"> </div> <div class="dialogCardContainer" @click.stop="cancel "> <div class="dialogCard"> <div class="dialogCard--header"> <div class="title">{{props.data.title}}</div> <button type="button" class="closeBtn" @click.stop="cancel" v-if="props.data.dialogOption.cancel.isShow"> <i class="fas fa-times"></i> {{props.data.dialogOption.cancel.label}} </button> </div> <div class="dialogCard--body"> <div class="message">{{props.data.message}}</div> <div class="btnContainer"> <button class="resultBtn" :style="{'order':props.data.dialogOption.isRightBottonYes==true?0:1}" v-if="props.data.dialogOption.no.isShow" @click.stop="props.data.noClick()"> {{props.data.dialogOption.no.label}}</button> <button class="resultBtn" :style="{'order':props.data.dialogOption.isRightBottonYes==true?1:0}" v-if="props.data.dialogOption.yes.isShow" @click.stop="props.data.yesClick()">{{props.data.dialogOption.yes.label}}</button> </div> </div> </div> </div> </div> </template>※cssはダイアログっぽいモーダルを用意します(省略)
要点は
- プロパティで受け渡す[DialogData]
- ダイアログ表示後のユーザー操作時の処理方法
- プロパティにある関数を実行
プロパティについて
DialogData はダイアログに関するデータを受け渡すプロパティ
vue-dialog.tsexport class DialogData { public zindex: number;//ダイアログを出す時のz-index public isShow: Boolean;//ダイアログ用コンポーネントの表示非表示 public title: string;//ダイアログのタイトル public message: string;//ダイアログのメッセージ public dialogOption: IDialogOption;//ダイアログに関する設定 constructor(zindex: number = 2000) { this.isShow = false; this.title = ""; this.message = ""; this.zindex = zindex; this.dialogOption = InitDialogOption(); } public yesClick: any;// ダイアログモーダルでユーザーがYesボタンを押下した時に実行する関数 public noClick: any;// ダイアログモーダルでユーザーがNoボタンを押下した時に実行する関数 public cancelClick: any;// ダイアログモーダルでユーザーがNoボタンを押下した時に実行する関数 } //dialogOption はDialog使用時に表示設定に使用する要素で使用します。 export interface IDialogOption { yes: { isShow: boolean;//Yesボタンを表示するかどうか label: string;//Yesボタンのラベル }; no: { isShow: boolean;//Noボタンを表示するかどうか label: string;//Noボタンのラベル }; cancel: { isShow: boolean;//Cancelボタンを表示するかどうか label: string;//Cancelボタンのラベル } isRightBottonYes: boolean;//Yesボタンを右側に表示するかどうか } //dialogOption の初期値 export const InitDialogOption = (): IDialogOption => { return { yes: { isShow: true, label: "Yes", }, no: { isShow: true, label: "No", }, cancel: { isShow: true, label: "キャンセル", }, isRightBottonYes: true, } }呼び出し元のコンポーネント
home.vue<script lang="ts"> import { defineComponent, reactive } from "vue"; import VcDialog from "@/component/vue-dialog/vue-dialog.vue" import { DialogData, Dialog, DialogResult, IDialogOption, InitDialogOption } from "@/component/vue-dialog/vue-dialog.ts" export default defineComponent({ components: { "vc-dialog": VcDialog, }, setup() { const state = reactive ({ dialogData: new DialogData(2000), }); ///...略 return { state, ///...略 } }, }); </script> <template> <vc-dialog :data="state.dialogData"></vc-dialog> </template>これに追加して同期的に呼び出してユーザー操作の結果を受け取る為に.....
vue-dialog.tsexport class Dialog { private DialogData: DialogData; constructor(dialogData: DialogData) { this.DialogData = dialogData; } public Show = (message: string, title: string, dialogOption: IDialogOption = InitDialogOption()) => { return new Promise<DialogResult>(async (resolve, reject) => { this.DialogData.title = title; this.DialogData.message = message; this.DialogData.dialogOption = dialogOption; if (this.DialogData.dialogOption.yes.isShow == false && this.DialogData.dialogOption.no.isShow == false && this.DialogData.dialogOption.cancel.isShow == false) { this.DialogData.isShow = false; reject("必ず「Yes」「No」「Cancel」のうち最低一つは表示設定にしてください"); return; } this.DialogData.yesClick = () => { this.DialogData.isShow = false; resolve(DialogResult.Yes); }; this.DialogData.noClick = () => { this.DialogData.isShow = false; resolve(DialogResult.No); }; this.DialogData.cancelClick = () => { this.DialogData.isShow = false; resolve(DialogResult.Cancel); }; this.DialogData.isShow = true; }); } }プロパティ用のデータにダイアログを表示しつつPromiseを返却する表示用の関数を含んだオブジェクトを用意
※ dialog.Show() 的な書き方がしたいから使用する時は、初期化の時にダイアログのプロパティ用オブジェクトを指定しておいて
home.vueconst dialog: Dialog = new Dialog(state.dialogData);こんな感じで使う
home.vueconst ret: DialogResult = await dialog.Show("たいとる", "めっせーじ"); if (ret == DialogResult.Yes) { console.log("Yesが押されました") } else if (ret == DialogResult.No) { console.log("Noが押されました") } else if (ret == DialogResult.Cancel) { console.log("Cancelが押されました") }という事で「vue.js コンポーネントでDialogを作ってみる」でした。(おしまい)
一応公式でもプロパティの型に「Function」と入っているので公式的にもOKなのかもしれません(自信ないけど)
興味がありましたらサンプルはこちら
https://github.com/zeronooekaki/vue3-dialog