20211202のvue.jsに関する記事は13件です。

YoutubeDataAPIで好きな情報を取得する

概要 YouTube見る人多いですよね!YouTubeのAPIがあると知ったとき、使えたら面白そうだと思ったので触っていこうと思います! 扱う言語はJavaScriptでVueを用いて進めて行きます。 (なのでVueの記述方法がわからないと少し読みにくいかもです、その場合はコードは気にせず、どういうことをしているのか雰囲気がわかれば大丈夫です!) YoutubeDataAPIv3 これ↑が今回使うものの公式ドキュメントです。 目次 APIキー 特定チャンネルの動画情報を取得する リクエスト内容 レスポンス内容を見てみる 任意チャンネルの情報を取得してブラウザに表示する リクエスト内容 レスポンス内容を見てみる ブラウザ上に表示 おわり APIキー Google Cloud ConsoleへアクセスしてAPIキーの発行が必用なのでまずはここからです。 この記事など情報はたくさんあるので活用していきましょう。そんなに悩むことなくできました。 特定チャンネルの動画情報を取得する まず、あの有名ラーメン系youtuberの動画情報を取ってきてブラウザに表示させるところを目標にします? 今回使うリクエスト先のURLの記述方法は基本的に以下のようになります。 "https://www.googleapis.com/youtube/v3/search?&key=[APIキー]....." 「.....」の部分に欲しい情報についてのパラメータを設定します。[APIキー]の部分はさきほど発光したAPIキーを入れます。 今回の目標は、検索して動画の情報を取得するという動きなのでリクエストで指定した検索パラメータに一致する情報を持ってきてくれる「search」を使います。検索機能は「search」ということでしょうか。詳しくはsearchリファレンスに。 このsearchリファレンスの中に使えるプロパティの説明がありました!そこに良さそうなのがあったので今回はこれ↓を使います。 リクエスト内容 そして最初のリクエストURLは以下のようにしました! "https://www.googleapis.com/youtube/v3/search?&key=" + this.myKey + // はじめに取得した自分のAPIキー "&channelId=" + this.channelId + // ラーメンyoutuberのchannelID "&part=snippet&maxResults=50&order=date" 補足説明します。this.myKeyとthis.channelIDはString型変数です。パラメータは以下のようになっています。 パラメータ 値 内容説明 channelId 文字列(this.channelId) チャンネルIDは、YouTubeチャンネルのURLに記載されています。それをコピーしてthis.channelIdに入れています。 part snippet オブジェクトで情報が返され、基本情報(タイトル、説明など)が格納されます。 maxResults 50 50本の動画の情報を取ってきます。 order data 新規アップロード順に動画の情報を取ってきます。 なお、リクエスト部分のコードはこのように methods: { async getYoutubeApi() { const res = await fetch( "https://www.googleapis.com/youtube/v3/search?&key=" + this.myKey + "&channelId=" + this.channelId + "&part=snippet&maxResults=50&order=date" ) try { const value = await res.json() console.log(value.items) } catch (e) { console.log("error:" + e) } }, }, ここ↓では、valueというものを設定して、そこにAPIレスポンス(取得データ)を入れています。 const value = await res.json() レスポンス内容を見てみる Google Chromeの検証ツールで見てみました。コード的に言うと上のconsole.log(value.items)と書いてある部分にあたります。 メインとなる部分はitemsというオブジェクトに入っていたのでその中身を出しました。 ※APIレスポンスの中にはめちゃ色々なデータがありましたが、今回使えそうなデータは、その中でもitemsというオブジェクトに入っていたということです。イメージしずらいかもですがその場合はあまり考えなくて大丈夫です。 そうすると、50本分あることが確認できました!さらにsnippetオブジェクトの中に動画のタイトル(気になったらyoutubeで検索してみてください!)や概要欄の文章がありました!これで目標達成です。上手く動作したときは気持ちいいですね! 任意チャンネルの情報を取得してブラウザに表示する さっきは動画についてでしたが、次はチャンネルについてやりたいと思います。また、任意のチャンネルを検索して情報を取得できるようにしたいと思います!さらにその情報をブラウザに表示するまでが目標です! リクエスト内容 欲しいものが違うので、リクエストするURLも違ってきます。今回のリクエスト先のURLの記述は以下のようになりました。 "https://www.googleapis.com/youtube/v3/search?&key=" + this.myKey + "&part=snippet&type=channel&q=" + this.q 先ほどのURLとの違いは、channelIDがないことです。任意のチャンネルを持ってくるので特定のIDは不必要ですね。また、qという変数が現れました。ここにチャンネル名が入ることでそのチャンネル情報を持ってこれます。 パラメータの設定はこのようにしてます。 パラメータ 値 内容説明 part snippet さっきのと同じ type channel チャンネルに対して検索することを指示します。 q 任意の文字列(this.q) this.qは自分で設定した変数でブラウザ上で入力します。中身は任意の文字列です。この文字列にヒットするチャンネルが対象になります。 コードは基本的にさきほどと同じですが、ブラウザに表示させる必用があるため、とってきたデータを自分で設定した配列に格納する必用があります。なので次の一文を追加しています。 (valueはレスポンス内容で、その中でitemsというオブジェクトが今回のメインデータでしたね!) this.infos = value.items レスポンス内容を見てみる 検証ツールをつかって内容を見てみます。なお、qは今回「釣り」としました。 どうやら1回のリクエストで5つのチャンネルまで持ってこれることがわかりました(もうちょっと欲しかった、、)。データとしてチャンネル名、チャンネルの説明文、チャンネルアイコンの画像データなどがありました! このデータをブラウザに表示していきます。 ブラウザ上に表示 取得したデータはinfosという変数に入れました。このinfosの中から表示したい情報を選びます。snippetにある以下の3つを今回は使います。 title(チャンネル名) thumbnails(チャンネルのアイコン情報、さらにこの中から画像urlを使います) description(チャンネルの説明文) 表示させる部分のコードはこのようになりました。 template> <div id="youtube"> <h1>YoutubeAPIをつかってみる</h1> <div> <input type="text" v-model="q" /> <button v-on:click="getYoutubeApi">チャンネル検索</button> <div v-for="info in infos" :key="info.id"> <img v-bind:src="info.snippet.thumbnails.default.url" /> <h3> {{ info.snippet.title }} </h3> {{ info.snippet.description }} <div>------</div> </div> </div> </div> </template> 簡単に説明すると、5つのチャンネルの情報を上から順番に「------」という区切りをつけながら並べて表示させています。こんなかんじに表示されています! タイトルの下に入力欄と検索ボタンがあり、ボタンが押されるとチャンネルの情報がばばばっと出てきます。これで目標達成です! 入力はなんでも大丈夫なので、全然知らないチャンネルも出てくるので面白いと思いました。表示させる情報を工夫したらオリジナルの面白い検索機能がつくれちゃいます! ※ここで一つ気がついたのですが、動画の概要欄や説明文を見ると文字数に限界があるみたいですね、、、このAPIはそういった制約が多そうだと思いました。 おわり YouTubeってかなり人気なコンテンツですよね!そのAPIを触ってみたかったのでこのような内容になりました。 また、この記事は大学生限定クリエイティブコミュニティGeekSalon Advent Calendar 2021の企画の一部として投稿させていただきました! GeekSalonは大学生限定のプログラミングスクールです、私もメンターとして所属しています。下のリンクからご覧になってください! 私の所属するコースの特設サイトはこちら!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】Vue3でvue-google-oauth2を使用する

概要 Vue.jsからgoogleの認証を使用する時に、vue-google-oauth2というライブラリを使用するという記事が、ちらほらあると思います。ただ、このライブラリは一見Vue3には対応してないように見え、Vue3で普通にライブラリをインストールしてもビルド時にエラーになってしまいます。 Vue3で使うにはどうしたら良いか、というのをメモ書きしておきます。 対応 ライブラリのページをよく見ると、以下の通りVue3を使う場合の参照リンクがあります。 このリンクの先に行くと、vue3-google-oauth2なるものがあって、これを使えばいけそうです。 インストールして使用してみたところvue-google-oauth2と変わらなく使用できてますので、対応としてはこのVue3用のライブラリを使うので良さそうです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】APIから取得した配列データをv-forで描画する方法

