20210911のvue.jsに関する記事は8件です。

フォームの値をキャッシュできるkeep-aliveを使ってみた(Vue.js / Nuxt.js)

はじめに 登録フォームと入力確認フォームで、次の画面に進んで「やっぱ戻る!」となった時でも値がキャッシュされるようにできたのでその方法をこちらに記載します。 現在作成中のサービスで動作確認を行っていますので、ビジュアル的にイマイチなところはご了承くださいm(_ _)m keep-aliveを使う フォームの値をキャッシュする時に便利な仕組みがあります。 使い方は公式ドキュメントにわかりやすい例がのっています。 今回はそれを自分のサービス内で使ってどう書いたか、というところを説明します。 動的 & 非同期コンポーネント - Vue.js まず動的コンポーネントとは? 動的なコンポーネントとは、ユーザーの操作やアプリケーションの状態によって、コンポーネントを切り替える仕組みです。 動的コンポーネントを使用すると、例えばタブ付きのインターフェースを持つアプリケーションで、タブがクリックされた時にタブページに表示されるコンポーネントを切り替えることができます。 コンポーネントを動的に切り替える 要素 [Vue.js] つまり、何らかの操作や変化が加わった際に状態を変えるコンポーネントのことだと理解しました。Vueでよくある書き方だとv-ifやisなどでしょうか。 次で実際に書いたコードを見ていきます。 keep-aliveを使ったコードの全体像 まずコードの全体像を貼り、その後keep-aliveを使った場合と使わなかった場合の違いを説明します。 こちらのフォームを構成する要素は3つ。 メインとなるregistration.vueのページと、FormListInput コンポーネント、 FormListConfirmコンポーネントです。FormListInput は入力フォーム、FormListConfirm は登録が完了しましたと告げるページです。 pages/registration.vue <template> <div> <keep-alive> <form-list-input v-if="formNumber === 0" /> <form-list-confirm v-if="formNumber === 1" /> </keep-alive> <button v-if="formNumber === 0" @click="plusNum">次へ</button> <button v-if="formNumber === 1" @click="minusNum">戻る</button> </div> </template> <script> import FormListInput from '../../components/FormListInput.vue' import FormListConfirm from '../../components/FormListConfirm.vue' export default { components: { FormListInput, FormListConfirm, }, data(){ return { formNumber: 0, } }, methods: { plusNum() { this.formNumber ++; }, minusNum() { this.formNumber --; } } } </script> components/FormListInput.vue <template> <div> <h1>チームを登録する</h1> <label for="チーム名">チーム名:</label><input type="text" v-model="name"> <label for="チーム名">競技レベル:</label><input type="text" v-model="level"> <label for="チーム名">活動場所:</label><input type="text" v-model="area"> </div> </template> <script> export default { data(){ return { name: "", level: "", area: "", } }, } </script> components/FormListConfirm.vue <template> <div> <h1>登録内容を確認する</h1> </div> </template> コードの詳細 ここでkeep-aliveを使った場合と使わなかった場合を比べます。 keep-aliveを使わなかった場合 <template> <div> <form-list-input v-if="formNumber === 0" /> <form-list-confirm v-if="formNumber === 1" /> <button v-if="formNumber === 0" @click="plusNum">次へ</button> <button v-if="formNumber === 1" @click="minusNum">戻る</button> </div> </template> ...省略 ※下記画像に表示される「フォーム番号:0」のコードは消してありますので気にしないでください。 フォームを入力する 次へボタンで画面が切り替わった ここで戻るボタンを押すと入力した値が消えている keep-aliveを使った場合 <template> <div> <keep-alive> <form-list-input v-if="formNumber === 0" /> <form-list-confirm v-if="formNumber === 1" /> </keep-alive> <button v-if="formNumber === 0" @click="plusNum">次へ</button> <button v-if="formNumber === 1" @click="minusNum">戻る</button> </div> </template> フォーム入力 確認画面へ 戻るを押しても値が保持されていることがわかる さいごに keep-aliveタグで囲むだけで入力値のキャッシュができるのはとても便利です。ただこの方法だとまだブラウザバックに対応しきれていないのでそこの対応は別途必要になります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSにデプロイ後、Vueファイルの更新が反映されない時の対処法

