20210914のvue.jsに関する記事は10件です。

【個人開発】タイピングゲーム「じゅげ〜む」を作ってみた

はじめに Vue.jsの勉強をかねて、タイピングゲームを作ってみました。 制作期間は5日。 意外と時間をかけてしまいました。 https://flamboyant-beaver-eb2250.netlify.app 使用技術 フレームワーク:Vue.js UIフレームワーク:Vuetify ライブラリ:vue-confetti デプロイ netlify 作ってみての感想 コンポーネントについての理解の甘さを実感し、次はコンポーネントをしっかりと活用したアプリケーションを作成してみたいと思います。 デザインがちょっと物足りなさがあるので、今後バージョンアップするかもしれません。 おわりに 暇な時間のお供に是非ご活用ください。 作ってみてなんですが、私はまだ一度もクリアしてません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

タイピングゲーム「じゅげ〜む」を作ってみた

はじめに Vue.jsの勉強をかねて、タイピングゲームを作ってみました。 制作期間は5日。 意外と時間をかけてしまいました。 https://flamboyant-beaver-eb2250.netlify.app 使用技術 フレームワーク:Vue.js UIフレームワーク:Vuetify ライブラリ:vue-confetti デプロイ netlify 作ってみての感想 コンポーネントについての理解の甘さを実感し、次はコンポーネントをしっかりと活用したアプリケーションを作成してみたいと思います。 デザインがちょっと物足りなさがあるので、今後バージョンアップするかもしれません。 おわりに 暇な時間のお供に是非ご活用ください。 作ってみてなんですが、私はまだ一度もクリアしてません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ViteをVue+Amplifyプロジェクトに導入する時に困ったこと&解決策

はじめに Viteとは、vue-cliと比較して高速で動作するビルドツールです。 筆者はVue.jsとAmplifyを利用したプロジェクトを作成しているのですが、プロジェクトが大きくなるとともにビルド時間が掛かるようになってしまい、困っていました。そこで試しにviteを入れてビルド時間を短縮できるか試すことにしました。 困ったことと解決策 viteがそもそも動作しない amplifyモジュールが古い場合にviteを入れたことで起動しないようです。 モジュールのアップデートを実行しましょう。 viteと相性が悪いモジュールが存在する 筆者の環境ではある1つのモジュールが動作しなかっため、アンインストールしました。 起動後にエラーが発生する 筆者の環境では、コンソール上にUncaught ReferenceError: global is not defined というエラーが発生しました。 こちらのStackOverflowを参考に解決しました。 index.htmlに下記のコードを追加すると解決します。 <script> var global = global || window; var Buffer = Buffer || []; var process = process || { env: { DEBUG: undefined }, version: [] }; </script> 感想&まとめ vite導入前は数分かかっていた起動が数秒に短縮されました。予想以上に早く、非常に可能性を感じました。 ただ、viteを導入する過程でモジュールの置き換えが必要になったことや、動作させるために準備が必要なことから、今回の導入は見送ることにしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JESTでよく使うVueのMockの方法まとめ[Nuxt]