はじめに こんにちは。 こちらの記事では、microCMSのAPIデータを元に繰り返し描画を行う方法を記しています。 誤っている点がございましたらコメントいただけると幸いです。 実装手順 1. microCMSからAPIデータを取得する Nuxtの拡張子.vueファイルでは、asyncDataを使ってaxios通信を行います。 retrunで返したcontentsには、microCMSに入力したすべてのデータが配列で格納されています。(contents[0].idを選択した場合は、配列の1番目のデータのIDが反映されます) データの取得方法については、過去のこちらの記事に記載しております。 script <script> import axios from "axios"; export default { async asyncData() { const test = await axios.get( 'https://サービス名.microcms.io/api/v1/APIのエンドポイント', { headers: { "X-API-KEY": "APIキーを入力" } } ); const contents = test.data.contents return {contents} } } </script> 2. v-forでタイトルを繰り返し描画する 先ほど取得した配列が格納されているcontentsを、v-forのlistに格納する。また、keyにはv-bindでIDを設定する。 v-forの形式は、v-for = "変数 in 配列"になります。 ※マスタッシュ構文で描画するlist.titleのtitleには、microCMSのAPI設定で任意で設定した「フィールドID」が入る。 template <template> <ul> <li v-for="list in contents" :key="list.id"> <h1>{{ list.title }}</h1> </li> </ul> </template> 配列の数だけ繰り返し描画されるので、データが5件あれば5回描画されます。 タイトル1 タイトル2 タイトル3 タイトル4 タイトル5 3. リンクや画像も表示させる idを選択することでページ遷移リンクを設定できたり、imgタグのsrcにURLを設定することで、画像も描画することができます。 template <template> <ul> <li v-for="list in contents" :key="list.id"> <nuxt-link :to="list.id"> <h1>{{ list.title }}</h1> </nuxt-link> <div> <img :src="list.image.url" /> </div> </li> </ul> </template> 参考 リストレンダリング Vue.jsで、取得したJSONデータの配列を元に繰り返し描画する方法 おわりに ここまでmicroCMSのAPIデータを元に繰り返し描画を行う方法についてまとめました。 これからもつまづいたことや機能の実装方法について記事にしていきます! 以上、最後まで読んでいただきありがとうございました! よければLGTMを押してくれると嬉しいです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RealWorldその2(フロントエンド)「Vue admin template」を動かしてみる

