20210612のvue.jsに関する記事は3件です。

vue3 + typescriptをwebpackを使って最小構成で構築!

はじめに vue-cliは使用せずにwebpackを自分で設定して、なるべく小さな構成でvue3+typescriptの動作環境を作っていきます。 初心者にも伝わるようになるべく丁寧に進めていきます! 〜目次〜 ①npmのインストール ②プロジェクトの作成 ③TypeScriptの設定 ④webpackの設定 ⑤Vueのインストール・簡単な実装 ⑥webpackのビルド設定・動作確認 ※動画でも説明してます ①npmのインストール vueの動作に必要なパッケージの管理をnpmで行います。 npmはnodejsのインストールが必要ですので、まだPCに入ってない場合はインストールします。 まずターミナルを開きます ※Windowsの場合はコマンドプロンプト ①npmが入っているか確認 npm --v 6.14.12 上記のようにバージョンが出ていればnpmは入っています。 もしまだインストールされてない場合はこちらからインストールをしてください nodejsのインストール ②プロジェクトの作成 まず、プロジェクトを作成するディレクトリを作成します ①任意の場所にディレクトリを作成します。僕は『sample-vue』という名前のディレクトリにします! mkdir sample-vue ②作成したディレクトリにnpmで初期化処理を行います。 cd sample-vue npm init -y ③ここまで上手くいっていれば下のような構成になっていると思います。 sample-vue/ ├ package.json ③TypeScriptの設定 それでは、TypeScriptを設定していきます。 先ほど『npm init』で作成されたpackage.jsonがあるディレクトリまで移動してください。 ①TypeScriptパッケージのインストール npm install --save-dev typescript ②tsconfig.jsonファイルの作成 touch tsconfig.json このtsconfig.jsonにtypescriptの設定を書きます ③tsconfig.jsonの設定 { "compilerOptions": { "sourceMap": true, "module": "ES2015", "target": "ES5", "moduleResolution": "node" } } sourceMap: true:  ・trueにすると、js変換時にソースマップファイルが生成されます。  ・ソースマップファイルがあると、chromeのデバッカーなどで、変換前のTypeScriptコードでデバックできます module: "ES2015"  ・TypeScriptをjsに変換する際、どのモジュールパターンにする指定します。  ・今回はvue公式でも推奨されているES2015を指定します。  ・ES2015を指定することでTree Shakingが有効になり、TypeScriptを変換する際に無駄なコードを削除することができます。 target: "ES5"  ・TypeScriptを変換する際、どのECMSScriptバージョンにするか指定します。  ・今回はVue公式でも推奨されているES5を指定ます。 moduleResolution: "node"  ・モジュールの解決方法を指定します。  ・何も指定しない場合、ES2015だとClassicになりますが、これは後方互換性の為に残されている方式なので、nodeを指定します。 参考-vue推奨構成 ④webpackの設定 次に、webpackの設定をしています。 『package.json』があるディレクトリで必要なパッケージをインストールします ①必要なパッケージのインストール npm install --save-dev webpack webpack-cli vue-loader@next @vue/compiler-sfc css-loader style-loader ts-loader ①webpack: webpack本体です ②webpak-cli: webpackを使用するためのコマンドツールです ③vue-loader@next: vueコンポーネント利用するためのLoaderです ⑤@vue/compiler-sfc: vue-loaderに必要なパッケージです ⑥css-loader: cssをjavascriptファイルに埋め込むためのLoaderです ⑦style-loader: jsに埋め込まれたcssをhtmlのstyleタグに加える際に利用されます ⑧ts-loader: typescriptを利用するためのLoaderです 参考-loaderについて ②webpack.config.jsの生成 touch webpack.config.js このwebpack.config.jsファイルにwebpackの設定を書きます ③webpack.config.jsの設定 const { VueLoaderPlugin } = require('vue-loader') module.exports = { //production(本番用)にすると最適化された状態で、 //development(開発用)に設定すると読みやすいjsが出力される mode: "development", //sourcemapをスクリプト内に埋め込む devtool: 'inline-source-map', //エントリーポイントになるjsファイル ※次のパートで作成します entry: "./src/index.ts", output: { //ビルド結果の出力先を指定します path: `${__dirname}/dist`,   //ビルド結果のjsファイル名を指定します filename: "bundle.js" }, module: { rules: [ { //vueのloader設定 test: /\.vue$/, loader: "vue-loader" }, { //cssのloader設定 test: /\.css$/, use:[ "style-loader", "css-loader" ] }, { //typescriptのloaderを設定 test: /\.ts$/, loader: "ts-loader", options: { //vueをtypescriptとして監視する appendTsSuffixTo: [/\.vue$/] } }, ] }, resolve: { //import文で、.tsを省略できるようにする extensions: [".ts"] },  //vue-loader v15以上を使う場合に必要 plugins:[new VueLoaderPlugin()] } ①mode: "development"  ・こちらは開発中はdebvelopmentに設定します。  ・productionにすることでコードが最適化されます。  ・本番環境では必ずproductionにします。 ②dev-tool:inline-source-map  ・dev-toolはソースマップを生成するかどうかと、その方法を指定します。  ・inline-source-mapを指定することで、コードの中にsourcemapが含まれるようになります。 ③entry: '.src/index.ts'  ・アプリケーションのエントリーポイントになるファイルを指定します。  ・まだsrc/index.tsは作ってませんが、次のプロセスで作成するので指定しておきます。 ④output->path: ${__dirname}/dist  ・出力ディレクトリを絶対パスで指定します。  ・__dirnameで実行中のソースコートが格納されているディレクトリの絶対パスを取得します。 ⑤output->filename: 'bundle.js'  ・出力結果のファイル名を指定します。 ⑥moduke->rule  ・ここにローダーの設定をしていきます。 ⑨plugins:[new VueLoaderPlugin()]  ・vue-loader V15以上を使う場合に必要です ⑤Vueのインストール・簡単な実装 ①vue3をインストールします npm install --save vue@next ②ルートディレクトにdistとsrcディレクトリを作成します mkdir dist mkdir src ③現在のディレクトリ構成はこのようになっていると思います sample-vue/ ├ dist ├ src ├ package.json ├ tsconfig.json ├ webpack.config.js ├ node_modules ④srcディレクトリの直下に、App.vueを作成します cd src touch App.vue ⑤App.vueを下の様に実装します <style> .hello{ color: red; /*cssが効いている事がわかりやすくする為に赤にする*/ } </style> <template> <span class="hello">{{ helloText }}</span> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ name: 'App', setup(){ return{ helloText: 'Hello World!' } } }) </script> ⑥srcディレクトリ直下にvue.d.ts(vueファイルの型定義ファイル)を作成します こちらを用意しないと、.vueのモジュールをimportする際にエラーになります declare module '*.vue' { import { ComponentOptions } from 'vue' const component: ComponentOptions; export default component } ⑦srcディレクトリ直下にindex.tsを作成します touch index.ts ⑧index.tsを下の様に実装します import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.mount('#app') ⑨distディレクトリ直下に、index.htmlを生成します cd ../dist touch index.html ⑩index.htmlを下の様に実装します <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> </head> <body> <div id="app"></div> <script src="bundle.js"></script> </body> </html> ・divのidをindex.jsでマウントしたものと同じにする ・webpackで出力指定したjsファイルを読み込むようにする ⑥webpackのビルド設定・動作確認 ①package.jsonを開き、scriptセクションの中に『build: "webpack"』を追加します "scripts":{ "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" //ここを新規追加 } ②package.jsonがあるディレクトリに移動し、webpackのバンドルを実行します npm run-script build ③distディレクトリにbundle.jsが生成されたことを確認します sample-vue/ ├ dist ├ index.html ├ bundle.js //ここが自動生成される ├ src ├ App.vue ├ index.ts ├ vue.d.ts ├ package.json ├ tsconfig.json ├ webpack.config.js ├ node_modules ④chromeでindex.htmlを開いて動作していることを確認します!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue Firebase】麻雀成績管理アプリ「Mahjanager」をリリースした話【個人開発】

麻雀に興味がある→けど得点計算ができないからリアル対局に参加できない… ネット対局じゃなく、リアル対局派だ。けどリアルだと和了率や放銃率の集計がめんどくさい。 そんな人のための麻雀成績管理アプリをリリースしました。 麻雀成績管理アプリ「Mahjanager」をリリースしました!!https://t.co/d7bIlO1tR9初心者が困る得点計算や、リアル対局の記録を保存したい!といった人のためのアプリです。モバイル、タブレット、PCすべてに対応しています。是非使ってみてください!!#拡散希望 #麻雀 #個人開発 #Mahjanager pic.twitter.com/H1jZXgGugP— ラーメン食太郎 (@samurai_se) June 11, 2021 作ろうと思ったきっかけ 冒頭でも述べた通り、リアル対局にて四麻をしようとすると、雀荘に行くのなら別ですが、 身近な人間を集めた場合、全員が得点計算ができるという状況がなかなかない。 そういうときのために、手軽に得点計算ができて、なおかつ対局の記録を残したいなと思ったのがきっかけでした。 で、なにで作る? フロントエンド 先ずフロントですが、ReactかVueかで迷いました。 Vueは業務でも少しは扱ったこともあって、前提知識が多少ある状態。 Reactは個人的に勉強はしていましたが、アプリを構築するとなると、かなり手が遅くなるというくらいのレベル感。 多少迷った結果、やはり素早くアプリリリースまでたどり着きたかったので、あまり手を止めずに書いていけるVueを採用。 あと、私一人で運用することを考えた場合、英語記事中心のReactでやるよりも、 日本語記事が豊富で、日本では先人たちが多いであろうVueのほうがいいと思ったのもありました。 バックエンド 次にバックエンド。 ここはフロントとは違い、技術的な要素よりも金銭面で決まった感じです。 おそらく大々的に収益を上げるのが難しいであろうと思ったので、 本格的にサーバーを用意する(GCPのGCE/cloudSQL, AWSのEC2/RDSみたいな構成)という選択肢は除外されました。 GCE/EC2はそこまで高くはありませんが、cloudSQL/RDSは個人開発で使うには少々お高い… となるとサーバーレスで開発がしたくなるので、 有名どころのFirebaseを使うか、となった次第です。 有名である以外にもFirebaseを選択した理由がいくつかありまして… 認証にFirebase Authenticationを使いたかった 運用時のために、Google Analyticsを使いたかった というところです。 Firebaseに関しては前提知識ほぼ0の状態で始めたのですが、 NoSQL、認証、Hostingなどアプリを作るための前提知識さえあれば、 公式ドキュメントがものすごく充実しているうえ、違和感のない日本語で表示してくれるので 簡単に実装を行うことができました。 基本的には公式のドキュメントだけをみて開発を進めていたのですが、 そのほかに1冊、頻繁に活用させていただいた書籍がこちら。 技術書典8 の頒布情報ページ、暫定版だけどやっと用意できた。執筆中の新刊の第2.5版、表紙のイラストは同じでもタッチや装丁デザインをアレンジを変えていい感じにしたい。 #りあクトhttps://t.co/A2Lb6dYhLM pic.twitter.com/q4WQ6md64s— 大岡由佳『りあクト! 第3.1版』BOOTHにて/紙本も販売中 (@oukayuka) February 13, 2020 大岡由佳さん著の『りあクト! Firebaseで始めるサーバーレスReact開発』です。 この『りあクト!』シリーズはReactを勉強するうえで非常に助けになった本で、 全シリーズ持っているのですが、今回アプリ作成するにあたって、先述の巻を多分に参考にさせていただきました。 書籍の内容はReact × Firebaseですが、そこをReact→Vueに読み替えながら実装すれば問題なく実装を進められることができ、実際のコードを書くうえで非常に参考になりました。 本記事との関連性は薄いですが、本当に良書ですのでおススメです。 製作期間 約1.5か月。 思ったより時間がかからなかったです。 Firebaseが、実装が面倒な認証やログ取得の部分を担ってくれるので、 UI開発とメイン機能の開発にのみ集中できたのが大きかったです。 成果物 URL: https://mahjanager.web.app/ モバイル・タブレット・PCすべてに対応しています。 モバイルではPWAでの利用も可能です。 ※以下で紹介する機能別の画像イメージは、全てPC版のイメージとなります。 ログイン とりあえずtwitter認証のみを用意しています。 まずはtwitterアカウントを持っている方のみに使ってもらうことで、 twitterにて拡散してもらえることを期待しているのと、 twitter認証しかなくても使ってくれる方というのは、ある程度アプリに対して需要がある方かと思うので、 有用なフィードバックが得られるのではないか?と考えたからです。 画面右上のノートマークはリリースノートへのリンクとなっています。 ちなみに、リリースノートは自身で開発しておらず、外部サービスのnoteを利用しています。 直近の成績照会 直近10局の成績・順位を表示しています。 10局としているのは、Firestoreを使っているが故の縛りになっています。 バックエンドをcloud Function × BigQueryで拡張してゴリゴリと通算の成績で集計することもできますが、 ユーザーが少ない現状でそこまでのサービスを提供するのかといわれると、 個人開発ではNoと言わざるを得ないと考えました。 そんなわけで現状は10局分の成績をFirestoreから読み取り→集計を行っている感じです。 対局一覧 過去20局分の対局履歴の閲覧が可能です。新規の対局も右上の+ボタンから作成します。 新規対局作成 ここから対局者の名前と初期の持ち点を入力し、新規対局を開始します。 入力値を全てinputし、エラーがない状態になると、saveボタンが現れて、 対局室の作成ができる仕組みです。 成績入力 対局室を作成すると、成績入力ができるようになります。 「得点状況」カードの青丸内部の数字は、リー棒供託を示しています。 各プレイヤーの持ち点の横に表示されている「立直」ボタンを押下すると、 リー棒供託がカウントアップされます。 得点の入力は、各プレーヤーの行の右に表示されている、 +インプットと-インプットに値を入力し、右下の保存アイコンを押下することで清算が可能ですが、 初心者のために得点計算機能を備えています。 それが画面左下の電卓アイコンです。 得点計算 麻雀の得点は、符の計算と翻の計算を行い、その結果に対して得点が決まっている という感じです。 符計算 まず符計算は、符計算ボタンを押下することで可能となります。 また、コンボボックスも活性状態ではあるので、手動で入力することも可能です。 待ちの形、頭、刻子など、麻雀の用語は覚えなければなりませんが、 それさえ覚えていれば、後は符計算に必要な情報を入力します。 入力後、OKを押下すれば、符の計算結果が反映されます。 翻計算 翻計算は、和了役によって決まります。 翻計算ボタンを押下すると、ダイアログが開き、役を選択します。 役選択後、OKを押下すると、選択した役に応じて翻が計算されます。 清算 以上で、符・翻が計算されました。 この状態で得点計算を押下します。 すると、得点状況画面で選択されていた、親・和了者・支払人の形に応じて支払い内容が反映されます。 最後に、右下の保存ボタンを押下することで、支払内容が得点に反映されます。 この時、清算結果が保存されます。 左下の時計アイコンを押下すると、和了履歴を確認することができます。 この和了履歴をもとに、直近の対局成績を算出しています。 流局 流局時は、先ほどの得点計算画面にて、「流局」ボタンを押下することで、 聴牌した人を選択します。 そして、OKを押下すれば、選択した内容でノーテン罰符の計算がされています。 あとは清算するだけです。 流局時の情報も、和了履歴に記録されています。 プロフィール ユーザーの直近5件の行動履歴が表示されるようになっています。 また、ユーザー名・アイコンはtwitterで利用している内容が表示されます。 その他機能 ナビゲーションバーのベルアイコンを押下することでnoteの更新情報を表示します。 そのほかフィードバック機能(Google Formに遷移します)、twitter共有機能、リリースノート。ログアウトを備えています。 今後実装したいこと 大きなところでいうと、Firestoreの最大行っても過言ではない強みである、 リアルタイムリスナーとオフライン機能を利用したいです。 そのほか一覧で実装したいことを記します。 ※有料機能は、一定数フォロワー様がつくか、アプリで収益が上がれば実装します 機能名 料金 通算の成績照会 有料 オフライン書き込み 有料 ダークテーマ 有料 お知らせのリアルタイムリスナー 無料 三麻対応 無料 団体戦機能 無料 上家下家の考慮 無料 包の綱領 無料 最後に 麻雀に興味ある人、麻雀が好きな人にたくさん使っていただきたいです。 そして、よりよいものを作れるように、ぜひフィードバックしてほしいです! twitterにコメントなどいただけますと、すごくうれしいです。 https://twitter.com/samurai_se
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsでAPIのコールからレスポンスが返ってくるまでぐるぐるマークを出す

はじめに 久しぶりの投稿すぎて、うまく書けるか分からないですが、 最近触っている Vue.js の投稿をしてみます。 やってみたこと 現在、Vue CLIでチャットアプリをつくっているのですが、そのアプリでチャンネル変更機能があります。 よくあるチャットアプリと同じイメージで、チャンネルを変更したら変更後のチャンネルのメッセージを取得します。 データ取得・画面表示はできたのですが、どうも操作感が悪いなーと思っていました。 ぐるぐるがなかったためです。 ぐるぐるを表示することで、表示の切り替えのタイミングがユーザーに分かりやすくなり、カクついた操作感は解消されます。また他のボタンを押されることを防ぐこともできます。 実際にぐるぐるを表示してみた ぐるぐるは何を使ったか ぐるぐる自体は Vuetify が用意してる Progress circular コンポーネントを使用しました。 https://vuetifyjs.com/ja/components/progress-circular/ どんな処理を入れたか ぐるぐるコンポーネントを作成 ぐるぐるコンポーネントを読み込む ぐるぐる専用のストアを作成 axiosのinterceptors内でぐるぐるを制御 ぐるぐるコンポーネントを作成 BaseLoading.vue <template> <v-dialog v-model="flag" fullscreen> <v-container fluid fill-height class="loading_bg"> <v-layout justify-center align-center> <v-progress-circular :indeterminate="true" size="64" color="accent" /> </v-layout> </v-container> </v-dialog> </template> <script lang="ts"> import Vue from "vue"; import { Component, Prop } from "vue-property-decorator"; @Component({ components: {}, }) export default class BaseLoading extends Vue { @Prop({}) public flag: boolean; constructor() { super(); this.flag = false; } } </script> 1つbooleanの値をもち、その値で表示/非表示を切り替えるだけのコンポーネントです。 その値がどこからどのタイミングでpropされるかは後述します。 ぐるぐるコンポーネントを読み込む 全画面共通でサーバとの通信時はぐるぐるを表示したいため、コンポーネントの一番親?にあたるApp.vueで読み込みます。 ぐるぐるコンポーネントに渡すbooleanは、次に説明する、ぐるぐる専用のストアのstateを見ています。 つまり、このApp.vueではストアのstateが更新されたタイミングでぐるぐるコンポーネントにbooleanをpropすることができます。 App.vue <template> <v-app id="inspire"> <v-content> <router-view /> <BaseLoading :flag="IsShow" /> </v-content> </v-app> </template> <script lang="ts"> import Vue from "vue"; import Component from "vue-class-component"; import BaseLoading from "./components/BaseLoading.vue"; import LoadingStore from "./store/loading/index"; @Component({ components: { BaseLoading }, }) export default class App extends Vue { constructor() { super(); } get IsShow() { return LoadingStore.IsShow; } } </script> ぐるぐる専用のストアを作成 中身はシンプルで、booleanのstateが1つと、そのstateに対するgetter/setter(mutation)のみ用意します。 loading/index.ts import { Module, VuexModule, Mutation, Action, getModule, } from "vuex-module-decorators"; import store from ".."; @Module({ dynamic: true, store, name: "loadingStore", namespaced: true }) class LoadingStore extends VuexModule { private isShow: boolean = false; @Mutation public setIsShow(flag: boolean) { this.isShow = flag } get IsShow(): boolean { return this.isShow; } } exort default getModule(LoadingStore); axiosのinterceptors内でぐるぐるを制御 このアプリでは、Vueで非同期処理をするときの定番であるaxiosを使っています。 axios を利用した API の使用 axiosでは、interceptorsなるものが用意されており、APIコールのリクエスト直前とレスポンス直後の処理を入れることができます。 interceptors.ts export default function setup() { axios.interceptors.request.use(async (config) => { LoadingStore.setIsShow(true) return config; }); axios.interceptors.response.use( (response) => { LoadingStore.setIsShow(false) return response; }, async (error: AxiosError) => { LoadingStore.setIsShow(false) } ); } リクエスト直前 LoadingStore.setIsShow(true) レスポンス直後 LoadingStore.setIsShow(false) これで、APIの通信時のみぐるぐるを表示することができました。 今後の課題 1操作で1APIコールならこれで問題ないのですが、1操作で複数APIコールする箇所があり、この処理のままだと、ぐるぐるがチカチカする感じで少し違和感があります。 それはまた追々。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む