EC2内のvueファイルを更新しても、ブラウザに反映されない。 既にAWSにデプロイ済みのLaravelで作成したプロダクトについて、git pullで変更点をEC2に持って来た際に、ファイル内のコードは変更が反映されているのに、ブラウザで見ると反映されない事態が発生しました。 phpのファイルは問題なく変更が反映されているのに、なぜvueは反映されないのか。 ローカルで確認すると、期待通りに表示できています。 結論 app.jsの中身が更新できていませんでした。 よくよく確認するとmargeが前後した関係で、app.jsが古い状態になっていました。 レアケースかもしれませんが、一応シェアしておきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vueと格闘する(日記)

この記事は僕がVueと格闘した記録である。 特定の意味は持たせていないので、この記事からなにかを得ようだなんて思ってはいけない。 テーブルを書く 実装 index.html <head> <meta charset="UTF-8"> <script src="lib/vue.js"></script> <script defer src="tet.js"></script> <title>my 1st Vue</title> </head> <body> <div id="app"> <table border> <tr> <th v-for="h in tableHeader" v-bind:name="h.id">{{h.text}}</th> </tr> <tr v-for="d in tableData"> <td v-for="h in tableHeader" v-bind:name="h.id">{{d[h.id]}}</td> </tr> </table> </div> </body> tet.js var app = new Vue({ el: '#app', data: { tableHeader: [ { "id": "id", "text": "ID" }, { "id": "name", "text": "商品名" }, { "id": "fee", "text": "値段" } ], tableData: [ { "id": "012", "name": "たこ焼き", "fee": "150" }, { "id": "023", "name": "わたあめ", "fee": "100" }, { "id": "034", "name": "りんご飴", "fee": "120" } ] } }) output <html><head> <meta charset="UTF-8"> <script src="lib/vue.js"></script> <script defer="" src="tet.js"></script> <title>my 1st Vue</title> </head> <body> <div id="app"> <table border=""> <tbody> <tr> <th name="id">ID</th> <th name="name">商品名</th> <th name="fee">値段</th> </tr> <tr> <td name="id">012</td> <td name="name">たこ焼き</td> <td name="fee">150</td> </tr> <tr> <td name="id">023</td> <td name="name">わたあめ</td> <td name="fee">100</td> </tr> <tr> <td name="id">034</td> <td name="name">りんご飴</td> <td name="fee">120</td> </tr> </tbody> </table> </div> </body> </html> ※イメージ ID 商品名 値段 012 たこ焼き 150 023 わたあめ 100 034 りんご飴 120 説明 不要だと思うけど。 データ出力部分は、 行毎ループがv-for="d in tableData" 列毎ループがv-for="h in tableHeader" でやってる。 おミソは、tableHeaderを配列にしたので、列の入れかえが死ぬほどかんたん。 tet.js@順番入れ替え tableHeader: [ { "id": "name", "text": "商品名" }, { "id": "fee", "text": "値段" }, { "id": "id", "text": "ID" }, ], のように、配列内で順番を変えれば列位置も変えられる(だからなんだという感じはなくはない。) 単位もつけてみたいにぇ。 index.html@単位対応 <td v-for="h in tableHeader" v-bind:name="h.id">{{d[h.id]}}{{unitName[h.id]}}</td> tet.js@単位対応 unitName: { "fee": "円" } @順番入れ替えと@単位対応を行った結果※イメージ 商品名 値段 ID たこ焼き 150円 012 わたあめ 100円 023 りんご飴 120円 034 いぇい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vueでテーブルを書く

