20210901のvue.jsに関する記事は4件です。

[備忘録]フロント側の対応だけでNginxでキャッシュされた古い画像が表示されないようにする

Nginxで画像ファイルをキャッシュするようにしていたのですが、同じ名前で画像を更新した場合に古い画像がしばらく表示されてしまいます。 かといって、まれにしか更新されない画像のためにキャッシュを無効にするのもイケてないので、解決策を調べてみました。 結論 imgタグのsrcに/path/image.jpg?xxxxxのようにパスの後にランダムな値を指定する ※右クリックで「名前を付けて画像を保存」しても?以降は認識されません。 具体例 参考にした投稿だとランダム値を指定してましたが、それだと常にキャッシュがスルーされてしまうのでレコードの更新日時を指定することにしました。 サーバーから以下のようなテーブルのデータを取得して、imageUrlの後ろに更新日時を指定することで、同名のファイルで更新して画像ファイルのURLが同じだったとしても更新日時が異なるためキャッシュから読み込まれず、最新の画像を表示することができます。 論理名 物理名 型 id ID 画像URL imageUrl string 更新日時 updatedAt string test.vue <template> <div> <img :src="imageUrl" /> </div> </template> <script lang="ts"> item; get imageUrl() { // 更新時に新しい画像が表示されるようにするため、更新日時をファイル名の後ろに付与 return `${this.item.imageUrl}?${moment(this.item.updatedAt).format('YYYYMMDDHHmmss')}`; } ただ、これだと画像URL以外のカラムが更新された場合でも画像を読み直してしまうので、頻繁に更新するようなテーブルの場合は要検討ですね。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ウマ娘のちょっとしたツールを作ってみた ―『ウマ娘レースプランナー』

おはようございます、@aya_seと申します。今回は『ウマ娘 プリティダービー』のちょっとしたツールを作って遊んでみたので、その紹介になります! 注):『ウマ娘 プリティダービー』のゲームシステムに関する基本的な説明は割愛します。 『ウマ娘レースプランナー』 (レース中盤で疲れにくく)なりません。そのかわり、ウマ娘の育成スケジュールの決定を少しだけ手助けしてくれます!とりわけ 固有スキルLvアップやレジェンド達成できる効率的なレース出走スケジュールが知りたい! ファン数稼ぎ(ファン活)の際にどれぐらいのファン数が稼げるか見積もりたい! というようなときに利用できるサイトを目指しました。 つまりは、本来の意味での『レースプランナー』というわけです。具体的には、以下のようなことができます。 ▲見るだけで 肌荒れしそうな スケジュール (575) レース計画 シナリオ・キャラクターを指定して、「ノルマ達成効率重視」「ファン数最大化」の2つの基本戦略からおすすめの出走スケジュールをレコメンドすることができます。 特定の期間までに達成すべきファン数やレース勝利数のノルマを考慮することができます(固有スキルLvUP・キャラの育成目標など)。 レコメンドされたスケジュールをもとに、個別に出走レースを編集してプランをカスタマイズすることができます。 レース一覧表 シナリオ固有のレース・メイクデビュー戦等を除いた全てのレースの一覧を表形式で見ることができます。 アカウントごとに重賞レースのトロフィー獲得状況を管理することができます(※Googleアカウントでログイン済の場合のみ)。 サイトにアクセス こちらのURLにアクセスします。Googleアカウントによるログイン機能を利用することもできます(※今のところトロフィー管理機能以外はログインの必要無し)。 注):多少レスポンシブも意識しているつもりですが、スマートフォンではサイトの動作がやや重い可能性があります。できればタブレット端末やPCでの利用をおすすめします。 レース計画機能について サイトのうち、レース計画機能について少し詳しく紹介します。 ①作成するスケジュールの内容を設定しよう! 作成対象のシナリオ・キャラクターをはじめ、出来る限り現実的なプランとするために、細かな項目を「詳細設定」から設定できます。それぞれの項目の内容は以下の通り(サイト内のヘルプでも同等の内容が確認できます)。 シナリオ・キャラクター・戦略選択 『シナリオ・キャラクター・戦略選択』では、スケジュール作成のための基本情報を設定できます。これらの項目を変更すると自動的におすすめのスケジュールが再設定されます(※レースカレンダーで個別に編集した内容は上書きされるので注意してください)。 シナリオ 育成シナリオを選択できます。 キャラクター 育成するキャラクターを選択できます。 戦略 おすすめスケジュールの作成における基本方針が設定できます。「ファン数最大化」・「ノルマ達成効率重視」の2つの戦略が利用可能です。「ファン数最大化」ではシナリオ等の制約下で可能な限りファン数を稼ぐためにレースに出場します(ファン活・金策向け)。「ノルマ達成効率重視」ではシナリオ上達成すべきファン数のノルマをなるべく少ない出走数で満たすことを目標とします。 詳細設定 『詳細設定』では、スケジュール作成に関わる細かな項目を設定できます。 余裕のあるノルマ達成計画(+%) 予想獲得ファン数は基本的に出走レース全てで1着を取ることが前提となっています(「負けイベント」を除く)が、実際には一部で1着を取り逃すことを想定し、本来のファン数ノルマよりも一定の余裕を持ったスケジューリングを行うことができます。例えば「10%」に設定し、「レジェンド達成(320000人)」のファン数ノルマを有効にした場合、育成終了時に352000人以上のファンを獲得できるようにします(※レースカレンダーから個別に出走レースを編集した場合でもこのノルマ目標を達成できない場合にはアラートが表示されます)。 出走適正下限 出走するレースの適正下限を設定します。適正を満たさないレースは、おすすめのスケジュールの目標外出走対象レースとして選択されないほか、レースカレンダーにも表示されません(ただし、シナリオで目標となっているレースや既に選択中のレースはそのまま表示されます)。 ファンボーナス サポートカードの編成によって変化するファンボーナスの値を設定できます。 最大連続出場レース数 おすすめのスケジュール作成における最大連続出場レース数を設定できます。『レース疲れ』回避のため、基本的にはこの値を「2」以下に設定することを推奨します。なお目標外レースの後にシナリオで目標となっているレースに連続出走する場合は、『レース疲れ』のペナルティが発生しないため、この設定は無視されます。 夏合宿中は目標外レースに出場しない この項目を有効にすると、おすすめのスケジュール作成において夏合宿期間中は目標外レースに出走しなくなります。 適正調節 因子継承等で適性を補正する場合に対応できます。この項目を変更すると、出走適正下限の設定と合わせて、おすすめのスケジュールでの目標外出走対象やレースカレンダーに表示されるスケジュールが変更されます。また、シナリオで目標となっているレースのうち、ウマ娘の適正に合致していないレース(※フィールド・距離適正がA・Aを合計2段階以上下回っている)は「負けイベント」と扱いファン数に加算しませんが、この項目を変更することによりその判定にも影響が出る場合があります。 クラス おすすめのスケジュール作成における目標外出走レース対象や、レースカレンダ―に表示するレースのクラスを設定できます(シナリオで目標となっているレースや既に選択中のレースはそのまま表示されます)。おすすめのスケジュール作成のアルゴリズムでは基本的にファン数の多いGⅠやGⅡのレースが選択されやすい為、一般的な目的であれば、この項目を変更する必要はあまりありません。 ファン数ノルマ一覧 『ファン数ノルマ一覧』では、達成すべきファン数ノルマの一覧を確認したり、各ノルマの有効/無効を切り替えることができます。 全体シナリオの目標 URAシナリオ等で固有スキルレベルアップなどに必要なファン数ノルマです。 ウマ娘のシナリオ目標 一部のウマ娘にはファン数の目標などが設定されています。これらのノルマは必ず達成する必要があるため、無効化することができません。なお、目標人数が「(レース)」となっているものはレース勝利数目標です。 ②スケジュールを作成しよう! これらの設定を適切に設定したところで、「おすすめのスケジュールを作成」ボタンをクリックすることで、条件に合ったスケジュールが作成されます。作成されたスケジュールはレースカレンダーや出走スケジュールに反映されます。 ③スケジュールを確認・編集しよう! 『レースカレンダー』では、各時期に開催される適正内のレースやシナリオの目標となっているレース、目標外として出走するレースを確認できます。また、目標外のレースにおいては個別に出走/非出走を編集することができます。 シナリオの目標となっているレース シナリオの目標となっているレースは赤色で表示されます。同時期のその他のレースは全て非表示になります。 現在のスケジュールで出走予定の目標外レース 現在のスケジュールで出走予定の目標外レースは青色で表示されます。 出走スケジュールボタンをクリックすると、出走するレースのみを時系列順で確認することができます(※ノルマが達成できない場合はこのボタンは非常時になります)。 目標外出走レースの編集 「選択中」もしくは「未選択」と表示されているボタンをクリックすることで各レースごとに個別に出走するかどうかを編集することができ、変更内容はただちに「予想獲得ファン数」や「出走スケジュール」へと反映されます。これらの個別編集は「詳細設定」における「最大連続出場レース数」や「夏合宿中は目標外レースに出場しない」といった設定を無視して行うことができます。なお、キャラクターを変更したり、おすすめのスケジュールを再作成した場合、これらの編集内容は全て上書きされるので注意してください。 ▲先ほどのスケジュールから一部を編集。サマースプリントシリーズ(函館スプリントS・キーンランドS・セントウルS)を出走レースに追加し、京王杯スプリングSを出走レースから除外した。 細かな仕様 予想獲得ファン数の値は「出走レースに全て勝利した場合のファン数最低値」です。実際には獲得ファン数はある程度ランダムであり、出走レースに全て勝利した場合の実際のファン数は予測値の1.00倍~1.09倍の範囲まで変動します。 一部ウマ娘において、適正の合わないレースに出走する場合(いわゆる「負けイベント」)ではファン数をカウントしない(0人扱い)ように配慮し、現実的に達成可能なプランとします。「負けイベント」であるかどうかはフィールドと距離の適正がAから合計で2段階以上下回っているかで判定しており、「詳細設定」から適正調節を行うことで判定が変更となる場合があります(例:マルゼンスキーの有馬記念は通常「負けイベント」扱いになりますが、長距離適性を上げることで判定が変更されます)。 オグリキャップ・スマートファルコンなどのシナリオにおける「特定のクラスのレースで○回○着」という形式の目標にもある程度対応しています。ただし着順を考慮していません。つまり、「条件を満たすクラスのレースに○回以上出走する」と解釈してプランを作成しています。 URAシナリオにおいて、メイクデビュー戦およびURAファイナルズのファン数は固定値として加算しています(メイクデビュー戦で1着を取れなかった場合のジュニア未勝利戦には対応していません)。 URAシナリオにおいて、ダート系のウマ娘は固有スキルレベルアップに必要なファン数条件が緩和される仕様に対応済です。 サイト上に明記していませんが、各レースの出走に必要なファン数条件を考慮したプランニングになっています(「メイクデビュー戦の次に皐月賞」などというようなプランは排除されているはずです、またファン数ボーナスが低すぎるとメイクデビュー戦の次にホープフルS等に出られなくなるはずです)。 最大連続出場レース数は目標外レースに関する設定です。例えば値を2に設定した場合、「目標外・目標外・目標外」「目標外・目標・目標外」というパターンは制限しますが、「目標外・目標外・目標」というようなパターンは制限しません。なお体力0によるレース疲れのリスクは考慮していません。 特にダートや短距離系のウマ娘は、初期設定では条件を満たすプランを作成できない場合があります。この場合はファン数ノルマの一部を無効にしたり、ファン数ボーナスをより高い値にするなど、条件を緩和することで実現可能なプランを作成可能です。 マチカネフクキタルの第2・7目標レースはランダムに決定されますが、こちらは毎日杯・函館記念に固定しています。 フジキセキのシナリオにおける目標分岐は三冠路線に固定しています。 ダイワスカーレットのシナリオにおける目標分岐はオークスに固定しています(改善の余地あり)。 制作に使ったもの 詳しい説明は割愛しますが、使用したものは主に以下です。 Vue.js Firebase Vercel 便利プラグイン各種(vue-modal-js・element-ui・vue-mqなど) 動的計画法 『ウマ娘』攻略wiki各所様 地道なjsonデータ作成作業を遂行する心 おわりに UI等、諸問題はありますが、ファン数見積計算的な用途など、ある程度実用的なツールになったかな……(??)と信じています(そうでもなかったらごめんなさい)。今後も必要に応じて更新していきたいと思います(キャラとかシナリオはどんどん増えますし……)。不具合などまだまだありそうなので、もしお気づきのことがあればご報告いただけると助かります!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js よく使うディレクティブ