概要 ユニットテストはを楽にするためにMockの仕方を調べることが多かった 以下はよく利用したMockの方法をまとめたものとなる 目次 methodsはWrapperの上書きをする $routerはconfig.mock VuexのSotreはshallowMountに設定 外部ツールはjest.spyOn 環境 "nuxt": "^2.0.0", "vue": "^2.6.11", "vuetify": "^2.2.27", "jest": "^26.6.3", "playwright": "^1.10.0", Mock方法 methodsはWrapperの上書きをする mountまたはshallowMountでWrapperを生成し、Wrapperのmethodを上書きする 全てのテストでmock状態にしたい場合はbeforeEachを使う mock関数色々 https://jestjs.io/ja/docs/mock-function-api テストしたいページ: ~/pages/index.vue <script> export default { methods: { getString() { return 'test1'; }, }, }; </script> テストコード import page from '~/pages/index.vue'; beforeEach(() => { const store = new Vuex.Store({getters}); wrapper = shallowMount(page, {store}); // Methodの上書き wrapper.vm.getString = jest.fn().mockReturnValue('test2'); }); afterEach(() => { wrapper = null; // test毎リセットしておくと安全 }); describe('Methods', () => { test('login: validationエラーの場合', async () => { const result = wrapper.vm.getString(); await flushPromises(); expect(result).toBe('test2'); }); }); $routerはconfig.mock this.$router などthis.$で取得できる情報はconfig.mocksで定義できる 参考:Vue Test Utils Config について import {config} from '@vue/test-utils'; beforeEach(() => { config.mocks['$router'] = { push: jest.fn(), go: jest.fn(), currentRoute: { path: 'dummy_path', }, }; }); VuexのStoreはshallowMountに設定 参考:VueTestUtils Vuex と一緒に使用する より効率的にMockする方法 mock用のファイルを用意して各testファイルでまとめて実装 getters.js (とか actions.js) const getters = { 'test/getter': jest.fn().mockReturnValue(''), }; export default getters; store.test.js import Vuex from 'vuex'; import getters from 'getters.js'; import actions from 'actions.js'; let wrapper; beforeEach(() => { const store = new Vuex.Store({getters, actions}); wrapper = shallowMount(page, {store}); }); 外部ツールはjest.spyOnを使う 例:Auth 参考:jest.spyOn(object, methodName) import Auth from '@aws-amplify/auth'; beforeEach(() => { // currentAuthenticatedUser はMockしたい関数名 jest.spyOn(Auth, 'currentAuthenticatedUser').mockResolvedValue({data: ''}); });
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WindowsなどからLinuxサーバのログを気軽に参照するサーバ