いきなり実装 index.html <head> <meta charset="UTF-8"> <script src="lib/vue.js"></script> <script defer src="tet.js"></script> <title>VueTable</title> </head> <body> <div id="app"> <table border> <tr> <th v-for="h in tableHeader" v-bind:name="h.id">{{h.text}}</th> </tr> <tr v-for="d in tableData"> <td v-for="h in tableHeader" v-bind:name="h.id">{{d[h.id]}}</td> </tr> </table> </div> </body> tet.js var app = new Vue({ el: '#app', data: { tableHeader: [ { "id": "id", "text": "ID" }, { "id": "name", "text": "商品名" }, { "id": "fee", "text": "値段" } ], tableData: [ { "id": "012", "name": "たこ焼き", "fee": "150" }, { "id": "023", "name": "わたあめ", "fee": "100" }, { "id": "034", "name": "りんご飴", "fee": "120" } ] } }) output <body> <div id="app"> <table border=""> <tbody> <tr> <th name="id">ID</th> <th name="name">商品名</th> <th name="fee">値段</th> </tr> <tr> <td name="id">012</td> <td name="name">たこ焼き</td> <td name="fee">150</td> </tr> <tr> <td name="id">023</td> <td name="name">わたあめ</td> <td name="fee">100</td> </tr> <tr> <td name="id">034</td> <td name="name">りんご飴</td> <td name="fee">120</td> </tr> </tbody> </table> </div> </body> </html> ※イメージ ID 商品名 値段 012 たこ焼き 150 023 わたあめ 100 034 りんご飴 120 説明 不要だと思うけど。 データ出力部分は、 行毎ループがv-for="d in tableData" 列毎ループがv-for="h in tableHeader" でやってる。 おミソは、tableHeaderを配列にしたので、列の入れかえが死ぬほどかんたん。 tet.js@順番入れ替え tableHeader: [ { "id": "name", "text": "商品名" }, { "id": "fee", "text": "値段" }, { "id": "id", "text": "ID" }, ], のように、配列内で順番を変えれば列位置も変えられる(だからなんだという感じはなくはない。) 単位もつけてみたいにぇ。 index.html@単位対応 <td v-for="h in tableHeader" v-bind:name="h.id">{{d[h.id]}}{{unitName[h.id]}}</td> tet.js@単位対応 unitName: { "fee": "円" } @順番入れ替えと@単位対応を行った結果※イメージ 商品名 値段 ID たこ焼き 150円 012 わたあめ 100円 023 りんご飴 120円 034 いぇい 今後に向けて テーブルの編集機能作りたい 表示機能と共存させると重くなりそうだけど、テーブル内容の編集・保存機能をつけたい editableにしたり、編集した後のtableDataのJSONを保存したりしたい。 サーバー側のを保存する機能は、サーバーサイドをがっちりしないとダメだろうから、いったん保留 属性もいじいじしたい テーブルの幅だの、alignだのだっていじいじしたい。 tableAttribとか作ってHeader.idで紐付けた配列にいろいろ持たせたやつを、JavaScriptで後からAddしてあげる感じか "tableAttrib":{"id":[{"align":"center"},{"width":"50"}],"name":[],"fee":[]} align属性はdeprecatedなのでまた別の方法かもしらん つか、thとtd指定のname指定(上記ならば)で、CSSでキメればいいのか でも、WebStormくんが「name属性使うなってVue3.0がサジェストしとるで」って言うから、それもなんか違うのかしらん そんなところです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxt jsonデータからバインディングした値で画像を表示させる