はじめに 前回の記事( https://qiita.com/ssugimoto/items/5bf561debe87843eb32c ) で紹介した 「Vue admin template (Vue2 + TypeScript + element-ui + vue-router ・・・)」をローカル環境で動かしてみます。 ローカルの開発環境に、Node等をインストールするのは手間なのでコンテナ(リモートコンテナ)を使います。 動かすフレームワーク・ライブラリのバージョンの一部 "vue": "^2.6.12", "vue-router": "^3.5.1", "element-ui": "^2.15.1", 前提 Windowsであれば WSL2 が使える環境であること VSCodeがインストールされており使ったことがあること Docker Desktop(もしくは代替のPodman / Mnikube / lima)でコンテナが動かせること リモートコンテナを使えるようにする git cloneしても良いですが、独自のカスタマイズをする場合はzipダウンロードが良いです リモートコンテナは、 Git リポジトリ https://github.com/ssugimoto/aws-amplify-typescript-local-container にあるものを 使います。 そのGit リポジトリはAWS Amplify を動かすことができるものをベースにしているため、不要なものがインストールされます。不要なものはDockerfileとdevcontainer.jsonから削ってください(Java, aws cli, amplify cli を削ると軽量化できます)。 GitHub → Code → Download ZIP → 「aws-amplify-typescript-local-container-main.zip」を任意のディレクトリに置き、展開する README.mdの説明を確認 VSCode で(plugin 「Remote - ContainersPreview」 と 「Remote - WSLPreview」をインストールする) VSCode → ファイル → フォルダを開く 、ローカルを表示し、「aws-amplify-typescript-local-container-main.zip」を展開したディレクトリを開く 信頼性を確認が表示されたら「はい」を選び VSCoddの右下あたりに「ReOpen in container」のボタンを押す コンテナのビルドがされます、約5分あればコンテナが使えます VSCode内でコンテナが使えるようになる コンテナ内からVueのソースを取得 Git clone または ZIPダウンロードで取得します Git cloneの場合 コンテナ内のターミナルで cd /workspaces/ mkdir vue GithubにSSH接続できるようにssh key等の設定 https://monsat.hatenablog.com/entry/generating-ssh-keys-for-github 等を参考にしてください コンテナ内の /root/.ssh/ に ssh接続設定します Git クローンする git clone git@github.com:Armour/vue-typescript-admin-template.git ZIPダウンロードの場合 コンテナ内のターミナルで cd /workspaces/ mkdir vue cd /workspaces/vue wgetでzipファイルを取得 wget https://github.com/Armour/vue-typescript-admin-template/archive/refs/heads/master.zip master.zip がダウンロードできる unzip master.zip vue-typescript-admin-template-master に展開される vueのプロジェクトがVSCodeリモートコンテナ内に配置されたのでアプリを動くようにする 実行するコマンド https://github.com/Armour/vue-typescript-admin-template#readme の通り cd /workspaces/vue/vue-typescript-admin-template yarn install yarn run serve ここまでのコマンドで、リモートコンテナ内で ブラウザアクセス用のWebサーバ相当、 ブラウザからAPIリクエストを受けるモックサーバ相当が起動します。 yarn installする前のディレクトリの場合の例 root ➜ /workspaces/vue/vue-typescript-admin-template (master ✗) $ ls -l total 1544 -rw-r--r-- 1 root root 468 Nov 30 11:45 babel.config.js drwxr-xr-x 2 root root 4096 Nov 30 11:45 demo -rw-r--r-- 1 root root 88 Nov 30 11:45 jest.config.js -rw-r--r-- 1 root root 1066 Nov 30 11:45 LICENSE drwxr-xr-x 3 root root 4096 Nov 30 11:45 mock -rw-r--r-- 1 root root 4095 Nov 30 11:45 package.json -rw-r--r-- 1 root root 59 Nov 30 11:45 postcss.config.js drwxr-xr-x 4 root root 4096 Nov 30 11:45 public -rw-r--r-- 1 root root 8454 Nov 30 11:45 README.md -rw-r--r-- 1 root root 8485 Nov 30 11:45 README-zh.md drwxr-xr-x 16 root root 4096 Nov 30 11:45 src drwxr-xr-x 3 root root 4096 Nov 30 11:45 tests -rw-r--r-- 1 root root 711 Nov 30 11:45 tsconfig.json -rw-r--r-- 1 root root 4120 Nov 30 11:45 vue.config.js -rw-r--r-- 1 root root 559790 Nov 30 11:45 yarn.lock yarn run serve 実行時の例 root ➜ /workspaces/vue/vue-typescript-admin-template (master ✗) $ yarn run serve yarn run v1.22.15 $ concurrently "npm:mock" "vue-cli-service serve" [mock] npm WARN lifecycle The node binary used for scripts is /tmp/yarn--1638442498826-0.7553495223286655/node but npm is using /usr/local/bin/node itself. Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with. [mock] [mock] > vue-typescript-admin-template@1.0.0 mock /workspaces/vue/vue-typescript-admin-template [mock] > cd mock && ts-node-dev mock-server.ts [mock] [1] Browserslist: caniuse-lite is outdated. Please run: [1] npx browserslist@latest --update-db [1] [1] Why you should do it regularly: [1] https://github.com/browserslist/browserslist#browsers-data-updating [1] INFO Starting development server... [mock] [INFO] 10:54:59 ts-node-dev ver. 1.1.6 (using ts-node ver. 9.1.1, typescript ver. 4.2.3) [1] Starting type checking service... [1] Using 1 worker with 2048MB memory limit [mock] { [mock] info: { [mock] name: 'Mock API', [mock] description: 'Mock API for vue-typescript-admin-template.', [mock] version: '1.0.0' [mock] }, [mock] paths: { [mock] get: [ [mock] '/mock-api/v1/articles', [mock] '/mock-api/v1/articles/:id', [mock] '/mock-api/v1/pageviews', [mock] '/mock-api/v1/transactions', [mock] '/mock-api/v1/roles', [mock] '/mock-api/v1/routes', [mock] '/mock-api/v1/users', [mock] '/mock-api/v1/users/:username' [mock] ], [mock] post: [ [mock] '/mock-api/v1/articles', [mock] '/mock-api/v1/roles', [mock] '/mock-api/v1/users/register', [mock] '/mock-api/v1/users/login', [mock] '/mock-api/v1/users/logout', [mock] '/mock-api/v1/users/info' [mock] ], [mock] put: [ [mock] '/mock-api/v1/articles/:id', [mock] '/mock-api/v1/roles/:id', [mock] '/mock-api/v1/users/:username' [mock] ], [mock] delete: [ [mock] '/mock-api/v1/articles/:id', [mock] '/mock-api/v1/roles/:id', [mock] '/mock-api/v1/users/:username' [mock] ] [mock] } [mock] } [mock] Mock server started on port 9528! yarn run serveで起動できると、自動でアクティブのブラウザのタブで http://localhost:9527/#/login?redirect=%2Fdashboard が開く ログイン画面が表示される ログインボタン押すと、 ダッシュボード画面が表示されます http://localhost:9527/#/dashboard 左のサイドメニューのリンクを押していくとモックAPIサーバ にリクエストされ画面が切り替わります 動いているポート番号 以上で動かしてみる作業は完了です。 他の画面等もさわり、SPAとVue(+ライブラリ)でできることを体感して見ましょう。 設定を見ておきましょう(時間があれば) ファイル /workspaces/vue/vue-typescript-admin-template/vue.config.js が起点となるようなファイルです process.env.XXX は環境用の設定です、nodeの場合によく使われれます。 yarn run serveで動く説明 npm run | yarn run では、 package.jsonの"scripts" に書かれているコマンドが実行されます。 package.json "scripts": { "serve": "concurrently \"npm:mock\" \"vue-cli-service serve\"", "test:unit": "jest --clearCache && vue-cli-service test:unit", "lint": "vue-cli-service lint", "build:prod": "vue-cli-service build", "build:stage": "vue-cli-service build --mode staging", "svg": "vsvg -s ./src/icons/svg -t ./src/icons/components --ext ts --es6", "mock": "cd mock && ts-node-dev mock-server.ts" }, yarn run serve |npm run serve の場合は、「"concurrently \"npm:mock\" \"vue-cli-service serve\""」が動くので vue-cli-service serve が動くことになります。 npm:mock では、"mock": "cd mock && ts-node-dev mock-server.ts" が動きます /workspaces/vue/vue-typescript-admin-template/mock/mock-server.ts が実行されるので、port 9528 でモックAPIサーバが動きます concurrently は複数コマンドを実行できるようにするためのおまじない。https://shigekitakeguchi.com/2016/08/10/1.html の説明を見るとわかりやすいです。 ドキュメント https://armour.github.io/vue-typescript-admin-docs/ に少しだけドキュメントがありますので参考に
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

領域展開「Gradle」で Node.js を制する

失礼しました... はじめに オークファンの大きめのデータを担当するバックエンドシステムでは Kotlin + Spring Boot + Gradle の構成がよく採用されています。少し前まではこの構成で作成されるのは、バッチプログラムや Web API がほとんどでしたが、最近さらに Vue.js を追加して UI を持った Single Page Application (SPA) の Web アプリも作成するようになってきました。 Spring Boot のプロジェクトを Spring Initializr で作成すると、Gradle Wrapper が付属しています。これにより、開発環境では JDK のみ用意するだけでプロジェクトのテストやビルドなどをお手軽に実行できていました。 ところが、JavaScript フレームワークである Vue.js がプロジェクトに追加されたことにより、別途 Node.js 環境を用意しなければいけなくなってしまい、これが結構面倒なうえに、プロジェクトメンバーに開発環境を構築してもらう際にトラブルが発生することが少なくありませんでした。 このような場合には Docker にご登場いただくのが一般的ですが、ここではあえて Docker を使わない縛りを課し、すでにプロジェクトに入っている Gradle での問題解決方法を開示していこうと思います。 個人的には Maven や Gradle (Ant は〇ソ...) 支配下の Java や Kotlin でこれまで戦うことが多かったので、npm (yarn は使いやすいですね...) の支配する不慣れな Node.js に対して有利に戦えるといいなと思ったのが発端でした。 プロジェクトの前提は以下としました。 開発環境に必要なのは JDK のみ Node.js まわりで必要なものは Gradle Plugin for Node で調達 幅広い OS (ここでは macOS、Linux、Windows を想定) で開発可能 今回のサンプルプロジェクトの構築は以下の順序で進めていきます。 Spring Boot プロジェクトの作成 Spring Boot プロジェクトのサブプロジェクト化 Vue.js サブプロジェクトの追加 Spring Boot と Vue.js のサブプロジェクト間の連携 プロジェクトのビルドと実行 サンプルでは Spring Boot と Vue.js を使用しますが、他のものであっても Gradle と Node.js のプロジェクトであれば今回の方法は適用可能なはずです。 コマンドは macOS や Linux の書式で記載しますが、パスの指定をスラッシュ (/) からバックスラッシュ (\) に変更すれば Windows でも実行可能です。 Spring Boot プロジェクトの作成 まず Spring Boot の雛形プロジェクトを Spring Initializr で生成します。 https://start.spring.io/ に Web ブラウザでアクセスし、以下のように選択します。(Group や Artifact などは適宜変更いただいて問題ありません。) GENERATE ボタンをクリックしてプロジェクトをダウンロードして展開します。 $ unzip spring-boot-vue-app.zip プロジェクトのディレクトリ構成は以下のようになっています。 初期の Gradle の設定ファイル settings.gradle.kts と build.gradle.kts は以下の内容になっています。 settings.gradle.kts rootProject.name = "spring-boot-vue-app" build.gradle.kts import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "2.5.7" id("io.spring.dependency-management") version "1.0.11.RELEASE" kotlin("jvm") version "1.5.31" kotlin("plugin.spring") version "1.5.31" } group = "io.aucfan.sample" version = "0.0.1-SNAPSHOT" java.sourceCompatibility = JavaVersion.VERSION_11 repositories { mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") testImplementation("org.springframework.boot:spring-boot-starter-test") } tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "11" } } tasks.withType<Test> { useJUnitPlatform() } 雛形プロジェクトはフラットに 1 つのプロジェクトのみで構成されていますが、これを以下のサブプロジェクトに分割していきます。 spring-boot-vue-app ├── web-flux-server (Spring Boot サブプロジェクト) │   ├── build.gradle.kts │   └── src ├── web-vue2-ui (Vue.js サブプロジェクト) │ └── build.gradle.kts ├── build.gradle.kts └── settings.gradle.kts Spring Boot プロジェクトのサブプロジェクト化 初期の Spring Boot プロジェクトを web-flux-server サブプロジェクトに移動します。以下のように web-flux-server ディレクトリを作成し、src ディレクトリを作成したディレクトリ下に移動します。(設定ファイルは YAML 形式で記述したいので、こっそり application.properties を application.yml に変更しています。) settings.gradle.kts の末尾にサブプロジェクトの情報を追記します。 settings.gradle.kts rootProject.name = "spring-boot-vue-app" include( "web-flux-server", ) プロジェクト直下の build.gradle.kts を以下の内容と、サブプロジェクト下の web-flux-server/build.gradle.kts に分割します。変更の概要は次のとおりです。 org.springframework.boot と io.spring.dependency-management のプラグインの行の末尾に apply false を追記 group と version の定義を allprojects 内に移動 dependencies 以降を subprojects 内に移動 java.sourceCompatibility 行を subprojects 内に移動 repositories を subprojects 内にもコピー subprojects 内で Kotlin 関連のプラグインを apply web-flux-server ディレクトリ内にサブプロジェクト用の build.gradle.kts を作成 親プロジェクト build.gradle.kts の subprojects から Spring 関連の dependencies と tasks を web-flux-server/build.gradle.kts へ移動 web-flux-server/build.gradle.kts で Spring 関連のプラグインを apply web-flux-server/build.gradle.kts に WebFlux や開発用、デプロイ用の dependencies と tasks を追加 build.gradle.kts import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { // apply false を付加してデフォルトでは術式を発動させないようにする id("org.springframework.boot") version "2.5.7" apply false id("io.spring.dependency-management") version "1.0.11.RELEASE" apply false kotlin("jvm") version "1.5.31" kotlin("plugin.spring") version "1.5.31" } allprojects { group = "io.aucfan.sample" version = "0.0.1-SNAPSHOT" } repositories { mavenCentral() } // サブプロジェクト共通設定 subprojects { // Kotlin 関連のプラグインを発動させる apply(plugin = "kotlin") apply(plugin = "org.jetbrains.kotlin.plugin.spring") java.sourceCompatibility = JavaVersion.VERSION_11 repositories { mavenCentral() } dependencies { implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "11" } } tasks.withType<Jar> { // JAR ファイル名の基本部分が <プロジェクト名>-<サブプロジェクト名> となるように設定 archiveBaseName.set(listOf(rootProject.name, project.name).joinToString("-")) } } web-flux-server/build.gradle.kts // Spring 関連のプラグインを発動させる apply(plugin = "org.springframework.boot") apply(plugin = "io.spring.dependency-management") dependencies { // サブプロジェクトでは developmentOnly がそのままでは呼び出せないので強制召喚 val developmentOnly = configurations.getByName("developmentOnly") // WebFlux に必要 implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") // 開発ツール developmentOnly("org.springframework.boot:spring-boot-devtools") testImplementation("org.springframework.boot:spring-boot-starter-test") } tasks.withType<Test> { useJUnitPlatform() } // JAR に起動スクリプトを埋め込んで単体で実行可能にする tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar> { launchScript() } Vue.js サブプロジェクトの追加 Spring Boot プロジェクトをサブプロジェクトに移動できたので、同様に Vue.js サブプロジェクトも追加していきます。 本来であればこちらは Node.js の領域なのですが、Gradle 領域を展開していきます。 Node.js まわりを Gradle で管理するために Gradle Plugin for Node を導入します。 以下のように web-vue2-ui ディレクトリを作成し、サブプロジェクト用の build.gradle.kts を作成します。 settings.gradle.kts に web-vue2-ui サブプロジェクトを追加します。 settings.gradle.kts rootProject.name = "spring-boot-vue-app" include( "web-flux-server", "web-vue2-ui", ) 親プロジェクト直下の build.gradle.kts に Gradle Plugin for Node を apply false で追加します。 build.gradle.kts import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "2.5.7" apply false id("io.spring.dependency-management") version "1.0.11.RELEASE" apply false // Gradle Plugin for Node を追加 (デフォルトでは発動させない) id("com.github.node-gradle.node") version "3.1.1" apply false kotlin("jvm") version "1.5.31" kotlin("plugin.spring") version "1.5.31" } // (後略) Vue.js サブプロジェクト用の web-vue2-ui/build.gradle.kts に以下を記述します。ここでは、web-vue2-ui/.cache/ ディレクトリ下に Node.js、npm、yarn がダウンロードされて配置されるように設定しています。 web-vue2-ui/build.gradle.kts import com.github.gradle.node.NodeExtension import com.github.gradle.node.npm.proxy.ProxySettings // Gradle Plugin for Node を発動させる apply(plugin = "com.github.node-gradle.node") // サブプロジェクトでは node が呼び出せないので強制召喚 configure<NodeExtension> { download.set(true) version.set("14.18.1") npmVersion.set("6.14.15") yarnVersion.set("1.22.17") distBaseUrl.set("https://nodejs.org/dist") npmInstallCommand.set("ci") workDir.set(file("${project.projectDir}/.cache/nodejs")) npmWorkDir.set(file("${project.projectDir}/.cache/npm")) yarnWorkDir.set(file("${project.projectDir}/.cache/yarn")) nodeProjectDir.set(file("${project.projectDir}")) nodeProxySettings.set(ProxySettings.SMART) } Node.js、npm、yarn の本体が .cache ディレクトリに取得されるように Gradle Plugin for Node 経由で yarn コマンドを素振りしておきます。 $ ./gradlew :web-vue2-ui:yarn 以下のように nodejs、npm、yarn ディレクトリが設定したとおりに作成され、Node.js まわりを閉じ込めることに成功しました。 これで yarn コマンドが呼び出せるようになったので、Vue.js プロジェクトを作成していきます。今回は Vue CLI を使用して Vue.js 2 のシンプルなプロジェクトを作成してみます。一般的には Vue CLI は global にインストールすることがほとんどだと思いますが、ここでは使い捨てのプロジェクト内にインストールします。 以下のように web-vue2-ui ディレクトリに入って、yarn コマンドで使い捨てプロジェクトを作成します。 (Windows の場合は yarn のディレクトリが少し異なり、.cache\yarn\yarn-v1.22.17\yarn となるようです。) $ cd web-vue2-ui $ .cache/yarn/yarn-v1.22.17/bin/yarn init yarn init v1.22.17 question name (web-vue2-ui): spring-boot-vue-app-ui question version (1.0.0): 0.0.1 question description: Spring Boot + Vue application question entry point (index.js): question repository url: question author: question license (MIT): question private: success Saved package.json 作成された使い捨てプロジェクトに Vue CLI を追加します。前述のとおり、ふつうは yarn global add @vue/cli とするのですが、Vue CLI が Gradle 領域の外に逃げてしまうので、ここでは global を指定していません。 $ .cache/yarn/yarn-v1.22.17/bin/yarn add @vue/cli 一時的に vue コマンドが使用できるようになったので、以下のようにシンプルな Vue.js 2 のプロジェクトを作成します。 $ ./node_modules/.bin/vue create spring-boot-vue-app-ui Vue CLI v4.5.15 ? Please pick a preset: Default ([Vue 2] babel, eslint) ? Pick the package manager to use when installing dependencies: Yarn web-vue2-ui/spring-boot-vue-app-ui 下にプロジェクトが生成されたので、1 階層上に移動させます。その際に不必要になった一時的な使い捨てプロジェクト用の node_modules、package.json、yarn.lock は削除してしまいます。また、作成された Vue.js プロジェクト内に Git 用の隠しディレクトリ .git が作成されてしまうので、こちらは移動せずに削除し、.gitignore ファイルのみ移動しています。 $ rm -rf node_modules package.json yarn.lock $ mv spring-boot-vue-app-ui/* . $ mv spring-boot-vue-app-ui/.gitignore . $ rm -rf spring-boot-vue-app-ui .cache ディレクトリを Git 管理対象外にするために、web-vue2-ui/.gitignore の方に定義を追加しておきます。 web-vue2-ui/.gitignore .DS_Store node_modules /dist # 以下を追記 /.cache # (後略) 最終的に web-vue2-ui サブプロジェクトのディレクトリ構成は以下のようになります。 (作成した Vue.js プロジェクトによって構成は変わる場合があります。) vue コマンドで生成された package.json の内容は以下です。 web-vue2-ui/package.json { "name": "spring-boot-vue-app-ui", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" }, "dependencies": { "core-js": "^3.6.5", "vue": "^2.6.11" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-service": "~4.5.0", "babel-eslint": "^10.1.0", "eslint": "^6.7.2", "eslint-plugin-vue": "^6.2.2", "vue-template-compiler": "^2.6.11" }, "eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/essential", "eslint:recommended" ], "parserOptions": { "parser": "babel-eslint" }, "rules": {} }, "browserslist": [ "> 1%", "last 2 versions", "not dead" ] } 開発用のサーバーを起動して動作を確認しておきます。 $ .cache/yarn/yarn-v1.22.17/bin/yarn serve Web ブラウザで http://localhost:8080/ にアクセスすると以下の画面が表示されます。 この後で起動する Spring Boot の Web サーバーもデフォルトでは 8080 ポートを使用するので、衝突を避けるために開発サーバを Ctrl + C で停止しておきます。(./gradlew :web-vue2-ui:yarn_serve でも開発サーバーは起動できますが、Ctrl + C でプロセスが停止できないのでここでは使用していません。) Spring Boot と Vue.js のサブプロジェクト間の連携 親プロジェクトのディレクトリに戻り、Git リポジトリの初期化を実行しておきます。 $ cd .. $ git init web-vue2-ui/package.json を以下のように変更します。 web-vue2-ui/package.json { "name": "spring-boot-vue-app-ui", "version": "0.0.1", "private": true, "scripts": { "serve": "vue-cli-service serve --port 8081 --watch --mode development", "build": "vue-cli-service build --dest ../web-flux-server/src/main/resources/static/", "lint": "vue-cli-service lint" }, (中略) } vue-cli-service serve --port 8081 --watch --mode development の部分で Vue.js の開発サーバーを設定しています。--port 8081 でポート番号を 8080 から 8081 に変更して帳を下ろしています。これは前述のとおり Spring Boot の WebFlux サーバーもデフォルトでは 8080 ポートを使用するので、衝突を避けるためです。--watch でソースファイルの変更を監視するようにし、--mode development で開発環境であることを設定しています。 vue-cli-service build --dest ../web-flux-server/src/main/resources/static/ の部分では Vue.js のビルドファイルの出力先を、デフォルトの dist から Spring Boot サブプロジェクトのリソースディレクトリに変更しています。 また、親プロジェクトのバージョンに合わせて、version を 0.0.1 に変更しています。 親プロジェクトの .gitignore に以下を追加して、Vue.js ビルドファイルを Git 管理対象外にしておきます。 # (前略) # Vue.js build files /web-flux-server/src/main/resources/static/ Gradle Plugin for Node 経由で Vue.js サブプロジェクトをビルドしてみます。 $ ./gradlew :web-vue2-ui:yarn_build Spring Boot サブプロジェクト側の web-flux-server/src/main/resources/static/ ディレクトリ下に Web ページ用のファイルが生成されます。 Vue.js サブプロジェクトがビルドできたので、Gradle タスク間の依存関係を設定します。 まず、yarn build の前に yarn install が実行されるようにします。(毎回 yarn install を実行する必要はないのですが、すでに必要なパッケージがインストールされている場合は何もしないので、ここでは気にせずに設定してしまいます。) web-vue2-ui/build.gradle.kts import com.github.gradle.node.NodeExtension import com.github.gradle.node.npm.proxy.ProxySettings apply(plugin = "com.github.node-gradle.node") // サブプロジェクトでは node が呼び出せないので強制召喚 configure<NodeExtension> { download.set(true) version.set("14.18.1") npmVersion.set("6.14.15") yarnVersion.set("1.22.17") distBaseUrl.set("https://nodejs.org/dist") npmInstallCommand.set("ci") workDir.set(file("${project.projectDir}/.cache/nodejs")) npmWorkDir.set(file("${project.projectDir}/.cache/npm")) yarnWorkDir.set(file("${project.projectDir}/.cache/yarn")) nodeProjectDir.set(file("${project.projectDir}")) nodeProxySettings.set(ProxySettings.SMART) } // 以下を追記 // yarn build 前に yarn install を実行する (Gradle Plugin for Node 経由の実行なので _ を付加) tasks.getByName("yarn_build") { dependsOn("yarn_install") } 次に、Spring Boot サブプロジェクトでリソースが処理される前に Vue.js サブプロジェクトをビルドするようにします。 web-flux-server/build.gradle.kts import org.springframework.boot.gradle.tasks.bundling.BootJar apply(plugin = "org.springframework.boot") apply(plugin = "io.spring.dependency-management") dependencies { // サブプロジェクトでは developmentOnly がそのままでは呼び出せないので強制召喚 val developmentOnly = configurations.getByName("developmentOnly") implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") developmentOnly("org.springframework.boot:spring-boot-devtools") testImplementation("org.springframework.boot:spring-boot-starter-test") } tasks.withType<Test> { useJUnitPlatform() } tasks.withType<BootJar> { launchScript() } // 以下を追記 // リソース処理の前に Vue.js サブプロジェクトのビルドを実行 tasks.withType<ProcessResources> { dependsOn(":web-vue2-ui:yarn_build") } これだけでは Spring Boot サブプロジェクト内のリソースに配置されたファイルを公開できないので、IndexHandler.kt と IndexRouterConfiguration.kt ファイルを以下のように作成します。 IndexHandler.kt には以下の内容を記述します。 IndexHandler.kt package io.aucfan.sample.spring.boot.vue import org.springframework.beans.factory.annotation.Value import org.springframework.core.io.Resource import org.springframework.http.MediaType import org.springframework.stereotype.Component import org.springframework.web.reactive.function.server.ServerRequest import org.springframework.web.reactive.function.server.ServerResponse import org.springframework.web.reactive.function.server.bodyValueAndAwait @Component class IndexHandler { @Value("classpath:/static/index.html") private lateinit var indexHtml: Resource suspend fun index(request: ServerRequest): ServerResponse = ServerResponse.ok() .contentType(MediaType.TEXT_HTML) .bodyValueAndAwait(indexHtml) } IndexRouterConfiguration.kt には以下を記述します。 IndexRouterConfiguration.kt package io.aucfan.sample.spring.boot.vue import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.io.ClassPathResource import org.springframework.web.reactive.function.server.RouterFunctions import org.springframework.web.reactive.function.server.coRouter @Configuration class IndexRouterConfiguration { @Bean fun indexRouter(indexHandler: IndexHandler) = coRouter { GET("/", indexHandler::index) } fun staticResourceRouter() = RouterFunctions.resources("/**", ClassPathResource("static/")) } プロジェクトのビルドと実行 以上で準備ができたので、親プロジェクトのディレクトリで (テストを省略して) ビルドを実行します。 $ ./gradlew clean build -x test Spring Boot サブプロジェクトの web-flux-server の build/libs/ ディレクトリ下に spring-boot-vue-app-web-flux-server-0.0.1-SNAPSHOT.jar が具現化されます。 spring-boot-vue-app-web-flux-server-0.0.1-SNAPSHOT.jar を JVM に流し込んで実行してみます。 $ cd web-flux-server/build/libs/ $ java -jar spring-boot-vue-app-web-flux-server-0.0.1-SNAPSHOT.jar Web ブラウザで http://localhost:8080/ にアクセスすると以下の画面が再度表示されます。(この時点では前述の Vue.js の開発用サーバーは http://localhost:8081/ でのアクセスに変更されています。) ここまでのプロジェクト構築では Spring Boot の WebFlux サーバーに何の Web API も実装されていません。ここから Web API を Kotlin で実装し、Vue.js から axios で利用するように開発を進めていくことになります。 おわりに 今回ご紹介したプロジェクトで作成された Web アプリをデプロイする最もシンプルな方法は以下のような手順になります。 開発環境に JDK を導入 プロジェクトを git clone プロジェクトのディレクトリで ./gradlew clean build -x test 作成された JAR を稼働環境に配置 稼働環境に JRE を導入 JAR を実行 (サービス化も可能) 実際のプロジェクトではさらに、JAR ファイルの外側から読み込む環境依存の設定ファイルの配置や、Docker イメージにして自動デプロイなどもろもろ追加されていきます。 このように Node.js 関連の儀式を明示的に行うことなく、Gradle 領域内にうまく閉じ込めることができたので、今までどおり心穏やかにデプロイ作業を進めることができています。(とはいえ開発時は Node.js 領域内に入って戦うことになるのですが...) 他にも以下のようなメリットがあるので、今後の SPA プロジェクトでも適している場面があれば採用していこうと思います。 開発環境構築時も同様に Node.js 環境を別途用意する必要がない Vue.js 2 から Vue.js 3 や Nuxt.js、React、Next.js などに変更する場合も別領域サブプロジェクトを展開して対応可能 Node.js から見ると領域は外界と隔絶されているので、UI のサブプロジェクト内では異なる Node.js のバージョンを採用可能 最後に... 劇場版「呪術廻戦 0」 12 月 24 日公開です。ぜひ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsの基本をまとめる(特徴など)

【はじめに】 フレームワークとは よくある問題に対するイディオム、方法をまとめたもの。 本格的なアプリを開発していると、似た問題によく遭遇する。 それを毎回解決していくのは大変&面倒!(前もやったのに、、!) →よくある問題解決をあらかじめ用意しておいてくれる「フレームワーク」! ただし、フレームワークの導入がいつでも正なわけではない。小さいアプリならわざわざフレームワークを学ぶ方が悪 主なJSのフレームワークは3つ Name about description Angular Googleを中心に開発されてるフルスタックフレームワーク 学習コスト高め・比較的難しい・途中からの導入は厄介。最初からちゃんと設計されてこそ力を発揮する React Facebookが開発したフレームワークで、ビュー(見た目)相当の機能を提供 比較的気軽に導入できる・後からの導入もしやすい Vue.js ビューに特化したシンプルなフレームワーク 比較的気軽に導入できる・後からの導入もしやすい。 Vueの特徴 React と比べても特に学習コストが低い アプリの成長に合わせての機能追加がしやすい(コンポーネント 作成・ルーティング機能..) コンポーネント指向 ....コンポーネントとは、ビュー(見た目)、ロジック、スタイルなどから成るUI部品のこと。Vueでは、部品化されたコンポーネントを組み合わせることで1つのページを構成していく。=コンポーネント思考。組み合わせてり、入れ子にしたり。。。 ライブラリが豊富 簡単に言うなら「UIを宣言的に記述するためのライブラリ」 あるデータをもとにページを作成。そのデータが変化した際に、UIを再構築して画面に反映させる。これがVueの基本機能。 Vueが支持されるわけ 様々な言語に対応したドキュメント より良い機能の提供、メンテナンスがされ続ける 昔は小ー中規模向きとされ、問題がいくつかあったが、アップデートされ、大規模アプリでも幅広くカバーされるようになった。 2020年にはGitHubスター数がReact, Angularをしのぐほどになっている。日本ではLineと言った大手からhey, STUDIOなど中規模以上のアプリにも使われている。 【Vueの基本】 核となるのはvueクラス Vue.js を起動させるにはVueクラスをインスタンス化する   new Vue({...}) アプリで利用するデータはオブジェクトで用意しておく。テンプレートからこれを参照する、という役割が基本。 Vue.jsを理解するための3つの柱 (1)ディレクティブ まずVueのtemplateを構成するのは、まずこの2点。 {{...}} Mastachek構文 与えられた値を組み込む v-...属性 ディレクティブ v-ifなどの様々な機能 ディレクティブを使って機能をつけたり、データを埋め込んだりする (2)算出プロパティ <div id="app"> <p>{{ email.split('@').toLowercase() }}</p> </div> //computed.js new.Vue([ el: '#app' data: { email: 'Y_SUZUKI@gmail.com' } ]) わかりづらい、テンプレートはシンプルであるべき ↓ここで <div id="app"> <p>{{ localEmail }}</p> </div> //computed.js new.Vue([ el: '#app' data: { email: 'Y_SUZUKI@gmail.com' }, computed{ localEmail():{ return this.email.split('@').toLowercase() } ]) 算出プロパティとは、既存のプロパティを算出した結果を取得できるゲッターのこと。 プロパティ:関数名.... の形で書く ちなみに?... 算出プロパティvsメソッド 算出プロパティは引数を持てない 引数がいるならメソッド 算出プロパティは取得に使う 算出;既存データの「加工を伴う取得」。 メソッド;取得・操作・更新が可能。算出でできることはできる 引数を伴わない単純な加工や演算は、算出プロパティを使ったほうがコードの意図が明確になって良い 算出プロパティはキャッシュされる 算出;depsが更新されるまで更新されない メソッド;常に実行される (3)ライフサイクル Vueのインスタンス; 生成→要素にマウントされる→データの変更に応じてビューを更新→破棄 created...まだマウント前。文書ツリーへのアクセスはmounted後 リアクティブデータ リアクティブデータとは、 Vueクラスのdataオプションに登録されたデータのこと。 データオブジェクトの変化を検知して、ページに自動反映させることから、リアクティブ(=反映できる)と呼ばれる。 ここで、Vueアプリを開発する上で陥りがちな罠について見ていく! (1)リアクティブシステムの制約 開発者は、リアクティブシステムの内部的な挙動を基本意識する必要はない。 が、Javascript  の機能上の制約より、Vueは追加や消去を検知できないため、そこは気をつけなくてはいけない。 そこで、解決策は 全てのプロパティを最初に準備する 最初に値が決まっていない場合でも、最低限、空値でプロパティを用意しておく(アプリで利用するデータを一望できるという意味でも良い) プロパティ追加をVue.jsに通知する Vue.setなどのメソッドを使って追加+追加を通知する (2)ビューの非同期更新を理解する リアクティブシステムによるページの(ビュー)の更新は、非同期! Vueではデータの変更を検知しても、これをすぐにページ(ビュー)に反映するわけではない。 連動して発生する全ての変更をためた上で、最終的な結果をビューに反映させる。 →余計な描写を防いでいる →ページに表示されたものを関数内で使う場合などは注意! (3)ウォッチャーによる明示的な監視 更新のタイミングを手動で制御したい時がある。 例えば、入力値がどんどん更新されるときに、都度リストを取得するのが無駄な時がある。 →入力の切れ目にだけ処理を実行させたい、とする。 そこでwatcher!! 細かい書き方はここには明記しないが、 監視すべきプロパティ、変更後のプロパティの値、変更前のプロパティの値、プロパティ変更時に実行すべき値がセットできる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スマートフォンで魚釣りして夢が釣れるwebアプリ

フィーーーーーーーーーッシュ 年齢がバレてしまいますね。 スマホ一つで直感操作。楽しく魚を釣りましょう。 未完です。完成記事は以下のアドベントカレンダーに投稿します。 操作方法 スマートフォンから以下のQRコードを読み取ってください。 加速度センサーが必要なので、ブラウザでは動作しません。 スマートフォンを振り上げる動作を検知して、y方向の加速度を緯度、z方向の加速度を経度として、スプレッドシートに記録していきます。 開発中に撮影したものなので、画面上にはフィッシュと出力されていますが、ここに緯度・経度として設定する数値が出力されるイメージです。 その後シートに記録された経緯と東京の経緯差から距離を測定、LINE notifyに返してくれます。 まるで旅をしているような気分になれる、夢を釣るアプリです。 スマホにいきなり6件も通知来て何かと思ったら、” 夢 ”でした。 開発環境、使用アプリ・ライブラリ CodePen integromat Netlify Stein-js-client Vue.js 作り方詳細 CodePen部分 See the Pen 釣り by watanabe-tsubasa (@watanabe-tsubasa) on CodePen. 27行目から32行目で加速度の最高値を記録し、加速度がyかつz方向で15m/s^2を記録すると、スプレッドシート上にその時のy,z方向の加速度が、緯度・経度として出力されます。 動かしてみるとわかりますが、加速度変化はdevicemotionで常時変化を観測しております。 出力後、再度最高値を0に戻す処理をしてプログラムを継続するので、勢いよく振り抜くと、1振りで複数回スプレッドシート上に出力されます。 加速度の閾値(今回は15m/s^2)を変更することで、振り抜く速度に応じた出力個数を調整可能です。 複数回転記されれば、複数個所の距離が返ってくるので、世界中を旅した気分が味わえます。 Vue.js, steinを使用しているのでCodePenにライブラリを埋め込んでください。 詳細はこちら展開ください 編集画面上部 Settingsを開く JS Add External Scripts/Pensに以下のURLを入力 https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js //Vue.js https://unpkg.com/stein-js-client //stein-js-client iOSで加速度センサーを有効にするためにはデプロイが必要です。今回はNetlifyを使用しています。 詳細はこちら展開ください Export .zipより圧縮ファイルをダウンロードし解凍 解凍されたファイルのうちdistをフォルダごとNetlifyのサイトにドラッグ&ドロップ 黄色の中にドロップ URLが出力されるので、デプロイされています。 integromat部分 スプレッドシートにはあらかじめA1にlatitude,B1にlongitude を記載しておきます。 GPS Toolsはoriginに東京、destinationに取得した経緯を記載しています。 最後に計算した距離が最大15分後にLINEに帰ってきます。 但し、QRリンク先のアプリで釣りをしても、残念ながら通知先は私のスマートフォンです。 誰かが釣りをしているんだな、とうれしくなりますので、ぜひ実施していただけるとありがたいです。 釣果については、15分後に聞いてください。 追記 想定の100倍くらい通知くるので、ある程度溜まったらTwitterに投稿するようにします。 追記2 通知は1時間ごとにします。一日の最後に釣果を報告させていただきます。 皆さま、ありがとうございます。 今後の改善点 フィーーーッシュと叫んで、釣りをスタートさせる スプレッドシートに、一定数のログがたまったら消去する機能を、GASで付随する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js devtoolsの使い方まとめ

はじめに こちらでは vue.js のdevtoolsについて使い方を簡単に解説します。 devtoolsとは Vue.js devtoolsは、Vue.jsの開発をサポートする Chromeブラウザの拡張機能 になります。こちらを導入すると、consoleを開かなくてもdataの中身などを確認/編集することができる ようになります。言い換えると、デバッグしやすくなるということです。 ★ devtools は以下からインストールが可能です インストールができていれば、Vue.jsを読み込んでいるファイルをブラウザ上で開くと、Vue.js Devtoolsのアイコンがアクティブになります。また、ディベロッパーツールを開くと、vueというタブが追加されます。 ↑アイコンがアクティブな状態 ↑ディベロッパーツールのタブ devtools の主な機能 今回は主な機能を3つ紹介します。 1.Components 2.Vuex 3.Events 1. Components Components機能を使用することで、各コンポーネントの親子関係や保持しているdataの内容などを確認することが可能になります。 ・操作方法は3つです。 1. ディベロッパーツールのvueタブからComponentsを選択します。 2. Componentsの左下にあるselectsを選択します。 3. カーソルを任意のコンポーネントへ移動させます。 以上の操作で、任意のコンポーネントの親子関係や、保持しているdataの内容を確認することができます。 2. Vuex Vuex機能を使用することで、Vuex※を使用している場合、storeの中の状態を確認することが可能になります。 ※Vuexとは何か-公式ドキュメントより参照 ・操作方法は2つです。 1. ディベロッパーツールのタブからVuexを選択します。 2. ディベロッパーツール内に表示されている任意のデータを選択して内容を確認します。 以上の操作で、Vuexを使用している場合、storeの中の状態を確認することができます。 3. Events Events機能を使用することで、イベントがトリガーされた履歴を確認することが可能になります。 ・操作方法は3つです。 1. ディベロッパーツールのタブからEventsを選択します。 2. 任意のイベントをトリガーします。※画面をスクロールするなど 3. ディベロッパーツール内に表示されている任意の履歴を選択して内容を確認します。 まとめ 今回は、Vue.js devtools の使い方を簡単にまとめました。今後新しい使い方などを発見した際は追記します。 実際に私が使ってみた感想としては、わざわざコンソールでデータの中身を確認したりする必要がなくなり、デバッグが楽にできるなと思いました。ぜひみなさんも使ってみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue3 の v-model を読む

はじめに Vue の特徴の 1 つである双方向バインディングを実現する v-model は意外と多くの機能があり、日本語の説明を読むだけでは完全に理解するのは難しいです。 ですがソースコードを読めば案外簡単に理解できるものなので、ソースコードを読んだことがない!という人に向けて、どうやってコードを読んだかをまとめます。 該当する処理が書いてあるファイルを探す なにはともあれ Vue3 のリポジトリを開きます。 https://github.com/vuejs/vue-next 最近のフロントエンドのライブラリは複数のパッケージに分割され packages というディレクトリが用意されていることが多いのでとりあえず packages を開きます。 ざっくりパッケージ名を眺めると vue という本体っぽいディレクトリがありました。 とりあえず中身を確認してみましょう。 src ディレクトリがあったため潜ってみると 3 ファイルしかなく、それぞれを開いてみても数十行程度のファイルでどうやら v-model に関する処理はなさそうです 気を取り直してパッケージの一覧に戻り、次は今回は SSR などではなく、ブラウザで実行するコードを探したいので、dom というサフィックスの付いた compiler-dom, runtime-dom をみてみましょう。 Vue3 は CDN から script タグで読み込むこともできるので、それに関するパッケージなのでは?というあたりをつけて、まずは runtime-dom を開いてみます。 src を開いてみると directives があり v-model はディレクティブと呼ばれる要素なのでとりあえず開いてみます。 そうするとちょうど vModel.ts というファイルが見つかりました! さっそく開いてみましょう。 vModel.ts を読む 上からざっと目を通してみると getModelAssigner という関数内で vnode.props!['onUpdate:modelValue'] という処理が書かれており、 Vue3 の v-model は update:modelValue というイベント使っているので、これに関連する処理だと思われます。 とりあえずどこから呼び出されているかをブラウザの検索機能を使って調べて見ましょう。 そうすると vModelText という変数の宣言内の el._assign = getModelAssigner(vnode) という処理で使われていました。 これは created という関数内の処理であり、おそらく変数名から <input type='text'/> が読み込まれたときに v-model が設定されていたときに実行される処理であることが予想できます。 また一旦読み進める上では必要なさそうですが、beforeUpdate など他のライフサイクル関数も定義されていて、読み込まれた瞬間以外にも何かしら処理を行っていることも読み取れます。 さらに読み進めると el.value から取り出した値を trim modifier(v-model.trim)が付いていれば trim し、また数値に変換できるなら変換してから、el._assign を呼び出しています。 el._assign は onUpdate:modelValue の呼び出しですが、これがなぜ双方向バインディングになるかは後で調べることとして、とりあえず先に進みましょう。 次に vModelText がどこで使われているかを確認してみましょう。 関数名をブラウザ上で検索すると callModelHook -> vModelDynamic にたどり着きます。 vModel.ts 内で vModelDynamic は参照されていないので GitHub の検索で vModelDynamic を検索してみます。 ※ ちなみに callModelHook の処理から vModelText は <input type="text"> だけでなく、<select />, <input type="radio"/>, <input type="checkbox"/> 以外のタグ全てで利用されるようです。 (カスタムコンポーネントの場合も使われる?) すると packages/vue-compat/src/createCompatVue.ts というファイルで利用されていました。 vue-compat とは Vue2 -> Vue3 へ移行するための移行用ビルドで、Vue3 で変更されたり、非推奨となった機能を使用すると警告が出るようになっているものです。 処理の内容としては app._context.directives.model = vModelDynamic となっており、v-model と vModelDynamic を紐付ける内容になっています。 これは移行用ビルドであり Vue3 とはまた違ったパッケージではありますが、 やはり vModelDynamic が v-model の処理と考えてよさそうです。 vModelText 以外を読む vModelText のちょうど直後に他のタグの場合の処理の定義もあったので読んでみましょう。 vModelCheckbox if (isArray(modelValue)), else if (isSet(modelValue)) で処理を分岐していて、modelValue に設定した値が配列か、 Set かそれ以外かで大きく処理が異なるようですね。 配列の場合は、チェックが入れらたときは、その配列に値を追加(.concat)し、チェックを外した場合は 値を削除 (.splice)しているようです。 Set の場合はチェックの有無でそれぞれ add, delete を呼んでいます。 その他の場合はシンプルにvalue に設定された値を el._assign に渡しています。 vModelRadio ラジオボタンの場合はシンプルに value に設定された値を el._assign に渡しています。 vModelSelect セレクトの場合は option の中から selected な要素の value に設定された値を el._assign に渡しています。 multiple の場合は配列のまま渡していますね。 onUpdate:modelValue を調べる 次に途中で後回しにした onUpdate:modelValue を呼び出すとなぜ双方向バインディングになるか?を調べたいと思います。 GitHub 上で onUpdate modelValue を検索します。 (: をつけるとヒットしなかったので外しています。) テストファイルを無視していくと packages/compiler-core/src/transforms/vModel.ts がヒットしました。 ここで宣言している eventName は assignmentExp と一緒に createObjectProperty の引数に渡されていました。 またコメントからこの部分が $event => (foo = $event) になり、v-model に設定された変数に、渡された引数を代入(assign)する処理になっているようです。 なので vModel.ts 内では el._assign という名前で扱っていたということですね。 つまり v-model="foo" は vModelText, vModelCheckbox, vModelRadio 内の処理を経て foo = $event が実行されることで双方向バインディングが実現されていることがわかりました。 createObjectProperty(eventName, assignmentExp) がどのように $event => (foo = $event) となるのかは長くなりそうだったので、また別の機会に読んで見たいと思います。 おわりに 今回は予測多めにあまり裏付けを取るようなとこまではやっておらず、間違っている箇所もあるかもしれませんが、 コードを読むことで v-model がどのような処理を行っているのかが理解できますし、読んでいる中で関係ない箇所でも理解が深まるので あまり難しく考えすぎずとりあえずソースコードを読んで見るという習慣をつけるのもいいのではないでしょうか。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】【Vue】 など流行りのフレームワークを使うもののためのオブジェクト指向とは

流行りのフレームワークを使っていると忘れがち(意識しなくてよい)JSの基礎を学び直してみた。 オブジェクト指向とは 直訳するとオブジェクトはモノ。しかしこれではあまりに分かりにくいですよね。 要約すると「現実世界のものに見立ててプログラミングをする方法」になります。 これでも想像つきにくいですよね。つまりこのオブジェクトを使って、わかりやすくプログラミングするよというふわっとした意味らしいです。 ※ { name:"菅田将暉"; age:28; job:"actor" } そして、このオブジェクトを作る方法が2パターンあります。 ★オブジェクトリテラル リテラルというのは文字通りという意味です。これはいつも何気なく使っている書き方です。 const person = { name:"菅田将暉", age:28, job:"actor" } ★クラス クラスというのは ・オブジェクトの設計図 ・クラスから作られたオブジェクトはインスタンスと呼ばれる とりあえず見ていきましょう。 例 class Person { constructor(initName,initAge,initAge) { this.name = initName, this.age = initAge, this.job = initJob } } こういった形でクラスを定義します。 この設計図を使うにはnewというものを用いて、 const masaki = new Person("菅田将暉",28,"actor") と書くと、※で示したオブジェクト同じものが出来上がります。 この設計図からオブジェクトを作ることをインスタンス化と呼び、このmasakiがインスタンスと呼ばれます。(インスタンスという名前は付きましたがオブジェクトです。) 同じもの作るのに、なぜクラスなんか使わなくてはいけないの?と思った方もいるかもしてません。 理由は簡単、クラスは何回も使いまわしできるからです。設計図と呼ばれる所以かもしれません 例えば、 const nana = new Person("小松奈菜",25,"actress") const Mackenyu = new Person("新田 真剣佑",25,"actor") という新しいインスタンスも、簡単に作れてしまうわけです。いまは、オブジェクトのプロパティ(オブジェクトの中の情報)が3つしかないので、そのまま書いてもさほど大変ではありませんが、これが10個もあったりしたら、オブジェクトを3つ作るだけでも、大変ですよね。設計図を書いておけば、情報さえ渡してやれば、いくつも短い記述量でオブジェクトが作れるようになります。 この記事でクラス、インスタンス、コンストラクタあたりを詳しく書いたので、参考にしてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

美男美女+ゆりやんレトリィバァを使って解説するオブジェクトとは

流行りのフレームワークを使っていると忘れがち(意識しなくてよい)JSの基礎を学び直してみた。 オブジェクト指向とは 直訳するとオブジェクトはモノ。しかしこれではあまりに分かりにくいですよね。 要約すると「現実世界のものに見立ててプログラミングをする方法」になります。 これでも想像つきにくいですよね。つまりこのオブジェクトを使って、わかりやすくプログラミングするよというふわっとした意味らしいです。 ※ { name:"菅田将暉"; age:28; job:"actor" } そして、このオブジェクトを作る方法が2パターンあります。 ★オブジェクトリテラル リテラルというのは文字通りという意味です。これはいつも何気なく使っている書き方です。 const person = { name:"菅田将暉", age:28, job:"actor" } ★クラス クラスというのは ・オブジェクトの設計図 ・クラスから作られたオブジェクトはインスタンスと呼ばれる とりあえず見ていきましょう。 例 class Person { constructor(initName,initAge,initJob) { this.name = initName, this.age = initAge, this.job = initJob } } こういった形でクラスを定義します。 この設計図を使うにはnewというものを用いて、 const masaki = new Person("菅田将暉",28,"actor") と書くと、※で示したオブジェクト同じものが出来上がります。 この設計図からオブジェクトを作ることをインスタンス化と呼び、このmasakiがインスタンスと呼ばれます。(インスタンスという名前は付きましたがオブジェクトです。) 同じもの作るのに、なぜクラスなんか使わなくてはいけないの?と思った方もいるかもしてません。 理由は簡単、クラスは何回も使いまわしできるからです。設計図と呼ばれる所以かもしれません 例えば、 const nana = new Person("小松奈菜",25,"actress") const Mackenyu = new Person("新田 真剣佑",25,"actor") という新しいインスタンスも、簡単に作れてしまうわけです。いまは、オブジェクトのプロパティ(オブジェクトの中の情報)が3つしかないので、そのまま書いてもさほど大変ではありませんが、これが10個もあったりしたら、オブジェクトを3つ作るだけでも、大変ですよね。設計図を書いておけば、情報さえ渡してやれば、いくつも短い記述量でオブジェクトが作れるようになります。 この記事でクラス、インスタンス、コンストラクタあたりを詳しく書いたので、参考にしてみてください。 ・クラスの継承 例えば、芸人さんの設計図 [class Comedian]を作るとします。 class Comedian { constructor(initName,initAge,initJob,initCompany) { this.name = initName, this.age = initAge, this.job = initJob, this.company = initCompany } } これでもクラスは作ることができますが、同じようなことを二回書くのはナンセンスですよね。 そこでクラスには、継承という機能があります。 class Comedian extends Person{ } これでPersonクラスを継承できました。 class Comedian extends Person{ } const suda = new Comedian("菅田将暉",28,"actor") こう書けば、※と同じオブジェクトができます。(クラスは芸人さんですが。) このPersonクラスを継承して所属事務所を付けたすと class Comedian extends Person{ constructor(initName,initAge,initJob,initCompany) { // 親クラスのコンストラクタを呼び出す super(initName,initAge,initAge,); this.company = initCompany } } こうかく そしてインスタンス化すると const yuriyann = new Comedian("ゆりやんレトリィバァ",31,"comedian","吉本興業") と書くことができます。 これは const yuriyan = { name: "ゆりやんレトリィバァ", age: 31, job: "comedian", company: "吉本興業", }; というオブジェクトと同じものが出来上がります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DjangoとVue.jsでSPA開発に挑戦

シフト表をSPAで作成する 以前に作成した、シフト表をSPA化することを挑戦しています。 バックエンドは、DjangoでフロントエンドはVue.js。 Django側からSerializerを使ってデータを受け取って、Vue.jsで表示の処理を行います。 vue.js <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component({ components: {} }) export default class Schedule extends Vue { get contents() { return this.$pageContents.Schedule } items: Schedule.Schedule[] = [] id: '' // 初期表示時に呼び込み async created() { const [err, res] = await this.$api.schedule.getSchedule() if (!err && res) { this.items = res console.log(res) } } </script> <template> <div> <v-simple-table> <thead> <tr> <th>{{ items[0].open_flg_display }}</th> <template v-for="item in items"> <th v-for="dayweek in item.dayweek" :key="dayweek.index"> {{ dayweek.day }} <br /> {{ dayweek.day_week_display }} </th> </template> </tr> </thead> <tbody v-for="item in items"> <tr v-for="(emp_year_month, index) in item.emp_year_month" :key="emp_year_month.id"> <td> {{ emp_year_month.emp.emp_nm }} </td> <td v-for="schedule, index) in emp_year_month.schedule" :key="schedule.id"> {{ schedule.shift1.name }} <div v-if="schedule.shift2!==null"> {{ schedule.shift2.name }} </div> <div v-if="schedule.shift3!==null"> <v-text class="red">{{ schedule.shift3.name }}</v-text> </div> </td> </tr> </tbody> </v-simple-table> </div> </template> <style lang="scss" scoped></style> 私の参考にしているコードが、テンプレートが下でスクリプトが上なのでそれをまねています。 上下どちらでも、そんな影響はないような気がします。 最初作り始めた時に、標準通り上にTemplateがある状態でしばらくコードを作っていたので(笑) 現在のシフト表 こんな感じで表示できました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsのモーダル表示とバリデーションチェック

Vue.jsでモーダル表示させる方法 qiita.js <template> <div> <button @click="openModal(num)" >モーダル表示ボタン</button> <div class="overlay" v-show="modalContent" > <div class="content"> モーダルで表示させたい内容をここに書きます。 <button @click="closeModal" >Close</button> </div> </div> </div> </template> <script> export default { data(){ return{ modalContent:false, content:'', } }, methods:{ openModal:function(){ this.modalContent = true; }, closeModal:function(){ this.modalContent = false; } } } </script> <style> li{ list-style:none; } .overlay{ z-index:1; position:fixed; top:0; left:0; width:100%; height:100%; background-color:rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; } .content{ z-index:2; width:20%; padding: 1em; background:#fff; } </style> バリデーションチェック qiita.js <template> <div> <p><b>{{title}}</b></p> <!-- v-on:submit.prevent="onSubmit" を追加 --> <form v-on:submit.prevent="onSubmit" > <span>ID : </span> <input type="text" placeholder="input your id" v-model="loginForm.loginId" > <span>ID : </span> <input type="text" placeholder="input your id" v-model="loginForm2.loginPw" > <br> <button v-on:click="checkFrom"> 送信する </button> <p class="error"> {{ Validation.loginerror }} </p> <!-- ここまでを追加 --> </form> </div> </template> <script> export default { props: { title : String }, data: function() { return { loginForm:{ loginId:null, }, loginForm2:{ loginPw:null, },//ここにカンマを追加 //ここから追加 Validation:{ loginReult: "", } //ここまでを追加 } },//ここにカンマを追加 //ここから追加 methods: { checkFrom: function(event){ var LoginRS = false //IDの入力フォームのバリデーション if (!this.loginForm.loginId && !this.loginForm2.loginPw) { this.Validation.loginerror="ログインIDを入力してくださいPWを入力してください" } else if(!this.loginForm.loginId){ this.Validation.loginerror="ログインIDを入力してください" } else if(!this.loginForm2.loginPw){ this.Validation.loginerror="PWを入力してください" } else { LoginRS = true } if(LoginRS == true){ alert('Hello,' + this.loginForm.loginId + '!'); } event.preventDefault() }, } //ここまでを追加 } </script> <style scoped> /* ここから追加 */ .error { color: red; } /* ここまでを追加 */ </style>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む