UbuntuなどのLinuxサーバにあるログを参照するためにわざわざSSHでログインするのが面倒なので、ブラウザから参照できるようにした。 適当につくったものなので、セキュリティも何もない。自己責任でお願いします。 画面はこんな感じ。一応行番号も付くようにしています。 ログの先頭や末尾をサクッと見れたり、前ページ・後ページに移動できたりします。 なんならファイルダウンロードもできます。 一応、APIKeyで守ってますが、適当実装なので、ローカルネットワークでのみ使てください。 ソースコードもろもろはGitHubに上げておきました。 poruruba/SimpleLogViewer ソースコード(サーバ) そのままソースコード載せておきます。 api/controllers/tail-file/index.js 'use strict'; const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/'; const Response = require(HELPER_BASE + 'response'); const BinResponse = require(HELPER_BASE + 'binresponse'); const TextResponse = require(HELPER_BASE + 'textresponse'); const APIKEY = "【お好きなAPIKey】"; const logfile_list = [ // 参照したいログファイル名の配列 ]; const { exec } = require('child_process'); const streamBuffers = require('stream-buffers'); const archiver = require('archiver'); const path = require('path'); exports.handler = async (event, context, callback) => { if( event.path == '/tail-view-file'){ if (!event.requestContext.apikeyAuth || event.requestContext.apikeyAuth.apikey != APIKEY ) throw "wrong apikey"; var body = JSON.parse(event.body); console.log(body); if( logfile_list.indexOf(body.fname) < 0 ) throw 'not allowed'; var num = Number(body.num); var start = Number(body.start); return new Promise((resolve, reject) =>{ var exec_batch; if (body.order == 'head'){ exec_batch = `cat -n ${body.fname} | head -n ${start - 1 + num} | tail -n ${num} | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" | col -bx`; } else if (body.order == 'tail'){ exec_batch = `cat -n ${body.fname} | tail -n ${start - 1 + num} | head -n ${num} | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" | col -bx`; }else{ reject('unknown order'); } exec(exec_batch, (err, stdout, stderr) => { if (err) { reject(err); return; } resolve(new TextResponse("text/plain", stdout)); }); }); }else if( event.path == '/tail-get-file'){ if (!event.requestContext.apikeyAuth || event.requestContext.apikeyAuth.apikey != APIKEY ) throw "wrong apikey"; var body = JSON.parse(event.body); console.log(body); if( logfile_list.indexOf(body.fname) < 0 ) throw 'not allowed'; return new Promise((resolve, reject) =>{ var dest_stream = new streamBuffers.WritableStreamBuffer(); const archive = archiver('zip', { zlib: { level: 9 } }); dest_stream.on('finish', () => { console.log('stream finish'); var response = new BinResponse('application/zip', dest_stream.getContents()); response.set_filename(path.basename(body.fname) + '.zip'); resolve(response); }); archive.pipe(dest_stream); archive.on('error', (err) => { reject(err); }); archive.file(body.fname, { name: path.basename(body.fname) }); archive.finalize(); }); }else if( event.path == '/tail-list' ){ return new Response({ list: logfile_list }); } }; 要は、以下のようなコマンドを実行しているだけです。 行番号付けたり、画面制御コードを省いたりしています。 cat -n ${body.fname} | tail -n ${start - 1 + num} | head -n ${num} | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" | col -bx ソースコード(クライアント) クライアント側ソースコード。 特に難しいことはしていません。Vueのおかげで。 public/log_viwer/js/start.js 'use strict'; //const vConsole = new VConsole(); //window.datgui = new dat.GUI(); const base_url = "http://【本サーバのURL】"; var vue_options = { el: "#top", mixins: [mixins_bootstrap], data: { apikey: '', file_list: [], num_of_col: 1, select_file: ["", ""], log_data: ['', ''], select_order: ["tail", "tail"], start_line: [1, 1], get_line: [30, 30], top_line: [-1, -1] }, computed: { class_row: function () { return "col-sm-" + Math.floor(12 / this.num_of_col); } }, methods: { check_top_line: function (index, log_data) { try { var i = 0; for (; ; i++) if (log_data.charAt(i) != ' ' || !log_data.charAt(i)) break; var j = i; for (; ; j++) if (log_data.charAt(j) == ' ' || !log_data.charAt(j)) break; if (i < j) this.top_line[index] = Number(log_data.substring(i, j)); else this.top_line[index] = -1; } catch (error) { console.log(error); } }, add_num: function (index, target, num) { if (target == 'start_line') { var line = this.start_line[index] + num; if (line < 1) line = 1; this.$set(this.start_line, index, line); } else if (target == 'get_line') { var line = this.get_line[index] + num; if (line < 1) line = 1; this.$set(this.get_line, index, line); } }, log_get_file: async function (index) { try { this.progress_open(); var param = { fname: this.select_file[index], }; var blob = await do_post_blob_with_apikey(base_url + "/tail-get-file", param, this.apikey); Cookies.set('tail-apikey', this.apikey, { expires: 3650 }); var url = window.URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.target = '_blank'; a.download = "download.zip"; a.click(); window.URL.revokeObjectURL(url); } catch (error) { console.error(error); alert(error); } finally { this.progress_close(); } }, log_view_file: async function (index) { var param = { fname: this.select_file[index], order: this.select_order[index], start: this.start_line[index], num: this.get_line[index], }; try { var log_data = await do_post_text_with_apikey(base_url + "/tail-view-file", param, this.apikey); if (!log_data) return; this.check_top_line(index, log_data); this.$set(this.log_data, index, log_data); Cookies.set('tail-apikey', this.apikey, { expires: 3650 }); } catch (error) { console.error(error); alert(error); } }, log_next: async function (index) { if (this.top_line[index] < 0) return; var start; if (this.select_order[index] == 'tail') { start = this.top_line[index] - this.get_line[index]; if (start < 1) start = 1; } else if (this.select_order[index] == 'head') { start = this.top_line[index] + this.get_line[index]; } var param = { fname: this.select_file[index], order: 'head', start: start, num: this.get_line[index], }; try { var log_data = await do_post_text_with_apikey(base_url + "/tail-view-file", param, this.apikey); if (!log_data) return; this.check_top_line(index, log_data); this.$set(this.log_data, index, log_data); } catch (error) { console.error(error); alert(error); } }, log_prev: async function (index) { if (this.top_line[index] < 0) return; var start; if (this.select_order[index] == 'tail') { start = this.top_line[index] + this.get_line[index]; } else if (this.select_order[index] == 'head') { start = this.top_line[index] - this.get_line[index]; if (start < 1) start = 1; } var param = { fname: this.select_file[index], order: 'head', start: start, num: this.get_line[index], }; try { var log_data = await do_post_text_with_apikey(base_url + "/tail-view-file", param, this.apikey); if (!log_data) return; this.check_top_line(index, log_data); this.$set(this.log_data, index, log_data); } catch (error) { console.error(error); alert(error); } }, }, created: function () { }, mounted: async function () { proc_load(); this.apikey = Cookies.get('tail-apikey'); try { var result = await do_post(base_url + "/tail-list", {}); this.file_list = result.list; this.select_file[0] = this.file_list[0]; this.select_file[1] = this.file_list[0]; } catch (error) { console.error(error); alert(error); } } }; vue_add_data(vue_options, { progress_title: '' }); // for progress-dialog vue_add_global_components(components_bootstrap); vue_add_global_components(components_utils); /* add additional components */ window.vue = new Vue(vue_options); function do_post_text_with_apikey(url, body, apikey) { const headers = new Headers({ "Content-Type": "application/json; charset=utf-8", "X-API-KEY": apikey }); return fetch(url, { method: 'POST', body: JSON.stringify(body), headers: headers }) .then((response) => { if (!response.ok) throw 'status is not 200'; // return response.json(); return response.text(); // return response.blob(); // return response.arrayBuffer(); }); } function do_post_blob_with_apikey(url, body, apikey) { const headers = new Headers({ "Content-Type": "application/json; charset=utf-8", "X-API-KEY": apikey }); return fetch(url, { method: 'POST', body: JSON.stringify(body), headers: headers }) .then((response) => { if (!response.ok) throw 'status is not 200'; // return response.json(); // return response.text(); return response.blob(); // return response.arrayBuffer(); }); } 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブラウザからLinuxサーバのログを気軽に参照するWebサーバ