はじめに タイトルの日本語があってるのかわかりませんが、やりたいのはこういう事?です。ソースを見てわかってください。。。 assets/js/data.js export const resultsData = [ { id: "00", text: "熱中する人", img: "charmander.png" }, { id: "01", text: "達成する人", img: "caterpie.png" }, { id: "02", text: "挑戦する人", img: "charmeleon.png" }, ] ここで定義したデータに画像が入ってます。 それを <h2>{{ result.text }}</h2> <script> import { resultsData } from "~/assets/js/data.js"; computed: { result() { return resultsData.find( (result: { id: string }) => result.id == (this as any).answerKey ); }, }, </script> みたいな感じで画像を取得するにはどうしたら良いか? というお話です! バッククオートが重要 <h2>{{ result.text }}</h2> <div class="mt-3"> <img :src="require(`@/assets/images/type/${result.img}`)" class="contentImg" /> </div> <script> import { resultsData } from "~/assets/js/data.js"; computed: { result() { return resultsData.find( (result: { id: string }) => result.id == (this as any).answerKey ); }, }, </script> この部分がなんて書いたら良いか分からず、、色々と試行錯誤した結果このようになりました! <img :src="require(`@/assets/images/type/${result.img}`)" class="contentImg" /> requireを""で囲って、()内のpathの部分はバッククオートで囲うのが正解なようです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでVue.jsのチラつきをv-cloakを使わずに防止する方法