Vue.js よく使うディレクティブ v-bind 引数には属性が入る v-bind:id="hogehoge" 値はデータでも算出プロパティでもメソッドでも式でもOK v-bindが付いていれば、vueインスタンスでかいた値や関数を”引っ張ってこれる” 省略形 :id="hogehoge" v-on 引数にはイベントが入る v-on:click="handleClick" 省略形 @click="handleClick" クリックイベントを検知して処理内容が書かれた関数(ここではhandleClick)に”渡す”ようなイメージ v-bind(vueインスタンスから引っ張る)v-on(vueインスタンスに渡す)という向きの違いがある v-model とりあえずv-modelを使えばリアクティブなフォームが完成する template <input v-model="message"> htmlで使用しているvueインスタンスを定義しているファイル script var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }) 例えばv-modelの値にdataのmessageを指定すると 初期値として'Hello Vue!'が見えていて inputを書き換えた瞬間messageが更新される v-modelはmessageを「参照しつつ更新する」 つまり v-model = v-bind:value + v-on:input このvalueとinputはそれぞれv-modelのデフォルトであるが変更も可能 v-if v-ifの値がtrueならv-if以下DOM表示をする ここの表示非表示ではcssの作成イベント削除イベントが適用される v-else v-else-if v-for template <ul> <li v-for="item in items" :key="item.id">{{ item.name }}</li> </ul> itemsの定義(オブジェクトのリスト構造が一般的) script data: { items: [ { id: 1, name: 'りんご' }, { id: 2, name: 'いちご' } ] } keyを設定をもセットで覚える(更新の処理数などが変わるため) keyに指定するのはindexでない方が良い idなど一意に決まるもの
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsでfirebaseのFirestore DatabaseとStorageからVuefireでデータの取得