UbuntuなどのLinuxサーバにあるログを参照するためにわざわざSSHでログインするのが面倒なので、ブラウザから参照できるようにした。 適当につくったものなので、セキュリティも何もない。自己責任でお願いします。 画面はこんな感じ。一応行番号も付くようにしています。 ログの先頭や末尾をサクッと見れたり、前ページ・後ページに移動できたりします。 なんならファイルダウンロードもできます。 一応、APIKeyで守ってますが、適当実装なので、ローカルネットワークでのみ使てください。 ソースコードもろもろはGitHubに上げておきました。 poruruba/SimpleLogViewer ソースコード(サーバ) そのままソースコード載せておきます。 api/controllers/tail-file/index.js 'use strict'; const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/'; const Response = require(HELPER_BASE + 'response'); const BinResponse = require(HELPER_BASE + 'binresponse'); const TextResponse = require(HELPER_BASE + 'textresponse'); const APIKEY = "【お好きなAPIKey】"; const logfile_list = [ // 参照したいログファイル名の配列 ]; const { exec } = require('child_process'); const streamBuffers = require('stream-buffers'); const archiver = require('archiver'); const path = require('path'); exports.handler = async (event, context, callback) => { if( event.path == '/tail-view-file'){ if (!event.requestContext.apikeyAuth || event.requestContext.apikeyAuth.apikey != APIKEY ) throw "wrong apikey"; var body = JSON.parse(event.body); console.log(body); if( logfile_list.indexOf(body.fname) < 0 ) throw 'not allowed'; var num = Number(body.num); var start = Number(body.start); return new Promise((resolve, reject) =>{ var exec_batch; if (body.order == 'head'){ exec_batch = `cat -n ${body.fname} | head -n ${start - 1 + num} | tail -n ${num} | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" | col -bx`; } else if (body.order == 'tail'){ exec_batch = `cat -n ${body.fname} | tail -n ${start - 1 + num} | head -n ${num} | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" | col -bx`; }else{ reject('unknown order'); } exec(exec_batch, (err, stdout, stderr) => { if (err) { reject(err); return; } resolve(new TextResponse("text/plain", stdout)); }); }); }else if( event.path == '/tail-get-file'){ if (!event.requestContext.apikeyAuth || event.requestContext.apikeyAuth.apikey != APIKEY ) throw "wrong apikey"; var body = JSON.parse(event.body); console.log(body); if( logfile_list.indexOf(body.fname) < 0 ) throw 'not allowed'; return new Promise((resolve, reject) =>{ var dest_stream = new streamBuffers.WritableStreamBuffer(); const archive = archiver('zip', { zlib: { level: 9 } }); dest_stream.on('finish', () => { console.log('stream finish'); var response = new BinResponse('application/zip', dest_stream.getContents()); response.set_filename(path.basename(body.fname) + '.zip'); resolve(response); }); archive.pipe(dest_stream); archive.on('error', (err) => { reject(err); }); archive.file(body.fname, { name: path.basename(body.fname) }); archive.finalize(); }); }else if( event.path == '/tail-list' ){ return new Response({ list: logfile_list }); } }; 要は、以下のようなコマンドを実行しているだけです。 行番号付けたり、画面制御コードを省いたりしています。 cat -n ${body.fname} | tail -n ${start - 1 + num} | head -n ${num} | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" | col -bx ソースコード(クライアント) クライアント側ソースコード。 特に難しいことはしていません。Vueのおかげで。 public/log_viwer/js/start.js 'use strict'; //const vConsole = new VConsole(); //window.datgui = new dat.GUI(); const base_url = "http://【本サーバのURL】"; var vue_options = { el: "#top", mixins: [mixins_bootstrap], data: { apikey: '', file_list: [], num_of_col: 1, select_file: ["", ""], log_data: ['', ''], select_order: ["tail", "tail"], start_line: [1, 1], get_line: [30, 30], top_line: [-1, -1] }, computed: { class_row: function () { return "col-sm-" + Math.floor(12 / this.num_of_col); } }, methods: { check_top_line: function (index, log_data) { try { var i = 0; for (; ; i++) if (log_data.charAt(i) != ' ' || !log_data.charAt(i)) break; var j = i; for (; ; j++) if (log_data.charAt(j) == ' ' || !log_data.charAt(j)) break; if (i < j) this.top_line[index] = Number(log_data.substring(i, j)); else this.top_line[index] = -1; } catch (error) { console.log(error); } }, add_num: function (index, target, num) { if (target == 'start_line') { var line = this.start_line[index] + num; if (line < 1) line = 1; this.$set(this.start_line, index, line); } else if (target == 'get_line') { var line = this.get_line[index] + num; if (line < 1) line = 1; this.$set(this.get_line, index, line); } }, log_get_file: async function (index) { try { this.progress_open(); var param = { fname: this.select_file[index], }; var blob = await do_post_blob_with_apikey(base_url + "/tail-get-file", param, this.apikey); Cookies.set('tail-apikey', this.apikey, { expires: 3650 }); var url = window.URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.target = '_blank'; a.download = "download.zip"; a.click(); window.URL.revokeObjectURL(url); } catch (error) { console.error(error); alert(error); } finally { this.progress_close(); } }, log_view_file: async function (index) { var param = { fname: this.select_file[index], order: this.select_order[index], start: this.start_line[index], num: this.get_line[index], }; try { var log_data = await do_post_text_with_apikey(base_url + "/tail-view-file", param, this.apikey); if (!log_data) return; this.check_top_line(index, log_data); this.$set(this.log_data, index, log_data); Cookies.set('tail-apikey', this.apikey, { expires: 3650 }); } catch (error) { console.error(error); alert(error); } }, log_next: async function (index) { if (this.top_line[index] < 0) return; var start; if (this.select_order[index] == 'tail') { start = this.top_line[index] - this.get_line[index]; if (start < 1) start = 1; } else if (this.select_order[index] == 'head') { start = this.top_line[index] + this.get_line[index]; } var param = { fname: this.select_file[index], order: 'head', start: start, num: this.get_line[index], }; try { var log_data = await do_post_text_with_apikey(base_url + "/tail-view-file", param, this.apikey); if (!log_data) return; this.check_top_line(index, log_data); this.$set(this.log_data, index, log_data); } catch (error) { console.error(error); alert(error); } }, log_prev: async function (index) { if (this.top_line[index] < 0) return; var start; if (this.select_order[index] == 'tail') { start = this.top_line[index] + this.get_line[index]; } else if (this.select_order[index] == 'head') { start = this.top_line[index] - this.get_line[index]; if (start < 1) start = 1; } var param = { fname: this.select_file[index], order: 'head', start: start, num: this.get_line[index], }; try { var log_data = await do_post_text_with_apikey(base_url + "/tail-view-file", param, this.apikey); if (!log_data) return; this.check_top_line(index, log_data); this.$set(this.log_data, index, log_data); } catch (error) { console.error(error); alert(error); } }, }, created: function () { }, mounted: async function () { proc_load(); this.apikey = Cookies.get('tail-apikey'); try { var result = await do_post(base_url + "/tail-list", {}); this.file_list = result.list; this.select_file[0] = this.file_list[0]; this.select_file[1] = this.file_list[0]; } catch (error) { console.error(error); alert(error); } } }; vue_add_data(vue_options, { progress_title: '' }); // for progress-dialog vue_add_global_components(components_bootstrap); vue_add_global_components(components_utils); /* add additional components */ window.vue = new Vue(vue_options); function do_post_text_with_apikey(url, body, apikey) { const headers = new Headers({ "Content-Type": "application/json; charset=utf-8", "X-API-KEY": apikey }); return fetch(url, { method: 'POST', body: JSON.stringify(body), headers: headers }) .then((response) => { if (!response.ok) throw 'status is not 200'; // return response.json(); return response.text(); // return response.blob(); // return response.arrayBuffer(); }); } function do_post_blob_with_apikey(url, body, apikey) { const headers = new Headers({ "Content-Type": "application/json; charset=utf-8", "X-API-KEY": apikey }); return fetch(url, { method: 'POST', body: JSON.stringify(body), headers: headers }) .then((response) => { if (!response.ok) throw 'status is not 200'; // return response.json(); // return response.text(); return response.blob(); // return response.arrayBuffer(); }); } 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel+vue.jsでFontAwesomeを使うメモ