背景 Vue.jsのチラつきとは Vue.jsの「マスタッシュ表記({{ data }}のような表記)」や「v-if」などで表示を制御している場合、ページ読み込み直後に一瞬だけVueデータが反映される前のコードが表示されてしまうことがある。これを経験した人は少なくないと思う。 v-cloakでの対策と問題点 このチラつきの解決策をネットで検索すると、「v-cloakを使いましょう」という記事が出てきて、下記のようなサンプルコードを提案される。 index.html <!DOCTYPE html> <html lang="ja"> <head> <style type="text/css"> [v-cloak] { display: none; } </style> </head> <body> <div id="app" v-cloak> <p>{{ message }}</p> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { message: "メッセージ", }, }); </script> </body> </html> ただの html や php 環境ならこの方法で解決できる。しかし、Laravel の blade で Vue.js を使用している場合、この方法では解決しないことがある。 (条件や原因を特定できていないので、もし知っている人はコメントいただけるとありがたいです。) v-cloakを使わない解決方法 サンプルコード v-cloakと同様の処理を下記サンプルコードのように自作してしまえば解決できる。 index.blade.php <!DOCTYPE html> <html lang="ja"> <head> </head> <body> <div id="app" style="display:none"><!-- (1)html読み込み時はcssで非表示 --> <p>@{{ message }}</p> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { message: "メッセージ", }, mounted: function () { const targetElement = this.$el; this.$el.style.display='block'; // (2)vueマウント完了後に表示させる }, }); </script> </body> </html> 解説 まず、Vueの制御対象のコンテンツ全体を「style="display:none"」で非表示にしておく。こうすることで、Vueと連動する部分はページ読み込み直後であっても表示されない。 Vueインスタンスが生成され、エレメントのマウントが完了後(=Vueインスタンスのデータがhtmlコード側に反映された後)に、非表示を解除する。 同様の問題で困っている人の参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js リアルタイム検索

Vue.jsで検索機能を実装します 検索ボタンを押してリロード後に検索結果を表示するのではなく、ユーザーが入力すると、ボタンを押さなくても、リロード無しで直ぐに検索結果が出てくるような機能です 検索欄を作成 まずは検索欄を作成します。 v-modelを使用して入力した文字をkeywordに同期させます(keywordに入力した文字を格納するイメージ)。 vuetifyを使用しています。 <template> <div id="app> <div class="search"> <v-text-field type="text" v-model="keyword" label="検索"></v-text-field>     <!-- input type="text" v-model="keyword"> vuetify使わないならこう?--> </div> </div> </template> こんな感じになります 次に検索用に使うデータを用意します 検索用に使う変数keywordも用意します <template> <div id="app> <div class="search"> <v-text-field type="text" v-model="keyword" label="検索"></v-text-field>     <!-- input type="text" v-model="keyword"> vuetify使わないならこう?--> </div> </div> </template> <script> new Vue({ data: {     keyword: "",//検索用 fruits: [ {id: 1, name: "オレンジ"} {id: 2, name: "メロン" } {id: 3, name: "アップル"} ] } }) </script> 検索のロジックを作成 検索ボックスに文字が入力された瞬間、関連データだけ表示する実装をします。 リアルタイムでデータ検索するには、データのフィルター機能が必要です。 例えば、検索ワードが「メロン」だった場合、ひとつずつデータをチェックして「メロン」という文字列が含まれているかどうかをチェックし、もし含まれているのならそのデータを残して他はスルーしなければいけません。 これを実装するためには、Vueのcomputedを利用します。 computedはデータが変更(ここでは検索キーワードが入力)されると同時に実行される算出プロパティです。 filteredFruits: function() { var fruits = []; //検索にヒットしたデータを格納する配列を用意 for(var i in this.fruits) { //this.fruitsはdataで定義しているもの 3つのデータをforで順番に回していきます var food = this.fruits[i]; //回されてきたデータを変数foodに格納 if(food.name.indexOf(this.keyword) !== -1) { //ここでfood.name(オレンジやメロン)とkeyword(ユーザーが入力した文字)が一致するか判断 fruits.push(food); //一致するなら配列fruitsにデータを格納 } } return fruits; //fruitsを返します } これで検索条件に合ったデータだけを返せるようになりました 検索に一致したデータだけを画面上に表示させます <template> <div id="app> <div class="search"> <v-text-field type="text" v-model="keyword" label="検索"></v-text-field> </div> <tr v-for="fruits in filteredFruits" :key="fruits.id"> <td v-text="fruits.name"></td> </tr> </div> </template> 以上でVue.jsでのリアルタイム検索ができると思います! 完成コード <template> <div id="app"> <div class="search"> <v-text-field type="text" v-model="keyword" label="検索"></v-text-field> </div>    <tr v-for="fruits in filteredFruits" :key="fruits.id"> <td v-text="fruits.name"></td> </tr> </div> </template> <script> new Vue({ data: {     keyword: "" fruits: [ {id: 1, name: "オレンジ"} {id: 2, name: "メロン" } {id: 3, name: "アップル"} ] }, computed: { filteredFruits: function() { var fruits = []; for(var i in this.fruits) { var food = this.fruits[i]; if(food.name.indexOf(this.keyword) !== -1) { fruits.push(food); } } return fruits; } } }) </script>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

3点リーダーのVueコンポーネント

概要 指定行以上のテキストコンテンツを、隠す3点リーダーを作る。 コンポーネントのインナー要素が指定行高を超えた高さを持っていたら、 is-overflowクラスを付与して、overflow: hidden;、 after疑似要素で点を追加して、背景に色を付けることで、文字を隠す。 仕上げに文字の切れ目になる部分をグラデーションにしてごまかす。 記述 <template lang="pug"> .a-dotleader( :class="{ 'is-overflow': isOverflow }" :style="{ height: `${maxHeight}px` }" ) .a-dotleader-inner(ref="inner") {{ text }} </template> <script> export default { props: { text: { type: String, required: false, default: '' }, spRow: { type: Number, required: false, default: 2 }, pcRow: { type: Number, required: false, default: 2 } }, data: () => ({ isMobile: false, isOverflow: false, lineHeight: 19.5 }), computed: { maxHeight() { return this.isMobile ? this.lineHeight * this.spRow : this.lineHeight * this.pcRow } }, mounted() { this.init() window.addEventListener('resize', this.init) }, methods: { init() { const ww = window.innerWidth const breakPoint = 1024 const elInner = this.$refs.inner const innerHeight = elInner.clientHeight const style = window.getComputedStyle(elInner) this.lineHeight = parseFloat(style.getPropertyValue('line-height')) this.isMobile = ww < breakPoint this.isOverflow = this.maxHeight < innerHeight } } } </script> <style lang="stylus" scoped> .a-dotleader overflow hidden &.is-overflow position relative word-break break-all &:after display block position absolute content '…' text-align right right 0 bottom 0 width 2em background linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1), rgba(255, 255, 255, 1)) </style>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む