の個人用メモです。データのPOSTとGET、ファイルのアップロードと読み取りが目標です。Vue.jsのバージョンは2.xで、Vuetify使用しています。 開発環境 node.js : v12.18.3 vue-cli : 4.5.10 yarn : 1.22.10 Firebaseのプロジェクトの作成+α コンソールからプロジェクトを作成 アプリの追加→ウェブからアプリの追加 Firestore DatabaseからDBを作成(ロケーションはasia-northeast1を選択) Storageの読み取り書き込み権限の変更しておく 必要なデータは後で用意します。 VueプロジェクトのFirebaseのセットアップ まずは諸々追加。 yarn add firebase vuefire@next @vue/composition-api srcディレクトリ直下にpluginsディレクトリを作成し、以下2ファイルを追加。 src/plugins/firebase.js import Vue from 'vue'; import firebase from 'firebase/app'; import 'firebase/firestore'; import 'firebase/storage'; import { firestorePlugin } from 'vuefire'; Vue.use(firestorePlugin); const firebaseApp = firebase.initializeApp({ apiKey: process.env.VUE_APP_API_KEY, authDomain: process.env.VUE_APP_AUTH_DOMAIN, projectId: process.env.VUE_APP_PROJECT_ID, storageBucket: process.env.VUE_APP_STORAGE_BUCKET, messagingSenderId: process.env.VUE_APP_MESSAGING_SENDER_ID, appId: process.env.VUE_APP_APP_ID, }); export const db = firebaseApp.firestore(); export default firebase; src/plugins/storage.js import firebase from '@/plugins/firebase'; export const storage = firebase.storage(); FirebaseのApiKey等はプロジェクトの設定から確認。 このApiKey等は公開してしまっても大丈夫だけど、嫌なら.envファイルをディレクトリ直下に作成し、環境変数を使ってアクセス。 env.local VUE_APP_API_KEY="<MY-API-KEY>" VUE_APP_AUTH_DOMAIN="<MY-AUTH-DOMAIN>" VUE_APP_PROJECT_ID="<MY-PROJECT-ID>" VUE_APP_STORAGE_BUCKET="<MY-STORAGE-BUCKET>" VUE_APP_MESSAGING_SENDER_ID="<MY-MESSAGING_SENDER_ID>" VUE_APP_APP_ID="<MY_APP_ID>" main.jsに以下を追加。 main.js import './plugins/firebase'; 最後にStorageからAxiosで引っ張ってくるときのCORSの設定のために、Google Cloud SDKをインストーラからインストール。特に何もいじらないでおk。 インストール終了後ターミナルが開くので初期設定をする。開かない場合はgcloud initから。 プロジェクトのディレクトリ直下にcors.jsonを作成。 cors.json [ { "origin": [ "https://xxxxxxx.web.app", "https://xxxxxxx.firebaseapp.com", "http://localhost:8080", "http://localhost:5000" ], "responseHeader": ["*"], "method": ["GET"], "maxAgeSeconds": 3600 } ] ターミナルからプロジェクトのディレクトリに移動し、CORSの設定をデプロイ。gs://以下はStorage Bucketを指定する(Storageからコピペできる)(最初引っ張ってくる予定のファイルを直接指定していて上手くいかず小一時間詰まりました…)。 //デプロイ gsutil cors set cors.json gs://xxxxxxx.appspot.com //デプロイの確認 gsutil cors get gs://xxxxxxx.appspot.com Firestore Databaseからデータの読み取り書き込み 以下のようなコレクション(テーブル)を作成します。 userドキュメントでuserの延べ人数を管理しています。 以下サンプルコードです。比較としてAxiosで直接取得する場合を併記。 Firestore.vue <template> <v-container> <v-text-field v-model="name" label="name"></v-text-field> <v-text-field v-model.number="age" label="age"></v-text-field> <v-btn @click="postData">post</v-btn> <v-row> <v-col cols="6"> <p>get with vuefire</p> <div v-for="i in firebase" :key="i.name"> <p>name : {{ i.name }}</p> <p>age : {{ i.age }}</p> </div> </v-col> <v-col cols="6"> <p>get with axios</p> <div v-for="i in axios" :key="i.name"> <p>name : {{ i.fields.name.stringValue }}</p> <p>age : {{ i.fields.age.integerValue }}</p> </div> </v-col> </v-row> </v-container> </template> <script> import { db } from '../plugins/firebase'; //エンドポイント const URL = 'https://firestore.googleapis.com/v1/projects/MY_PROJECT_ID/databases/(default)/documents/'; export default { data: () => ({ firebase: [], usersNum: [], axios: [], //書き込む値 name: '', age: '', }), //vuefireでの取得 firestore() { return { firebase: db.collection('users').orderBy('userId'), //データの取得と並び替え usersNum: db.doc('users/user'), //userドキュメントの取得 }; }, async created() { await this.getAxios(); }, methods: { //Axiosでの取得 getAxios() { this.$axios.get(URL + 'users').then((response) => { this.axios = response.data.documents; this.axios.splice(0, 1); //userドキュメントの除外 }); }, //データの書き込み postData() { let id = 0; //usersコレクションが無い場合のidの初期値 this.usersNum ? (id = this.usersNum.totalNumber) : null; id++; //user情報書き込み db.collection('users') .doc(`user${id}`) .set({ userId: id, name: this.name, age: this.age, }) .then(() => { this.name = this.age = ''; }); //延べ人数更新 db.collection('users').doc('user').set({ totalNumber: id }); }, }, }; </script> リアルタイムでデータベースの値拾ってくるのすごい。 今回はコレクション作成のテストを兼ねたので延べ人数取得で面倒くさいことしているけども、適当なコレクション予め作っておく方が楽だと思います。 Storageへのアップロードとデータの読み取り jsonファイルをアップロードし表示します。 ファイルの中身は以下のようになっています。 api.json { "users": [ { "userId": 1, "name": "foo", "age": 111 }, { "userId": 2, "name": "bar", "age": 222 }, { "userId": 3, "name": "baz", "age": 333 } ] } 続いてサンプルコードです。 Storage.vue <template> <v-container> <v-progress-linear v-model="fileLoading" stream></v-progress-linear> <v-file-input v-model="inputFile" accept=".json"></v-file-input> <v-btn :disabled="!inputFile" @click="upload(inputFile)"> submit </v-btn> <div v-for="i in getFile" :key="i.userId" style="white-space: pre-line"> <p>id : {{ i.userId }}</p> <p>name : {{ i.name }}</p> <p>age : {{ i.age }}</p> </div> </v-container> </template> <script> import { storage } from '../plugins/storage'; export default { name: 'Storage', data: () => ({ getFile: [], fileLoading: '', inputFile: null, }), async created() { await this.getStorage(); }, methods: { //ファイルのアップロード upload(file) { const storageRef = storage.ref(`assets/${file.name}`); //ファイルの参照 const uploadTask = storageRef.put(file); //ファイルのアップロード //アップロードとその状況の監視 uploadTask.on( 'state_changed', //送信中 (snapshot) => { const percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; this.fileLoading = percentage; }, //エラー (error) => { console.log(error); }, //完了 () => { uploadTask.snapshot.ref .getDownloadURL() .then((url) => { this.fileLoading = 0; //v-progress-linerの初期化 this.inputFile = null; //ファイル入力欄の初期化 return this.$axios.get(url); }) .then((response) => { const data = response.data; this.getFile = data.users; }); } ); }, getStorage() { const file = storage.ref('assets/api.json'); //ファイルの参照 file .getDownloadURL() .then((url) => { return this.$axios.get(url); }) .then((response) => { const data = response.data; this.getFile = data.users; }); }, }, }; </script> 無事Storageへのアップロードと読み取りができたら完了! 読み取り後に何か処理をする場合は非同期処理にしましょう。 最後に 以下の記事を参考にさせていただきました。感謝! Vue.js、Firebase、axiosでパパッと掲示板! VueでFirestoreのSubscribe機能を使いたい時のアプローチ Firebase Cloud Firestoreの使い方 Firebase StorageにCORSの設定をする Firebase CloudStorageを使ってブログのサムネイルは画像を設定する【Vue.js】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む