はじめに Laravel8+Vue3でFont Awesomeを使用する際に 少し苦戦してしまったので 忘れないようにメモしておきます 開発環境は DockerでLaravel vue.jsの環境を構築してます FontAwesomeをインストールする プロジェクトに移動して FontAwesomeをインストールします $ npm install --save @fortawesome/fontawesome-svg-core $ npm install --save @fortawesome/free-solid-svg-icons #Using Vue 3.x $ npm install --save @fortawesome/vue-fontawesome@prerelease 上記にもあるのですが vue 3.x ~はvue-fontawesomeの後ろに@prerelease(事前公開)が付くみたいです vue 2.x ~は@latest (最新)をつけるみたいです インストールし終わったら package.jsonを見に行って インストールしたものがあるかチェックしておきましょう "@fortawesome/fontawesome-svg-core": "^1.2.36" "@fortawesome/free-brands-svg-icons": "^5.15.4" "@fortawesome/vue-fontawesome": "^3.0.0-4" 実際に使用する インストールが終わったのであとは使用するだけです! 今回はこいつを使いましょう https://fontawesome.com/v5.15/icons/angle-right?style=solid よく見るやつです まず、表示したいvueファイルのscript内で <script> import { library } from "@fortawesome/fontawesome-svg-core"; import { faAngleRight } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; library.add(faAngleRight); export default { components: { FontAwesomeIcon, }, </script> 上記のようにimportとexport をしてあげます library.addでは使いたいアイコンを追加する。(使用する宣言をしてあげます) 今回の場合はfaAngleRightを使用すると宣言します。 また、アイコンを追加する際は fa-angle-righ のように ハイフンで繋げてあるケバブケースから faAngleRight のように キャメルケースにして使用してください! script 内の記述が終わったので 次はtemplateです <template> <FontAwesomeIcon icon="angle-right" /> </template> 上記のように使いたい箇所に記載すれば アイコンが使用できます! またしてもここで注意が必要なのですが icon="" の中身は angle-rightのように  ケバブケースにしてあげないと動きません! 少し面倒ですがお忘れなく!! 以上 自分のメモ用に記載しました。 間違い等ありましたら 優しくご指摘くださいませ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel blade + vue.js でユーザー入力に対応する

きっかけ Laravel blade + vue.js という環境でユーザーの入力を扱う際にいろいろ苦戦したので、備忘録として記載します。 blade 記法で値を置くと コントローラから渡したデータを blade 記法で書く際はすぐに以下の記載を行うと思います。 {{ $var }} 一般的なデータについてはこの入力で渡せるので良いと思いますが、もしこのデータ自体がユーザー入力等で{{ 何らかの入力 }}を含んでいる場合、 blade テンプレートのレンダリング vue.js のコンパイル 画面の表示 という順序の内、1 番目の blade のレンダリング後にユーザーが入力した{{ 何らかの入力 }}がページソース上に載った状態で 2 番目のレンダリングに回されます。 この際、2 番目のコンパイルで vue.js 側は真面目に{{ 何らかの入力 }}の中身を解釈しようとするので、大抵の場合はコンパイル時のエラーが出ることになります。 回避方法1 データを置く部分の親要素にv-preを付ける。 例 <div v-pre> {{ $var }} </div> 用途:ユーザーの入力をただ表示するだけの場合 (内容を確認する画面等) v-preはついている要素とその子要素のコンパイルをスキップするものであり、結果的に子要素であるユーザー入力内の{{ 何らかの入力 }}のコンパイルもスキップされ、表示できるようになります。 回避方法2 script 内でデータを渡し、vue.js の data から参照する。 <textarea v-model="message"></textarea> (中略) var app = new Vue({ el: '#app', data: { message: {{ $var }} } }) 用途:ユーザーの入力を vue.js 側でも利用する場合。 (input や textarea などの入力が絡む場合) 実際の入力部分にv-preを付けると、入力された内容に対しての vue.js の一切の処理が行えない状況になります。 入力内容に対して何らかの vue.js の処理を行う場合、blade 記法で入力部分にデータを渡すのは諦めて、vue.js の data に blade 記法で渡す必要があります。 この際、実際には、改行を含む際の対応や vue.js の data から参照する際の記法など、javascript, vue.js, html 間のお約束に沿った書き方に気を付ける必要があります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】ディレクティブについて

はじめに こんにちは。 Vue.jsのディレクティブについてアウトプットしていきます! ディレクティブとは ディレクティブとは、 DOM 要素に対して何かを実行することをライブラリに伝達する、マークアップ中の特別なトークンです。 参照:https://012-jp.vuejs.org/guide/directives.html タグに付与する属性のことで、冒頭にv-が付きます。 いくつか紹介していきます。 v-bindディレクティブ 属性へのデータバインディングのときに使用する。 HTML <div id="app"> <input type="text" v-bind:value="message"> </div> Vue.js var app = new Vue({ el: '#app', message: 'Hello!' }) v-ifディレクティブ 要素の表示や非表示を「真偽値」を使用して切り替えることができる。 HTML <div id="app"> <p v-if="toggle"> Hello! </p> </div> Vue.js var app = new Vue({ el: '#app', data: { toggle: true //trueまたはfalse } }) trueの場合は、Hello!が表示される。 falseの場合、toggleで指定したpタグはDOMごと非表示になる。 v-showディレクティブ 要素の表示や非表示を「真偽値」を使用して切り替えることができる。 v-ifディレクティブとの違いは、falseの場合CSSのdisplay:noneを適用させる。 HTML <div id="app"> <p v-show="toggle"> Hello! </p> </div> Vue.js var app = new Vue({ el: '#app', data: { toggle: true //trueまたはfalse } }) trueの場合は、Hello!が表示される。 falseの場合、toggleで指定したpタグはdisplay:noneで非表示になる。 v-forディレクティブ オブジェクトの繰り返しを行う際に使用する。 <タグ名 v-for="変数 in データの配列"> {{変数}} </タグ名>で記述する。 HTML <div id="app"> <ol> <li v-for="color in colors"> {{ color }} </li> </ol> </div> Vue.js var app = new Vue({ el: '#app', data: { colors: ['red','blue','yellow'] } }) 配列colorsの値がv-forディレクティブにより繰り返されて、全てリスト表示される。 v-onディレクティブ クリックイベントなどの処理を行いたい場合に使用する。 HTML <div id="app"> <button v-on:click="onclick"> Click! </button> </div> Vue.js var app = new Vue({ el: '#app', methods: { onclick: function(){ alert('onclick'); } } }) ボタンをクリックするとアラートが呼ばれる処理を実行する。 最後に ここまでディレクティブについてまとめました。 まだ一部のディレクティブしか紹介しきれていないので、これからもまとめていきたいと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vueでvue-pdfを使う時にしたエラーの対処

2021/9/14時点の対応 ■[SyntaxError: Unexpected token <]の対処法 // ver4.3.0時点での公式のバグらしい .\node_modules\vue-pdf\src\vuePdfNoSss.vue:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<style src="./annotationLayer.css"></style> SyntaxError: Unexpected token < ./plugins/vue-pdf.jsを作成 import Vue from 'vue' import pdf from 'vue-pdf' Vue.component('pdf', pdf) export default { // } 2.main.jsに追記 import Vue from 'vue' import App from './App.vue' import vuetify from './plugins/vuetify' import router from './route' import store from './store/store' import pdf from './plugins/vue-pdf.js' // pluginsフォルダのvue-pdf.jsを指定 Vue.config.productionTip = false // 定期的なセッション更新処理を稼働 polling.methods.refreshSession() new Vue({ router, vuetify, pdf, store, }).$mount('#app') ■[TypeError: Cannot read property 'catch' of undefined]の対処法 // このバージョンならエラーが出ない "pdfjs-dist": "2.5.207", "vue-pdf": "4.2.0"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む