- 投稿日:2020-08-04T22:43:11+09:00
フォーマット[書式]指定子の使い方。(%s, %d, %iなど)
- 投稿日:2020-08-04T21:42:19+09:00
【 Vue.js】算出プロパティ(computedオプション)
【 Vue.js】算出プロパティ(computedオプション)
computedオプションによって算出したデータをテンプレートに表示できる。
算出プロパティの使い方
▼.jsの記述
computed:{算出プロパティ名: function(){return 処理}
▼.htmlの記述
マスタッシュ展開でプロパティ名を記載する。
{{ 算出プロパティ名 }}
算出プロパティのメリット
・テンプレートの記述をシンプルにできる。
・複雑な処理を複数回使用する場合に有効。算出プロパティの事例
dataプロパティのテキストを反転し、4文字目から10文字目まで表示。
▼.jsの記述
.jsvar app = new Vue({ el:"#app", data:{ greeting:"Hello World!!!" }, computed:{ revText: function(){ return this.greeting.split('').reverse().join('').substring(3,10) } } })
算出プロパティ使用・未使用の比較
▼算出プロパティなしの記述
.html<body> <div id="app"> <h2>▼マスタッシュ展開</h2> <p> {{ greeting.split('').reverse().join('').substring(3,10)}} {{ greeting.split('').reverse().join('').substring(3,10)}} {{ greeting.split('').reverse().join('').substring(3,10)}} {{ greeting.split('').reverse().join('').substring(3,10)}} </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>▼算出プロパティありの記述
.html<body> <div id="app"> <h2>▼computed(算出プロパティ)</h2> <p> {{ revText }} {{ revText }} {{ revText }} {{ revText }} </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>算出プロパティを使うことでシンプルに記述できる。
算出プロパティとメソッドの違い
違い1・・・呼び出し方法
メソッドは呼び出し時に「()」が必要なのに対し、算出プロパティは不要。(メソッドかプロパティの違い)
.jsvar app = new Vue({ el:"#app", data:{ greeting:"Hello World!!!" }, computed:{ revText1: function(){ return this.greeting.split('').reverse().join('').substring(3,10) } }, methods:{ revText2: function(){ return this.greeting.split('').reverse().join('').substring(3,10) } } }).html<body> <div id="app"> <h2>▼computed(算出プロパティ)</h2> <p> {{ revText1 }} </p> <h2>▼メソッド</h2> <p> {{ revText2() }} </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>両者に大きな違いはない。cmoputedの方が2文字少ない。
違い2・・・getterとsetter
・computed: getterとsetterの両者を定義可能。
・method: getterのみ。違い3・・・キャッシュ
computedは一度呼び出したら、再計算することなく表示できる。一方、methodは呼び出される度に計算する。
・computed: キャッシュされる
・method: キッシュされない
算出プロパティのgetterとsetterを使った処理
getter(ゲッター)とsetter(セッター)とは?
getter: 取得した値を関数に入れて返す。
setter: 関数処理した値をセットする。.jsvar app = new Vue({ el:"#app", data:{ basePrice:100 }, computed:{ taxIncludedPrice:{ get: function(){ return parseInt(this.basePrice * 1.10) }, set: function(taxIncludedPrice){ this.basePrice = Math.ceil(taxIncludedPrice/1.10) } } } }).html<body> <div id="app"> <p> 税抜き:<input type="text" v-model="basePrice"> </p> <p> 税込み:<input type="text" v-model="taxIncludedPrice"> </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>perseInt(数値)
整数を返す。
Math.ceil(数値)
切り上げた数値を返す。
算出プロパティのキャッシュ動作確認
ランダムな数値を表示するプログラムで確認。
・Math.random()
・console.log('テキスト')
┗ 処理が実行される毎にconsole.logでテキストを表示.jsvar app = new Vue({ el:"#app", data:{ basePrice:100 }, computed:{ computedNum: function(){ console.log('computed!') return Math.random() } }, methods:{ methodNum: function(){ console.log('methods!') return Math.random() } } }).html<body> <div id="app"> <p> Computed </p> <ol> <li>{{ computedNum }}</li> <li>{{ computedNum }}</li> <li>{{ computedNum }}</li> </ol> <p> Method </p> <ol> <li>{{ methodNum() }}</li> <li>{{ methodNum() }}</li> <li>{{ methodNum() }}</li> </ol> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>
computedプロパティは同じ値。メソッドの場合はすべて個別になっている。
- 投稿日:2020-08-04T19:35:26+09:00
【Vue.js】フィルタによる書式設定
【Vue.js】フィルタによる書式設定
filtersオプションで書式の設定ができる。
(1)Mustache展開と(2)v-bindディレクティブの2種類に対して使用できる。・Vue.js公式ページ
https://jp.vuejs.org/v2/guide/filters.html目次
ローカルフィルタとグローバルフィルタ
ローカルフィルタ
特定のインスタンス内で定義するフィルタ。
filtersオプション
で記述。▼jsファイルの記述
filters:{フィルタ名: function(value){return 処理}}.jsvar app = new Vue({ el:"#app", data: { price: 2240000000000 }, filters:{ numberFormat: function(num){ return num.toLocaleString() } } })グローバルフィルタ
グローバルで呼び出せるフィルタ。特定のインスタンスに依らない。
filterメソッド
で記述▼jsファイルの記述
Vue.filter('フィルタ名', function(value){return 処理}}.jsVue.filter('numberFormat', function(num){ return num.toLocaleString() }) var app = new Vue({ el:"#app", data: { price: 2240000000000 } })▼htmlファイルの記述
ローカルフィルタもグローバルフィルタも適用方法は同じ。
(1)Mustache展開
{{式| フィルタ名}}
(2)v-bind
<要素 v-bind:属性="プロパティ名 | フィルタ名"
1000桁区切り
数値.toLocaleStringメソッドを使う。
▼.jsの記述
function(value){return value.toLocaleString()}
.jsvar app = new Vue({ el:"#app", data: { price: 2240000000000 }, filters:{ numberFormat: function(num){ return num.toLocaleString() } } }).html<body> <div id="app"> <h2>▼Mustache展開</h2> <p>{{ price | numberFormat}}</p> <br> <h2>▼v-bindディレクティブ</h2> <input type="text" v-bind:value="price | numberFormat"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>
¥マークをつける
toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))
.jsvar app = new Vue({ el:"#app", data: { price: 22400 }, filters:{ numberFormat: function(num){ return num.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }) } } })?マークをつける
toLocaleString('ja-JP', { style: 'currency', currency: 'USD' }))
.jsvar app = new Vue({ el:"#app", data: { price: 22400 }, filters:{ numberFormat: function(num){ return num.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }) } } })小数点
toFixedメソッドを使う。
┗ .toFixed(int)
┗ int:表示する桁数
filters:{decimalFormat: function(num){return num.toFixed(int)}}
.jsvar app = new Vue({ el:"#app", data: { price: 224.1234 }, filters:{ decimalFormat: function(num){ return num.toFixed(2) } } }).html<body> <div id="app"> <h2>▼Mustache展開</h2> <p>{{ price | decimalFormat}}</p> <br> <h2>▼v-bindディレクティブ</h2> <input type="text" v-bind:value="price | decimalFormat"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>フィルターの連結
一つの要素に対し、複数のフィルターを連結することができる。
{{ dataオブジェクト | フィルタ名 | フィルタ名 | フィルタ名 |フィルタ名...}}
▼日本円を①USDに変換し②3桁区切りし③ドルマークをつける
①フィルタ名:toUSD
・グローバルフィルタで定義
・100で割る②フィルタ名:numberFormat
・ローカルフィルタで定義③フィルタ名: dollar
・引数で$を渡し、冒頭に表示する。.jsVue.filter('toUSD', function(jpPrice){ return jpPrice/100 }) var app = new Vue({ el:"#app", data: { jpPrice: 2456000 }, filters:{ numberFormat: function(num){ return num.toLocaleString() }, dollar: function(num, prefix){ return prefix + num } } }).html<body> <div id="app"> <h2>日本円</h2> <p> {{jpPrice | numberFormat}} </p> <h2>▼Mustache展開</h2> <p>{{ jpPrice | toUSD | numberFormat | dollar('$')}}</p> <br> <h2>▼v-bindディレクティブ</h2> <input type="text" v-bind:value="jpPrice | toUSD | numberFormat | | dollar('$') "> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>引数を活用したフィルタ
引数を使うことで、書式条件の変更ができる。
{{ dataプロパティ名 : フィルタ名(引数1, 引数2,,,)}}
▼指定文字数のみ表示し、末尾に「...」をつける
・readmore機能
.jsVue.filter('readmore', function(text, length, suffix){ return text.substring(0, length) + suffix }) var app = new Vue({ el:"#app", data: { text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' } }).html<body> <div id="app"> {{ text | readmore(20, '...') }} </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>substringメソッド
指定した文字数だけ抜き出す。
文字列.subtsring(int1, int2)
┗ int1: 開始の文字数
┗ int2: 終了の文字数(省略可)
- 投稿日:2020-08-04T17:58:01+09:00
【Vue.js】JavaScript式。Mustache構文内で式が使える。
【Vue.js】JavaScript式。Mustache構文内で式が使える
マスタッシュ構文{{ プロパティ名 }}では、dataオブジェクトの値を表示するだけでなく計算もできる。これの式をJavaScript式と呼ぶ。
目次
1. 四則演算
2. メソッドによる処理
3. 真偽値の値で表示内容を分岐
4. エラー事例
四則演算
.jsvar app = new Vue({ el:"#app", data: { number1: 10, number2: 3 } }).html<body> <div id="app"> <p>{{number1+10*10}}</p> <p>{{number1-number2}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>メソッドによる処理
Vue.jsではJavaScriptのメソッド、split()などは、「要素.split」という形で使用できる。
このメソッドはマスタッシュ構文の中でも使える。
▼文字列を① 1文字づつ分割し、② 反転させ、③ 再結合するjavascript式
.split('').reverse().join('')}
.jsvar app = new Vue({ el:"#app", data: { string:'こんにちは' } }).html<body> <div id="app"> <p>{{string.split('').reverse().join('')}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>真偽値の値で表示内容を分岐
プロパティの真偽値に合わせ表示内容を変更する式が、マスタッシュ構文で表現できる。
プロパティ名:真偽値
{{プロパティ名 ? 'trueの場合の表示内容' : 'falseの場合の表示内容'}}
.jsvar app = new Vue({ el:"#app", data: { ok: true } }).html<body> <div id="app"> <p>{{ok ? 'trueです' : 'falseです'}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>エラー事例
式以外はエラーになる。
▼エラーとなる例
1. 文
{{ var x = 1 }}
- フロー制御 {{ if(ok){return string} }}
- 投稿日:2020-08-04T17:38:40+09:00
正式リリース前に総予習!! Vue3の変更点まとめ
8月上旬に正式リリース予定とされているVue3の変更点をいち早く理解できるように概要をまとめてみました。それぞれの項目ごとにvuejs/rfc又はVue3 Docmentへのリンクを貼っているので索引的に使ってもらえると嬉しいです。
この記事は以下バージョン時点の情報です。
Composition APIの追加
おそらく一番大きな目玉となる変更はこちら。Composition APIという新しいAPIが追加されます(PluginでVue2系でも使用可能です)。
Composition APIはコンポーネントのロジックの柔軟な再構成を可能にする関数ベースのAPI群です。
なお、Vue2系のOptional APIのサポートも継続されるので、Vue2系からのVue3へのバージョンアップ時にComposition APIに書き換える必要はありません。<!-- Vue3 Composition API --> <template> <form> <input type="text" v-model="formState.name" /> <input type="text" v-model="formState.value" /> <p>{{ contentLength }}</p> <button @click="submit" type="submit">submit</button> </form> </template> <script lang="ts"> import { defineComponent, computed, ref, onMounted, reactive } from "vue"; export default defineComponent({ props: { maxContentLength: { type: String, required: true } }, setup(props, context) { // reactive data const formState = reactive({ name: '', content: '' }) // computed const contentLength = computed(() => `${formState.content.length} / ${props.maxContentLength}`) // emit const submit = () => context.emit('submit', formState) // lifecycle hook onMounted(() => { // .... }) return { formState, contentLength, submit }; } }); </script>Composition APIについてはこちらの記事でより詳細にまとめています。
先取りVue 3.x !! Composition API を試してみる - Qiita
Vue Composition APIで使えるリアクティブ関連のAPI一覧 - QiitaTeleportの追加
Teleportは定義したコンポーネントが属するDOMツリーとは別の場所に、まるでテレポートしたかのようにコンポーネントを移動できる機能です。Vue2系でもサードパーティのプラグインLinusBorg/portal-vueで実現されていました。
以下のようにモーダル表示をハンドルするコンポーネントで
<teleport>
を使うと、to
で指定したDOM要素に内部のコンポーネントを移動できます。<template> <div class="container"> <button @click="toggleModal">toggle modal</button> <teleport to="#teleport-target"> <MyModal v-if="isVisible"/> </teleport> </div> </template> <script lang="ts"> import { defineComponent, ref } from "vue"; export default defineComponent({ setup() { const isVisible = ref(false); const toggleModal = () => { isVisible.value = !isVisible.value; }; return { isVisible, toggleModal }; } }); </script>
to
で指定できるDOM要素は自身のVueインスタンスをマウントしたDOM要素以外も指定できます。<html lang="ja"> <body> <div id="app"></div> <!-- VueがマウントされるDOM --> <div id="teleport-target"></div> <!-- teleportで指定されているDOM。ここにMyModalが表示される--> <script src="/dist/main.js"></script> </body> </html>
teleport
を利用すると、いままでCSSのz-index
で調整していたDOMの重なり順制御を、宣言的に制御できるようになりz-index
の指定に悩まされることはなくなります。
Vue3を入れたらすぐに使いたいと思える実用的な機能ですね。こちらの記事でも詳細をまとめています。
Vue.js 3.0 の新機能を試す。 〜 Teleport 編〜 - QiitaFragmentsの追加
FragmentsはVue2系では実現できなかったmulti-root nodeのコンポーネントを可能にするものです。
Vue2系ではコンポーネントのroot要素は必ず1つという制約がありました。<template> <div> <header>...</header> <main>...</main> <footer>...</footer> </div> </template>Vue3ではFragmentsのおかげでその制約がなくなり、root要素に複数の要素を記載できます。冗長なdivでのラップなどが不要になります。簡潔で良いですね。
<template> <header>...</header> <main>...</main> <footer>...</footer> </template>ただ、注意点とし子てコンポーネントに直接Class指定をしていると、今まで自動的にroot要素にClassを当てられたのですが、それがfragmentsの場合は明示的な指定が必要になるというのがあります。
Suspenseの追加(実験的)
Suspenseは非同期処理が解決されるまでフォールバックコンテンツ(例えばLoading中アイコン)を表示してくれる特別なコンポーネントです。いままで、
v-if="loading === true"
などの状態変数を使って制御していたものを、状態変数を使わずに簡潔に書くことができます。Suspenseはまだ実験的な機能で、Vue3.0の段階では仕様が確定しておらず今後変更が入ることも考えられます。Vue 3.1での正式リリースを見越しているとのことです。
<template> <Suspense> <template #default> <AsyncComponents/> <!-- 非同期処理を実行するコンポーネント --> </template> <template #fallback> loading... </template> </Suspense> </template>Suspenseの詳細はこちらにまとめています。
Vue.js 3.0 の新機能を試す。 〜 Suspense 編〜 - Qiitav-modelの仕様変更
v-modelの機能が拡張され、ひとつの要素に複数のv-modelの設定が可能になります。
Vue2系のv-bind.syncで実現していたようなことがv-modelで実現できるようになるイメージですね。この機能によってv-bind.syncは代替されるので利用できなくなります。以下v-modelの複数バインドの例です。
v-model:xxxx
のxxxのところで明示的にバインドするプロパティを指定しています。<!-- 親コンポーネント --> <template> <UserForm v-model:name="name" v-model:message="message" /> </template><!-- UserFormコンポーネント --> <template> <form> <label>name</label> <input type="text" @input="$emit('update:name', $event.target.value)" > <label>message</label> <input type="text" @input="$emit('update:message', $event.target.value)" > </form> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ props: { name: { type: String, default: '' }, age: { type: String, default: '' } }, setup() { return {} } }) </script>また、modifiersの機能が拡張され、
.lazy
,.number
,trim
のデフォルトのmodifiers以外に独自に,modifiersを定義できるようになりました。
以下はcapitalizeというmodifiersを設定している例です。v-model:name.capitalize=
とすることで入力値にcapitalizeを実行しています。<!-- 親コンポーネント --> <template> <form> <MyName v-model:name.capitalize="form.name"/> <!-- ... --> </form> </template><!-- MyNameコンポーネント --> <template> <input :value="name" @input="updateName" type="text" name="name" /> </template> <script> import { defineComponent } from "vue"; export default defineComponent({ props: { name: { type: String, default: '' }, nameModifiers: { default: () => ({}) } }, setup (props, { emit }) { const updateName = event => { let val = event.target.value if (props.nameModifiers.capitalize) { val = val.charAt(0).toUpperCase() + val.slice(1) } emit('update:name', val) } return { updateName } } } </script>scoped CSSの仕様変更
scoped CSSで使える擬似クラスの仕様変更・機能追加が行われます。
まず1つ目が::v-deep()
でこれは、今まで/deep/
として設定していた、子コンポーネントにスタイルを適用するための擬似クラスです。
/deep/
の記法がDEPRECATEDとなり、新たに::v-deep()
が追加されています。::v-deep(.foo) {}/* コンパイル後 */ [v-data-xxxxxxx] .foo {}2つ目が、
::v-slotted()
で、これはslotで受け取った親コンポーネントの要素にスタイルを適用するためのものです。Vue3からデフォルトではslotで受け取った要素は、子コンポーネントのスタイルが適用されなくなるため、こちらが追加されました。::v-slotted(.foo) {}/* コンパイル後 */ .foo[v-data-xxxxxxx-s] {}最後が、
::v-global()
で、これはscoped CSSの中でグローバルなスタイルの定義を可能とするものです。この擬似要素を設定したクラスには[v-data-xxxx]
が付与されないため、Scopedではなくグローバルに適応されます。::v-global(.foo) {}.foo {}$attrsの仕様変更
$attrs
の機能が拡張され、今まで$listeners
で参照していたネイティブイベントや別管理であったclass、styleも全て包括して$attrs
から取得できるようになりました。<MyButton @click="handleClick" @custom="handleCustom" v-model="value" type="button" class="btn" />// MyButton.vue $attrs: { class: 'btn' type: 'button', onClick: handleClick, onCustom: handleCustom, 'onUpdate:modelValue': () => { value = payload }, }そのため、
$listeners
はDEPRECATEDとなります。(実行時に警告がでます)
$listeners
を使って透過的なラッパーコンポーネントを作っていた場合は、$listeners
を削除し$attrs
への書き換えが必要です。<!-- Vue2系 --> <input v-bind="$attrs" v-on="$liseners" /><!-- Vue3 --> <input v-bind="$attrs" />Global APIの仕様変更
Vueの初期化処理が変わります。
createApp
でインスタンスを生成し、そのインスタンススコープでuse
やmixin
などが適応されるようになります。
これによってテストケースでのグローバル設定の汚染を防いだり、同一ファイル内で別設定のVueインスタンスの初期化が容易になります。import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // インスタンスを生成 app.config.isCustomElement = tag => tag.startsWith('app-') app.use(/* ... */) // インスタンススコープで設定される app.mixin(/* ... */) app.component(/* ... */) app.directive(/* ... */) app.config.globalProperties.customProperty = () => {} app.mount(App, '#app')filterの廃止
filterは、パイプ演算子
|
を使って関数適応をlinuxの標準入出力のパイプラインするものですがJavaScriptにはない独自構文で学習コストが増加する、構文解析を複雑にするという理由で削除されます。filterの処理は通常の関数適応で代替できます。
<!-- filter形式 --> <p>{{ msg | uppercase | reverse }}</p> <!-- 通常の関数適応形式 --> <p>{{ reverse(uppercase(msg)) }}</p>他の代替方法についてはrfcs/0015-remove-filters.md#alternativesをご覧ください。
Event Emitter系のAPIの廃止
Event Emitter系のAPI(
$on
,$off
,$once
)が削除されます。
グローバルなイベント管理としてEvent Emitterを仕様している場合は書き換えが必要です。
Event管理の代替にはMittなどの別のEvent Emitterライブラリの利用が推奨されています。Functional Componentの廃止
Functional Componentはdata等の状態を持たない代わりにレンダリングパフォーマンスの大幅な改善が行えるコンポーネントです。
Vue3ではFunctional Componentを作る際に使用するfunctional: true
のオプションや、<template functional>
が削除されます。Vue3では、通常のコンポーネントとFunctional Componentの性能差は大幅に縮小され、ほとんどのユースケースでは取るに足らないものとなったそうです。
SFC上でfunctionalを使用している場合は、functionalの属性を削除し、attrs、listnersの参照方法の修正が必要です。
<!-- Vue2 functional component --> <template functional> <component :is="`h${props.level}`" v-bind="attrs" v-on="listeners" /> </template> <script> export default { props: ['level'] } </script><!-- Vue3 --> <template> <!-- functionalを削除 --> <component v-bind:is="`h${props.level}`" v-bind="$attrs" <!-- attrs及びlistnersは$attrsにまとめられる --> /> </template> <script> export default { props: ['level'] } </script>終わりに
以上「正式リース前に総予習!! Vue3の変更点まとめ」でした。
色々ワクワクするような新機能が追加されていてVue3のリリースが待ち通しいですね。
他にも諸々細かい点が変わってるのでより詳細な変更はvuejs/rfcをご確認ください。参考
- 投稿日:2020-08-04T17:28:29+09:00
【Vue.js】主要ディレクティブ一覧と実例
【Vue.js】主要ディレクティブ一覧と実例
タグに付与する属性。冒頭にv-がつく。
ディレクティブを設定することで機能を追加できる。・Vue.js公式ページ
https://jp.vuejs.org/v2/api/#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96
https://012-jp.vuejs.org/api/directives.html主要なディレクティブ一覧
ディレクティブ 内容 v-bind 単方向バインディング。dataオブジェクトの値を反映する。 v-if 真偽値がfalseの場合要素を非表示にする。v-showと違いDOM毎非表示にするため重い。 v-else v-ifの真偽値がfalseの場合に表示する。任意。 v-show 真偽値がfalseの場合、display:noneにする。 v-for 配列や複数のプロパティを一つづつ抜き出す v-model 双方向バインディング。dataオブジェクトの値を反映および、タグへの入力値をdataオブジェクトに反映。 v-on イベントリスナの割り当て。 v-once 初回のみテンプレートやコンポーネントを描画。以降は静的コンテンツとして扱う。 v-pre 指定要素とすべての子要素のコンパイルをスキップ。 v-html dataオブジェクトのhtmlタグをタグとして認識する。 v-cloak ViewModel のコンパイルが終了するまで効果を持続。外部サイトのデータ読み込み中の処理など。 v-text dataオプションの読み込み方法。マスタッシュ構文の代わり。 v-class 真偽値がtrueの時、指定したクラス属性を付与。 v-style 要素にインライン CSS スタイルを適用。 実例
1. v-bind
2. v-ifとv-else
3. v-show
4. v-for
5. v-model
6. v-on
7. v-once
8. v-pre
9. v-html
10. v-cloak
11. v-text
12. v-bindの省略記法v-bind
nameなどの属性でデータバインディングを行う。
v-bind属性名="プロパティ名"▼inputタグで使用する例
<input type="text" v-bind:value="message">
.html<body> <div id ="app"> <input type="text" v-bind:value="message"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>※値にマスタッシュ構文は使えない※
×:<input type="text" value="{{message}}">
×:<input type="text" value="message">
v-bindの応用
v-bind:class{クラス名:真偽値}
┗ trueの時のみ指定したclass属性を付与.html<body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <li v-for="task in tasks"> <input type="checkbox" v-model="task.isActive"> <!-- ▼追加 --> <span v-bind:class="{active:task.isActive}">{{task.item}}</span> </li> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.css#app li{ list-style: none; } #app li > span.active{ text-decoration: line-through; }
<span v-bind:class="{active:task.isActive}">{{task.item}}</span>
・spanタグにclass=activeをバインド。
・isActiveの値がtrueなら属性を付与。falseなら付与しない。v-ifとv-else
要素をDOMごと表示/削除を切り替える。
※頻繁に表示を切り替える時は、v-showディレクティブを使う。
− true:表示
− false:非表示
▼htmlタグの記述
< v-if="プロパティ名"></>▼vue.jsの記述
data:{プロパティ名:真偽値}.jsvar app = new Vue({ el: '#app', data: { isActive:false } }).html<body> <div id ="app"> <p v-if="isActive"> isActiveの真偽値はtrueです。 </p> <p v-else> isActiveの真偽値はfalseです。 </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>v-show
要素の表示・非表示を切り替える。
┗ cssのdisplayプロパティと同じ
┗ v-ifより軽い(DOM← →要素)▼htmlタグの記述
< v-show="プロパティ名"></>▼vue.jsの記述
data:{プロパティ名:真偽値}.jsvar app = new Vue({ el: '#app', data: { aaa:false } }).html<body> <div id ="app"> <p v-show="aaa"> hello </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>v-for
配列オブジェクトの繰り返し表示。
・マスタッシュ構文を使う。
・配列と、複数の値をもつプロパティのどちらでも使用可
・キーを抜き出すことも可能
<要素名 v-for="変数 in 配列オブジェクト名">{{変数}}</要素名>
①値の繰り返し
配列の場合
.jsvar app = new Vue({ el: '#app', data: { colors:['red','blue','yellow'] } }).html<body> <div id ="app"> <ol> <li v-for="color in colors">{{color}}</li> </ol> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>複数のプロパティの場合
.jsvar app = new Vue({ el: '#app', data: { user: { lastName: 'Todoroki', firstName: 'Takashi', prefecture: 'Tokyo', age:'34' } }).html<body> <div id ="app"> <ul> <li v-for=" value in user">{{value}}</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>②キーとプロパティの繰り返し
オブジェクトの「キー:プロパティ」の両方を抜き出す。
※第1引数がvalue, 第2引数がkey<要素名 v-for="(値の変数,キーの変数) in 配列オブジェクト名">{{変数}}</要素名>`
.jsvar app = new Vue({ el: '#app', data: { user: { lastName: 'Todoroki', firstName: 'Takashi', prefecture: 'Tokyo', age:'34' } }).html<body> <div id ="app"> <ul> <li v-for=" (value, key) in user">{{key}}: {{value}}</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>v-model
双方向データバインディング
▼単方向と双方向の違い
・単方向データバインディング
┗ マスタッシュ構文で、テンプレートにdataオブジェクトのプロパティを反映する。(v-bind)・双方向データバインディング
┗ jsのdata側とテンプレート側の両方で変更可能。
┗ テンプレートの値を変更すると、dataオブジェクトのプロパティも変更される。★双方向データバインディングを簡単に実装できるのは、vue.jsの利点。
v-model="プロパティ名"
┗ タグ要素とvue.jsのプロパティが結びつく.jsvar app = new Vue({ data: { el: '#app', data: { message: '双方向バインディング' } }).html<body> <span>セルのテキスト変更で、dataプロパティの値も変更</span> <div id ="app"> <p> <input type="text" v-model="message"> </p> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>dataプロパティの中身をテンプレートに表示する
<pre>{{$data}}</pre>
・「\$el」や「\$methods」は表示できない。
v-on
イベントリスナの割り当て。
▼htmlの設定
・書き方は2種類
①<要素 v-on:イベントリスナ= "イベントプロパティ名">
②<要素 v-on="イベントリスナ: イベントプロパティ名">・v-on:click = " "
・v-on="click: "・v-on:keyup = " "
・v-on="keyup: "
など▼jsの設定
・methodsオプションを使用。
methods:{イベントプロパティ名:function(){処理}
onclickで文字を反転するプログラム
.html<body> <div id="app"> <p> {{message}} </p> <button v-on:click="clickHandler">クリック</button> </button> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.jsvar app = new Vue({ el:"#app", data: { message: 'Hello World' }, methods:{ clickHandler:function(){ this.message = this.message.split('').reverse().join('') } } })
▼メソッド
・str.split('指定文字')
┗ 指定文字で分割。配列化する。
┗ 空白の場合は1文字づつ分割。・
array.join('指定文字')
┗ 配列を指定文字で結合。
┗ 空白の場合は1文字づつ結合・
array.reverse
┗ 配列の要素を反転v-once
初回のみテンプレートやコンポーネントを描画。以降は静的コンテンツとして扱う。
・ページロード時にテンプレートに評価し静的化。
▼上記、v-on:clickを反映しなくする。
.html<body> <div id="app"> <p v-once> {{message}} </p> <button v-on:click="clickHandler">クリック</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>v-pre
指定要素とすべての子要素のコンパイルをスキップ。
用途
ディレクティブのない大量のノードをスキップすることで、コンパイルのスピードを上げる。
マスタッシュ構文をそのまま表示する
XSS(クロスサイトスクリプティング)対策
▼v-preの実行例
.jsvar app = new Vue({ el:"#app", data: { message: 'Hello World' } }).html<body> <div id="app"> <p v-pre> {{message}} </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>v-html
dataオブジェクトのhtmlを、html要素として反映する。
<要素 v-html="プロパティ名">
※セキュリティ対策として、デフォルトはhtmlタグはテキストとして表示される。
.jsvar app = new Vue({ el:"#app", data: { message: 'Hello <span style="color:blue;">World</span>' } }).html<body> <div id="app"> <p> ▼通常の表示<br> {{message}} </p> <p> ▼v-htmlを使用<br> <span v-html="message"></span> </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>※v-htmlの注意点
・XSS脆弱性の危険あり
・信用できるテンプレやデータのみに使用
・ユーザーが入力するコンテンツには使用禁止v-cloak
ViewModel のコンパイルが終了するまで効果を持続させる。
用途
・ページを表示開始してから、インスタンスの作成が終わるまでの間にコンパイル前のコードが表示されるのを防ぐ。
・Loading... を表示する
チラつき防止
チラつき(初期の一時的なコード表示)を防止したい要素にv-cloakを設置。
v-cloak
CSSで非表示設定
[v-cloak]{dispaly:none}
.html<body> <div id="app"> <section v-cloak> <p> {{message}} </p> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.css[v-cloak]{ display: none; }v-text
dataプロパティの呼び出しをv-textで行う。マスタッシュ構文を使わないパターン。
<要素 v-text="dataプロパティ">
.jsvar app = new Vue({ el:"#app", data: { message: 'Hello World' } }).html<body> <div id="app"> <p> ▼マスタッシュ構文で呼び出し<br> {{message}} </p> <p> ▼v-textで呼び出し<br> <span v-text="message"></span> </p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>▼実際の利用時
・コードの可読性を上げるため、マスタッシュ構文がv-textのどちらかに統一する。マスタッシュ構文で統一するのが一般的。
v-bindの省略記法
v-bindは頻繁に使うため、省略した表記が可能。「v-bind」をごっそり削除できる。
▼完全な表記
<要素 v-bind:属性='プロパティ名'>▼省略表記
<要素 :属性='プロパティ名'>.jsvar app = new Vue({ el:"#app", data:{ url: 'https://jp.vuejs.org/' } }).html<body> <div id="app"> <a v-bind:href="url">通常の表記</a> <br> <a :href="url">省略表記</a> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>
- 投稿日:2020-08-04T17:02:15+09:00
【Nuxt.js】Nuxt文法編:computed
? この記事はWP専用です
https://wp.me/pc9NHC-wY前置き
今回はcomputed?
getter関数とsetter関数が使える
算出プロパティです!簡単な使い方や
methodsとの違いを解説しています?♀️computed
簡単な使い方
テキストを反転させます?
【index.vue】
プロパティなので呼び出す際は
{{ reversedMessage() }}
ではなく
{{ reversedMessage }}
でOKです?index.vue<template> <div class="page"> <p>message: {{ message }}</p> <p>reversed message: {{ reversedMessage }}</p> </div> </template> <script> export default { data () { return { message: 'Hello Nuxt.js!', } }, computed: { reversedMessage () { return this.message.split('').reverse().join('') }, }, } </script>methodsを使った場合のコード
呼び出す物が関数になるので
{{ reversedMessage() }}index.vue<template> <div class="page"> <p>message: {{ message }}</p> <p>reversed message: {{ reversedMessage() }}</p> </div> </template> <script> export default { data () { return { message: 'Hello Nuxt.js!', } }, methods: { reversedMessage () { return this.message.split('').reverse().join('') }, }, } </script>thisコンテキストを使う
thisコンテキストが使えます。
this.messageを平仮名にしてみます。index.vue<template> <div class="page"> <p>message: {{ message }}</p> <p>reversed message: {{ reversedMessage }}</p> </div> </template> <script> export default { data () { return { message: 'Hello Nuxt.js!', } }, computed: { reversedMessage () { let message = this.message = 'あいうえお' return message.split('').reverse().join('') }, }, } </script>methodsとの違い
computedはプロパティ
methodsはメソッドなので
そもそも土台が違うのですが
似ていますよね?? 続きはWPでご覧ください?
https://wp.me/pc9NHC-wY
- 投稿日:2020-08-04T15:00:58+09:00
【Vue.js】無料のAPIを使ったビットコイン価格表示アプリの作成
【Vue.js】ビットコイン価格表示アプリの作成
・価格はcoindeskのAPIのデータを使用。
・データ取得はaxiosを使用。作成手順
0.使用するAPIの確認
1. bpiの価格を格納するプロパティを作成
2. axiosのCDNを読み込みとデータ取得
3. エラーcatch構文の設定
4. 画面上に価格を表示
5. 小数点以下の調整(filterオプション)
6. チラつき防止(v-cloak)
7. エラー時の表示分岐
8. ローディング表示
9. 完成版0. 使用するAPIの確認
coindeskのビットコイン価格を使用。公式ページからAPIのURLをコピー。
▼ビットコインの現在価格API
・APIエンドポイント:
https://api.coindesk.com/v1/bpi/currentprice.json・API:Application Programming Interface
┗ 第三者アプリのデータ取得
・endpoint: 固有で変更することのないURL
・BPI:Bitcoin Price Index(ビットコイン価格指数)
▼使用するデータ
bpiプロパティのUSDプロパティのrateを使用。1. bpiの価格を格納するプロパティを作成
.html<body> <div id="app"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.jsvar app = new Vue({ el: '#app', data:{ bpi: null } })初期値はnullとする。
2. axiosのCDNを読み込み
axiosとは?
指定したWEBサイトからデータを取ってくるJSライブラリ。
┗ HTTP(WEB)クライアントと呼ぶ。axiosの使い方
1. axiosのCDNを.htmlに貼り付け
▼最新バージョンを使用する場合
githubから、jsDeliverのCDNをコピー。
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
▼バージョンを固定する場合
jsDeliverの公式ページから直接CDNを取得。
「dist/axion.min.js」を使う。
https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js
2. mountedプロパティを使ってJSファイルでデータ取得したいURLを指定
mounted:function(){}
┗ mountedプロパティ
axios.get('url').then(function(response)){処理}.bind(this)
┗ mountedプロパティの中でaxiosを使う
┗ 引数responseに取得データが格納される ※引数は任意(resなどでも可)
┗ データ使用は、引数名.data (response.data)
┗ .bind(this)でインスタンスと紐付ける``
※.bind(this)でインスタンスと紐付けないとdataと紐づかない。
.jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi; }.bind(this)) } })改行できる。.thisや.bindで改行すると見やすくなる。
▼console.logで確認する方法
console.logで出力すると、chromeのdeveloperツールでデータ取得できているか確認できる。・bpiデータ:console.log(response.data.bpi)
・USDの価格:console.log(response.data.bpi.USD.rate_float).jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json').then(function(response){ console.log(response.data.bpi); console.log(response.data.bpi.USD.rate_float); this.bpi = response.data.bpi; }.bind(this)) } })3. エラーcatch構文の設定
.catch(function(error){処理}
┗ 引数は任意。errなどでも可.jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) }) } })4. 画面上に価格を表示
・v-forで複数のプロパティデータを個々に取得し、マスタッシュ構文で表示。
v-for="(値の変数, プロパティ名の変数) in プロパティ"
.html<body> <div id="app"> <h2>ビットコイン価格</h2> <ul> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>5. 小数点以下の調整(filterオプション)
▼JSファイル
・フィルタ名(value){return value.書式}
・.toFixed(桁数)
:数の小数点表記。▼HTMLファイル
・{{値 | フィルタ名}}
.html<body> <div id="app"> <h2>ビットコイン価格</h2> <ul> <li v-for="(rate, currency) in bpi"> <!-- 追記 --> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>.jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) }) }, //追記 filters:{ currencyDecimal(value){ return value.toFixed(2) } } })6. チラつき防止(v-cloak)
画面ロード時に一瞬コードが表示される。(チラつきと呼ぶ)
v-cloakディレクティブを使用
・タグの属性に
v-cloak
を追加
・cssファイルに[v-cloak]{処理}
を記述.html<body> <div id="app"> <h2>ビットコイン価格</h2> <!-- 追記 --> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>.css[v-cloak]{ display: none; }7. エラー時の表示分岐
通信エラー発生時にエラー用テキストを表示。エラーがない場合は正常に表示。
・
v-if="真偽値"
とv-else
を使う
┗ true:要素を表示
┗ false:v-elseがある要素を表示・dataオプションにhasErrorプロパティを設置(名称は任意)
┗ 初期値をfalseにし、正常表示のタグにv-elseを設置・catch構文でエラー発生時に、hasErrorをtrueにする
┗ dataオプションと紐づけるため、.bind(this)
をつける。.jsvar app = new Vue({ el: '#app', data:{ bpi: null, //追加 hasError: false }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) //追加 this.hasError = true }.bind(this)) }, filters:{ currencyDecimal(value){ return value.toFixed(2) } } }).html<body> <div id="app"> <h2>ビットコイン価格</h2> <!-- 追加 --> <section v-if="hasError"> 通信エラーが発生しています。 </section> <!-- 追加 --> <section v-else> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>8. ローディング表示
通信中にLoadingと表示する。
・dataオプションにloadingプロパティを追加(名称任意)
┗ 初期値:true・axiosの通信終了後にloadingプロパティをfalseにする。
.finally(function(){処理}.bind(this))
┗ .finally: 処理が終わったら実行
┗ .bind(this): dataプロパティと紐付ける・テンプレートにv-ifで「loading...」を記述。
┗ v-if="loading"で、trueの間のみ表示。・正常な表示内容に
v-else
を設置。.jsvar app = new Vue({ el: '#app', data:{ bpi: null, hasError: false, //追加 loading:true }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) this.hasError = true }.bind(this)) //追加 .finally(function(){ this.loading = false }.bind(this)) }, filters:{ currencyDecimal(value){ return value.toFixed(2) } } }).html<body> <div id="app"> <h2>ビットコイン価格</h2> <section v-if="hasError"> 通信エラーが発生しています。 </section> <section v-else> <!-- 追加 --> <div v-if="loading"> Loading... </div> <div v-else> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>
9. 完成版
.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Bitcoin API</title> <link rel="stylesheet" href="css/main.css"> </head> <body> <div id="app"> <h2>ビットコイン価格</h2> <section v-if="hasError"> 通信エラーが発生しています。 </section> <section v-else> <!-- 追加 --> <div v-if="loading"> Loading... </div> <div v-else> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body> </html>.jsvar app = new Vue({ el: '#app', data:{ bpi: null, hasError: false, //追加 loading:true }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) this.hasError = true }.bind(this)) //追加 .finally(function(){ this.loading = false }.bind(this)) }, filters:{ currencyDecimal(value){ return value.toFixed(2) } } }).css[v-cloak]{ display: none; }
- 投稿日:2020-08-04T15:00:58+09:00
【Vue.js】ビットコイン価格表示アプリの作成
【Vue.js】ビットコイン価格表示アプリの作成
・価格はcoindeskのAPIのデータを使用。
・データ取得はaxiosを使用。作成手順
0.使用するAPIの確認
1. bpiの価格を格納するプロパティを作成
2. axiosのCDNを読み込みとデータ取得
3. エラーcatch構文の設定
4. 画面上に価格を表示
5. 小数点以下の調整(filterオプション)
6. チラつき防止(v-cloak)
7. エラー時の表示分岐
8. ローディング表示
9. 完成版0. 使用するAPIの確認
coindeskのビットコイン価格を使用。公式ページからAPIのURLをコピー。
▼ビットコインの現在価格API
・APIエンドポイント:
https://api.coindesk.com/v1/bpi/currentprice.json・API:Application Programming Interface
┗ 第三者アプリのデータ取得
・endpoint: 固有で変更することのないURL
・BPI:Bitcoin Price Index(ビットコイン価格指数)
▼使用するデータ
bpiプロパティのUSDプロパティのrateを使用。1. bpiの価格を格納するプロパティを作成
.html<body> <div id="app"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.jsvar app = new Vue({ el: '#app', data:{ bpi: null } })初期値はnullとする。
2. axiosのCDNを読み込み
axiosとは?
指定したWEBサイトからデータを取ってくるJSライブラリ。
┗ HTTP(WEB)クライアントと呼ぶ。axiosの使い方
1. axiosのCDNを.htmlに貼り付け
▼最新バージョンを使用する場合
githubから、jsDeliverのCDNをコピー。
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
▼バージョンを固定する場合
jsDeliverの公式ページから直接CDNを取得。
「dist/axion.min.js」を使う。
https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js
2. mountedプロパティを使ってJSファイルでデータ取得したいURLを指定
mounted:function(){}
┗ mountedプロパティ
axios.get('url').then(function(response)){処理}.bind(this)
┗ mountedプロパティの中でaxiosを使う
┗ 引数responseに取得データが格納される ※引数は任意(resなどでも可)
┗ データ使用は、引数名.data (response.data)
┗ .bind(this)でインスタンスと紐付ける``
※.bind(this)でインスタンスと紐付けないとdataと紐づかない。
.jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi; }.bind(this)) } })改行できる。.thisや.bindで改行すると見やすくなる。
▼console.logで確認する方法
console.logで出力すると、chromeのdeveloperツールでデータ取得できているか確認できる。・bpiデータ:console.log(response.data.bpi)
・USDの価格:console.log(response.data.bpi.USD.rate_float).jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json').then(function(response){ console.log(response.data.bpi); console.log(response.data.bpi.USD.rate_float); this.bpi = response.data.bpi; }.bind(this)) } })3. エラーcatch構文の設定
.catch(function(error){処理}
┗ 引数は任意。errなどでも可.jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) }) } })4. 画面上に価格を表示
・v-forで複数のプロパティデータを個々に取得し、マスタッシュ構文で表示。
v-for="(値の変数, プロパティ名の変数) in プロパティ"
.html<body> <div id="app"> <h2>ビットコイン価格</h2> <ul> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>5. 小数点以下の調整(filterオプション)
▼JSファイル
・フィルタ名(value){return value.書式}
・.toFixed(桁数)
:数の小数点表記。▼HTMLファイル
・{{値 | フィルタ名}}
.html<body> <div id="app"> <h2>ビットコイン価格</h2> <ul> <li v-for="(rate, currency) in bpi"> <!-- 追記 --> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>.jsvar app = new Vue({ el: '#app', data:{ bpi: null }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) }) }, //追記 filters:{ currencyDecimal(value){ return value.toFixed(2) } } })6. チラつき防止(v-cloak)
画面ロード時に一瞬コードが表示される。(チラつきと呼ぶ)
v-cloakディレクティブを使用
・タグの属性に
v-cloak
を追加
・cssファイルに[v-cloak]{処理}
を記述.html<body> <div id="app"> <h2>ビットコイン価格</h2> <!-- 追記 --> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>.css[v-cloak]{ display: none; }7. エラー時の表示分岐
通信エラー発生時にエラー用テキストを表示。エラーがない場合は正常に表示。
・
v-if="真偽値"
とv-else
を使う
┗ true:要素を表示
┗ false:v-elseがある要素を表示・dataオプションにhasErrorプロパティを設置(名称は任意)
┗ 初期値をfalseにし、正常表示のタグにv-elseを設置・catch構文でエラー発生時に、hasErrorをtrueにする
┗ dataオプションと紐づけるため、.bind(this)
をつける。.jsvar app = new Vue({ el: '#app', data:{ bpi: null, //追加 hasError: false }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) //追加 this.hasError = true }.bind(this)) }, filters:{ currencyDecimal(value){ return value.toFixed(2) } } }).html<body> <div id="app"> <h2>ビットコイン価格</h2> <!-- 追加 --> <section v-if="hasError"> 通信エラーが発生しています。 </section> <!-- 追加 --> <section v-else> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>8. ローディング表示
通信中にLoadingと表示する。
・dataオプションにloadingプロパティを追加(名称任意)
┗ 初期値:true・axiosの通信終了後にloadingプロパティをfalseにする。
.finally(function(){処理}.bind(this))
┗ .finally: 処理が終わったら実行
┗ .bind(this): dataプロパティと紐付ける・テンプレートにv-ifで「loading...」を記述。
┗ v-if="loading"で、trueの間のみ表示。・正常な表示内容に
v-else
を設置。.jsvar app = new Vue({ el: '#app', data:{ bpi: null, hasError: false, //追加 loading:true }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) this.hasError = true }.bind(this)) //追加 .finally(function(){ this.loading = false }.bind(this)) }, filters:{ currencyDecimal(value){ return value.toFixed(2) } } }).html<body> <div id="app"> <h2>ビットコイン価格</h2> <section v-if="hasError"> 通信エラーが発生しています。 </section> <section v-else> <!-- 追加 --> <div v-if="loading"> Loading... </div> <div v-else> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body>
9. 完成版
.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Bitcoin API</title> <link rel="stylesheet" href="css/main.css"> </head> <body> <div id="app"> <h2>ビットコイン価格</h2> <section v-if="hasError"> 通信エラーが発生しています。 </section> <section v-else> <!-- 追加 --> <div v-if="loading"> Loading... </div> <div v-else> <ul v-cloak> <li v-for="(rate, currency) in bpi"> {{currency}} : {{rate.rate_float | currencyDecimal}} </li> </ul> </div> </section> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script> <script src="js/main.js"></script> </body> </html>.jsvar app = new Vue({ el: '#app', data:{ bpi: null, hasError: false, //追加 loading:true }, mounted: function(){ axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(function(response){ this.bpi = response.data.bpi }.bind(this)) .catch(function(error){ console.log(error) this.hasError = true }.bind(this)) //追加 .finally(function(){ this.loading = false }.bind(this)) }, filters:{ currencyDecimal(value){ return value.toFixed(2) } } }).css[v-cloak]{ display: none; }
- 投稿日:2020-08-04T14:49:28+09:00
Vuejs CLIにて一部を外部htmlファイルを読み込んで実装する方法
Vuejs CLI環境下で一部をhtmlで実装したい時
Vuejs CLIでvue拡張子のファイル内で一部をhtmlファイルを読み込んで実装したい時がある方、
その方々に、試行錯誤を経て分かった方法を共有します。参考
環境の整理
- 開発環境:Vuejs CLIでインストールしたばかりの環境
方法
- Vuejs CLIをインストールする。
HelloWorld.vueが生成される、その中を以下のように変更。
HelloWorld.vue<template> <div class="hello"> <p>Practice</p> <div v-html="htmlContent"></div> </div> </template> <script> export default { name: "HelloWorld", data() { return { htmlContent: "", }; }, mounted: function () { this.loadHtml(); }, methods: { loadHtml() { fetch("./html/sample.html").then((res) => { res.text().then((html) => { this.htmlContent = html; }); }); }, }, }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>肝は
*v-htmlを使用
*dataにv-htmlで使用しているデータhtmlContentを紐づける
*mountedにて、fetch使用のメソッドloadHtmlを読み込む
*methodsにて、メソッドloadHtmlを定義し、fetchで外部htmlを読み込んで、
htmlをデータhtmlContentに格納する。fetchメソッドに書いたパス(./html/sample.html)に
sample.html(=今回対象となる一部htmlファイル)を格納する。
*publicフォルダの中となる。
sample.html中は以下のようにstyle, htmlタグを書くことができる。
sample.html<style> .text { color: red; } </style> <div class="text">Hello ! External.htmlだよ! </div>*
npm run build
コマンドを実行しビルドした場合、
distフォルダ内にhtmlはそのまま格納される。
(このsample.htmlを直した場合もブラウザーに問題なく反映された。)
- 投稿日:2020-08-04T12:04:06+09:00
VeeValidateを利用したコンポーネントをJestでテストする
はじめに
Vue v3及び、CompositionAPIで作られたコンポーネントでvee-validate v3系を対象に、Jestでテストを書きます
以下のようなコンポーネントを想定
- validationProviderでinputをvalidate
- validationObserverで各Providerを監視
child-input.vue<template> <validation-provider mode="eager" rules="required"> <input v-model="val" name="input" > <ul v-if="errors.length" class="errors"> <li v-for="(error, i) in errors" :key="i"> {{ error }} </li> </ul> </validation-provider> </template> <script lang="ts"> export default { setup(_, { emit }) { const val = ref<string>('') watch(() => { emit('update', val.value) }) return { val } } } </script>parent-form.vue<template> <validation-observer ref="observer"> <form> <child-input @update="update" /> </form> </validation-observer> </template> <script lang="ts"> export default { setup(_, { emit }) { const val = ref<string>('') const update = (value: string) => { val.value = value } return { val, update } } } </script>テスト
それではテストを書いていきます
form-validation.spec.tsimport { createLocalVue, mount } from '@vue/test-utils' import { ValidationObserver, ValidationProvider, extend } from 'vee-validate' import ParentForm from '@your/path/parent-form.vue' const localVue = createLocalVue() localVue.component('ValidationObserver', ValidationObserver) localVue.component('ValidationProvider', ValidationProvider) const { required } = require('vee-validate/dist/rules.umd') extend('required', required) jest.useFakeTimers() describe('フォームのバリデーションチェック', () => { test('未入力でバリデーションされること', async (): Promise<any> => { const wrapper = mount(ParentForm, { localVue }) const observer: InstanceType<typeof ValidationObserver> = wrapper.vm.$refs.observer await observer.validate() jest.runAllTimers() await wrapper.vm.$nextTick() expect(wrapper.find('.errors').exists()).toBeTruthy() }) test('入力が完了すること', async (): Promise<any> => { const wrapper = mount(ParentForm, { localVue }) wrapper.find('input').setValue('hoge') const observer: InstanceType<typeof ValidationObserver> = wrapper.vm.$refs.observer await observer.validate() jest.runAllTimers() await wrapper.vm.$nextTick() expect(wrapper.find('.errors').exists()).toBeFalsy() }) })テストの解説
それぞれの処理について見ていきます。
const wrapper = mount(ParentForm, { localVue })今回は子コンポーネントもテスト対象のため
shalowMount
ではなくmount
を利用しています。古い記事を参照するとmount
のオプションに{ sync: false }
を追加するという情報がありますがそのオプションは廃止されています。
https://github.com/vuejs/vue-test-utils/issues/1137const observer: InstanceType<typeof ValidationObserver> = wrapper.vm.$refs.observer await observer.validate()ValidationObserverインスタンスを取得して
validate
メソッドを実行します。これによってvee-validateのバリデーションが実行されます。jest.runAllTimers()ValidationObserverの処理に16msかかるそうで、それを待ちます。
https://logaretm.github.io/vee-validate/advanced/testing.html#testing-validationobserver-debounced-stateawait wrapper.vm.$nextTick()先程
{ sync: false }
オプションがなくなったことで画面描画を待つために、$nextTick
を利用します。このメソッドがPromiseを返すためawaitで待つことによってこの後の処理ではDOMに反映された状態を取得することができます。
vee-validate公式ではflush-promises
を使う例を紹介されていますが$nextTickを利用することで同様の結果を得られるので不要になるかと思います。まとめ
sync
オプションはもう使えないflush-promises
ではなく$nextTick
を使おう
- 投稿日:2020-08-04T11:52:40+09:00
Vue.jsを1から学んでみた〜カスタムディレクティブ〜
11-1 カスタムディレクティブとは
Vue.jsで用意してくれているディレクティブ(
v-on
,v-bind
等)の他に、
自分で作成したディレクティブ(これがカスタムディレクティブ)を定義&使用できる。簡単な例(グローバル登録)
画面が表示された時に最初にフォーカスされる
v-focus
というカスタムディレクティブを定義、使用します。main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false // グローバル登録:カスタムディレクティブ Vue.directive('focus', { // フック関数 inserted: function (el) { // ディレクティブフックに引数でelを渡し、 // 要素にフォーカスを当てる el.focus() } }) new Vue({ render: h => h(App), }).$mount('#app')App.vue<template> <div> <Job></Job> </div> </template> <script> import Job from "./components/Job.vue"; export default { data: function() { return { defaultAge: 15, defaultCheck: true } }, components: { Job: Job } } </script>Job.vue<template> <div> <p>私はエンジニアです</p> <input type="checkbox"> <!-- こちらにフォーカスがあたる --> <input type="text" v-focus> </div> </template>簡単な例(ローカル登録)
main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')App.vue<template> <div> <Job></Job> </div> </template> <script> import Job from "./components/Job.vue"; export default { data: function() { return { defaultAge: 15, defaultCheck: true } }, components: { Job: Job } } </script>Job.vue<template> <div> <p>私はエンジニアです</p> <input type="checkbox"> <!-- こちらにフォーカスがあたる --> <input type="text" v-focus> </div> </template> <script> export default { directives: { // ローカル登録:カスタムディレクティブ focus: { inserted: function (el) { // ディレクティブフックに引数でelを渡し、 // 要素にフォーカスを当てる el.focus() } } } } </script>フック関数
カスタムディレクティブには、(Vueインスタンスのライフサイクルフックのような)用意された関数がある。
main.jsVue.directive('focus', { // bind(), inserted(), update(), componentUpdated(), unbind() // 上記5つが用意されている。 bind(el, binding, vnode) { // 画面が表示された時に1回だけ実行されるメソッド }, inserted(el, binding, vnode) { // 親Nodeに挿入された時に実行されるメソッド }, update(el, binding, vnode, oldNode) { // 子コンポーネントが更新される前に実行されるメソッド }, componentUpdated(el, binding, vnode, oldNode) { // 子コンポーネントが更新される後に実行されるメソッド }, unbind(el, binding, vnode, oldNode) { // ディレクティブが紐づいている要素から削除される時に1回だけ実行されるメソッド } })ディレクティブフック引数
フック関数には、以下の引数を渡せる。
- el:ディレクティブのが紐づく要素。VNodeではなく、DOM要素を直接操作できる。
- binding:オブジェクト。以下のプロパティを持つ
- name:
v-
無しのディレクティブ名。v-focus
であればfocus
。- value: ディレクティブに渡される値。
v-focus="'1+1'"
であれば1+1
という文字列。ダブルクォーテーション内はJavaScript式として判断されるため、文字列を指定する場合はシングルクォーテーションが必要。- oldValue: update と componentUpdated においてのみ利用できる、更新前の値。
- expression: ディレクティブに渡される値を文字列として評価する。
v-focus="1+1"
は、valueの場合2
、expressionの場合1+1
となる。- arg: ディレクティブに渡される引数。
v-focus:hoge
であればhoge
。一つしか設定できない。- modifiers: 修飾子 (modifier) を含んでいるオブジェクト。設定された場合、trueが設定される。
v-focus:hoge.foo.zoo
の場合、{ foo: true, zoo: true}
となる。- vnode:紐づくVNode=仮想ノード。
- oldValue:
update()
,componentUpdated()
のみで利用できる。変更前のVnode。省略記法
実際のところ、フック関数は
bind()
、update()
が多く使われる。
このため、Vue.jsは以下のような省略記法が用意される。main.jsVue.directive('color-swatch', function (el, binding) { el.style.backgroundColor = binding.value })実際の開発でもほぼこれが使われるだろうと思う。
11-2 引数:el
elは、直接DOMを操作できる。
main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.directive('color-swatch', function (el) { // elを使い、背景色を赤色に。 el.style.backgroundColor = 'red' }) new Vue({ render: h => h(App), }).$mount('#app')Job.vue<template> <div> <p>私はエンジニアです</p> <input type="text" v-color-swatch> </div> </template>11-3 引数:binding
value(単一)
カスタムディレクティブに値を渡すことで、bindingに設定される
main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.directive('color-swatch', function (el, binding) { // カスタムディレクティブの // bindingを使って背景色を変更する el.style.backgroundColor = binding.value }) new Vue({ render: h => h(App), }).$mount('#app')Job.vue<template> <div> <p>私はエンジニアです</p> <!-- 値を指定する。JavaScriptを指定するので文字列はシングルクォーテーション --> <input type="text" v-color-swatch="'blue'"> </div> </template>value(複数)
カスタムディレクティブにオブジェクトを渡すことで、bindingに設定される
main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.directive('color-swatch', function (el, binding) { // オブジェクトのkeyを指定する el.style.backgroundColor = binding.value.color el.style.width = binding.value.width }) new Vue({ render: h => h(App), }).$mount('#app')Job.vue<template> <div> <p>私はエンジニアです</p> <!-- 値を指定する。JavaScriptを指定するので文字列はシングルクォーテーション --> <input type="text" v-color-swatch="{color: 'black', width: '15px'}"> </div> </template>arg
ディレクティブに渡される引数。
v-focus:hoge
であればhoge
。一つしか設定できない。main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.directive('color-swatch', function (el, binding) { el.style.backgroundColor = binding.value.color el.style.width = binding.value.width // .argで引数の文字列をそのまま取得できる el.style.borderStyle = binding.arg }) new Vue({ render: h => h(App), }).$mount('#app')Job.vue<template> <div> <p>私はエンジニアです</p> <!-- :dotted のように引数を指定する --> <!-- 引数の指定は一つだけしか許可されていない --> <input type="text" v-color-swatch:dotted="{color: 'white', width: '200px'}"> </div> </template>modifiers
修飾子 (modifier) を含んでいるオブジェクト。設定された場合、trueが設定される。
v-focus:hoge.foo.zoo
の場合、{ foo: true, zoo: true}
となる。main.jsimport Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.directive('color-swatch', function (el, binding) { el.style.backgroundColor = binding.value.color el.style.width = binding.value.width el.style.borderStyle = binding.arg if (binding.modifiers.round) { // modifirs.修飾子名で評価できる el.style.borderRadius = "500rem" } }) new Vue({ render: h => h(App), }).$mount('#app')Job.vue<template> <div> <p>私はエンジニアです</p> <!-- .roundのように修飾子を指定する --> <!-- 複数指定する場合は、:dotted.round.mount のように、.でつなげる --> <input type="text" v-color-swatch:dotted.round="{color: 'white', width: '200px'}"> </div> </template>
- 投稿日:2020-08-04T11:23:58+09:00
【Vue.js】オブジェクト、プロパティ、プロパティ名の違い
【Vue.js】オブジェクト、プロパティ、プロパティ名の違い
呼び名で迷うことがあるのでメモ。
<条件>
・変数appに生成したVueインスタンスを格納。
・入れ子構造のデータが存在。.jsvar app = new Vue({ el: "#app", data:{ user:{ age:27, lastName:'Toroki', firstName:'Takashi' }, product:{ serise: 'iphone10', price: 110000 } }, methods:{ onClick:function(){ alert('Clicked!') } } })オブジェクト
一つの塊。(複数の)プロパティから成る。
app
がオブジェクト。プロパティ
プロパティ名:値
のセットの呼び名。
入れ子構造をとる。el: "#app"
data:{ }
user:{ }
age:27
LastName: 'Todoroki'
method:{ }▼入れ子の例(プロパティ3つ)
dataプロパティの中の、userプロパティの中の、ageプロパティのプロパティ名がage, 値が27。.jsdata:{ user:{ age:27, } }
- 投稿日:2020-08-04T11:23:58+09:00
【Vue.js】オブジェクト、オプション、プロパティ、プロパティ名の違い
【Vue.js】オブジェクト、オプション、プロパティ、プロパティ名の違い
呼び名で迷うことがあるのでメモ。
<条件>
・変数appに生成したVueインスタンスを格納。
・入れ子構造のデータが存在。.jsvar app = new Vue({ el: "#app", data:{ user:{ age:27, lastName:'Toroki', firstName:'Takashi' }, product:{ serise: 'iphone10', price: 110000 } }, methods:{ onClick:function(){ alert('Clicked!') } } })オブジェクト
一つの塊。(複数の)プロパティから成る。
app
がオブジェクト。オプション
正式名称はコンポーネントオプション。用途毎にオプションを指定する。
オプションの中身は(複数の)プロパティになっているため、各オプションのデータをオプションオブジェクトと呼ぶ。
▼主なオプション
オプション 内容 el テンプレートと紐付けるid名を記述。.html(DOM)にVueインスタンスを与える data データオブジェクト filters 書式の設定 methods イベント発生時の処理 ・コンポーネントオプション公式ページ
https://012-jp.vuejs.org/api/options.htmlプロパティ
プロパティ名:値
のセットの呼び名。
入れ子構造をとる。el: "#app"
data:{ }
user:{ }
age:27
LastName: 'Todoroki'
method:{ }▼入れ子の例(プロパティ3つ)
dataプロパティの中の、userプロパティの中の、ageプロパティのプロパティ名がage, 値が27。.jsdata:{ user:{ age:27, } }
- 投稿日:2020-08-04T11:23:07+09:00
UIT INSIDE(Podcast)のVue 3 Study回をまとめます
2020年7月18日にVue 3.0がRC(Release Candidate)ステージに入りましたので
そろそろVue 3 キャッチアップしたい皆さんが多いと思います。ということで、
LINE UIT室の開発者による「最新のフロントエンド」をキャッチアップできる
Podcast「UIT INSIDE」の Vue 3 Studyの回のみURLをまとめます。
更新日 タイトル URL 2020/02/07 ep.32 Vue 3 Study
「RFC を全部読んで理解する Vue 3.0 の進化」https://uit-inside.linecorp.com/episode/32 2020/02/21 ep.34 Vue 3 Study
「バンドルサイズを減らすTree Shakingとその方法」https://uit-inside.linecorp.com/episode/34 2020/03/26 ep.36 Vue 3 Study
「何が変わる? Composition API」https://uit-inside.linecorp.com/episode/36 2020/04/17 ep.39 Vue 3 Study
「Render function で React の世界を覗いてみる」https://uit-inside.linecorp.com/episode/39 2020/06/26 ep.51 Vue 3 Study
「Teleport でキレイに解消するモーダルの z-index 問題」https://uit-inside.linecorp.com/episode/51 2020/07/10 ep.53 Vue 3 Study
「Vue.js にもやってくる Fragment」https://uit-inside.linecorp.com/episode/53 音声を1.5倍にすると、サクサク聴けてオススメです!
UITはイベントも開催してるみたいです。
https://uit.connpass.com/Vue 3 参考リンク
v3のドキュメントと移行ガイドはまだベータ版です。
- 投稿日:2020-08-04T11:07:58+09:00
【Vue.js】ToDoアプリの作成
【Vue.js】ToDoアプリの作成
実装する機能
- listの追加
- 追加したリストの個々削除
- 空の入力値の場合追加しない
- 完了・未完了のチェックボックス作業手順
- Vue.jsの読み込み
- Vueインスタンスの作成
- 空のルートテンプレートの作成
- テンプレートのマウント
- 見出し設置
- フォーム作成
- 入力欄作成
- ボタンの作成
- クリックイベントの設置
- フォームsubmitの無効化(イベント修飾子.prevent)
- inputタグ内容の双方向バインディング
- 追加内容を格納する配列を作成
- 配列にタスクを追加する処理を作成
- タスク追加後にinputタグの表示を消去
- inputタグが空ならタスクを追加しない
- タスクを表示する
- チェックボックスの表示とステータス管理
- リストマークの非表示
- タスク完了時に取消線を設置
- タスク削除機能
- 完成版
1. Vue.jsの読み込み
.html<body> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>2. Vueインスタンスの作成
.jsvar app = new Vue({ })※変数は省略可
3. 空のルートテンプレートの作成
.html<body> <div id="app"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>4. テンプレートのマウント
.jsvar app = new Vue({ // ▼追加 el: "#app" })5. 見出し設置
.html<body> <div id="app"> <h1>To Do List</h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>6. フォーム作成
.html<body> <div id="app"> <h1>To Do List</h1> <!-- ▼追加 --> <form action=""> </form> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>7. 入力欄作成
.html<body> <div id="app"> <h1>To Do List</h1> <form action=""> <!-- ▼追加 --> <input type="text" > </form> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>8. ボタンの作成
.html<body> <div id="app"> <h1>To Do List</h1> <form action=""> <input type="text" > <!-- ▼追加 --> <button>追加</button> </form> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>9. クリックイベントの設置
.html<body> <div id="app"> <h1>To Do List</h1> <form action=""> <input type="text" > <!-- ▼追加 --> <button v-on:click="addItem">追加</button> </form> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.jsvar app = new Vue({ el: "#app", // ▼追加 methods:{ addItem:function(event){ } } })10. フォームsubmitの無効化
・フォームで次ページのロードを無効にする。
・イベント修飾子 .prevent を使用。
v-on:submit.prevent
.html<body> <div id="app"> <h1>To Do List</h1> <!-- ▼追加 --> <form v-on:submit.prevent> <input type="text" > <button v-on:click="addItem">追加</button> </form> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>11. inputタグ内容の双方向バインディング
・inputタグの入力内容を保存するdataオプションを作成
・プロパティ名はnewItem
・デバッグ用にdataオプションの中身を表示.jsvar app = new Vue({ el: "#app", // ▼追加 data:{ newItem:'' }, methods:{ addItem:function(event){ } } }).html<body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <!-- ▼追加 --> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>12. 追加内容を格納する配列を作成
・タスク追加用配列として、tasks[]を用意。
.jsvar app = new Vue({ el: "#app", data:{ newItem:'', // ▼追加 tasks: [] }, methods:{ addItem:function(event){ } } })13. 配列にタスクを追加する処理を作成
・クリックする毎に、itempプロパティを作成する。
・itemプロパティを配列に格納する。
・イベント修飾子 .push を使用。.jsvar app = new Vue({ el: "#app", data:{ newItem:'', tasks: [] }, methods:{ addItem:function(event){ // ▼追加 var task = { item: this.newItem }; this.tasks.push(task); } } })ボタンクリックで {item: this.newItem} を生成。
.pushで、tasks[]の中に追加。14. タスク追加後にinputタグの表示を消去
.jsvar app = new Vue({ el: "#app", data:{ newItem:'', tasks: [] }, methods:{ addItem:function(event){ var task = { item: this.newItem }; this.tasks.push(task); // ▼追加 this.newItem = ''; } } })15. inputタグが空ならタスクを追加しない
・ifで条件分岐を設定 (※イコールは2つ)
・returnで処理を終了.jsvar app = new Vue({ el: "#app", data:{ newItem:'', tasks: [] }, methods:{ addItem:function(event){ // ▼追加 if(this.newItem =='') return; var task = { item: this.newItem }; this.tasks.push(task); this.newItem = ''; } } })16. タスクを表示する
・v-for="変数名 in 配列"
・マスタッシュ構文 {{変数名}}
・変数のプロパティを抜き出す 変数名.プロパティ名.html<body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <!-- ▼追加 --> <li v-for="task in tasks"> <span>{{task.item}}</span> </li> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>17. チェックボックスの表示とステータス管理
・チェックボックスの初期値をfalse(チェックなし)にする
・inputタグのtype="checkbox"にv-modelを記述すると、チェックボックスのステータスを双方向バインディングできる.jsvar app = new Vue({ el: "#app", data:{ newItem:'', tasks: [] }, methods:{ addItem:function(event){ if(this.newItem =='') return; var task = { item: this.newItem, // ▼追加 isActive: false }; this.tasks.push(task); this.newItem = ''; } } }).html<body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <li v-for="task in tasks"> <!-- ▼追加 --> <input type="checkbox" v-model="task.check"> <span>{{task.item}}</span> </li> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>18. リストマークの非表示
・cssで設定
.css#app li{ list-style: none; }※HTMLファイルのheadタグ内でcssファイルを読み込む。
<link rel="stylesheet" href="css/main.css">
19. タスク完了時に取消線を設置
・cssのバインディングを使用
v-bind:class{クラス名:真偽値}
┗ trueの時のみ指定したclass属性を付与.html<body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <li v-for="task in tasks"> <input type="checkbox" v-model="task.isActive"> <!-- ▼追加 --> <span v-bind:class="{active:task.isActive}">{{task.item}}</span> </li> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>.css#app li{ list-style: none; } #app li > span.active{ text-decoration: line-through; }
<span v-bind:class="{active:task.isActive}">{{task.item}}</span>
・spanタグにclass=activeをバインド。
・isActiveの値がtrueなら属性を付与。falseなら付与しない。20. タスク削除機能
・削除ボタンの設置
・削除ボタンとインデックス番号を連動
┗ v-for="(変数1, 変数2) in 配列"
→ 変数2にインデックス番号が入る
・要素の削除 .spliceを使用
.splice(開始配列番号, 削除する配列数)
→ array.splice(2,2): 3つ目の要素から2つの要素を削除.jsvar app = new Vue({ el: "#app", data:{ newItem:'', tasks: [] }, methods:{ addItem:function(event){ if(this.newItem =='') return; var task = { item: this.newItem, isActive: false }; this.tasks.push(task); this.newItem = ''; }, // ▼追加 deleteItem:function(index){ this.tasks.splice(index, 1) } } }).html<body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <!-- ▼追加 --> <li v-for="(task, index) in tasks"> <input type="checkbox" v-model="task.isActive"> <span v-bind:class="{active:task.isActive}">{{task.item}}</span> <button v-on:click="deleteItem">削除</button> </li> <pre>{{$data}}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body>
完成版
.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>To do App</title> <link rel="stylesheet" href="css/main.css"> </head> <body> <div id="app"> <h1>To Do List</h1> <form v-on:submit.prevent> <input type="text" v-model="newItem"> <button v-on:click="addItem">追加</button> </form> <li v-for="(task, index) in tasks"> <input type="checkbox" v-model="task.isActive"> <span v-bind:class="{active:task.isActive}">{{task.item}}</span> <button v-on:click="deleteItem">削除</button> </li> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script> <script src="js/main.js"></script> </body> </html>.jsvar app = new Vue({ el: "#app", data:{ newItem:'', tasks: [] }, methods:{ addItem:function(event){ if(this.newItem =='') return; var task = { item: this.newItem, isActive: false }; this.tasks.push(task); this.newItem = ''; }, deleteItem:function(index){ this.tasks.splice(index, 1) } } }).css#app li{ list-style: none; } #app li > span.active{ text-decoration: line-through; }
- 投稿日:2020-08-04T02:20:32+09:00
Laravel + Vue.jsの導入方法
LaravelのBladeにVueコンポーネントを組み込む方法をまとめます。
環境
- laradock
- php: 7.3
- Laravel: 7.2
Vue.jsをインストールする
laravel/package.json"vue": "^2.6.11", "vue-template-compiler": "^2.6.11"$ docker-compose exec workspace npm installVueコンポーネントを作成する
試しにハートボタンを作成します。
laravel/resources/js/components/SampleLike.vue<template> <div> <button type="button" class="btn m-0 p-1 shadow-none" > <i class="fas fa-heart mr-1" /> </button> 10 </div> </template> <script> </script>app.jsを編集
laravel/resources/js/app.jsimport Vue from 'vue' import Samplelike from './components/SampleLike' const app = new Vue({ el: '#app', components: { SampleLike, } })laravelの全画面で使用できるようにここで読み込みます。
Laravel Mixを編集
laravel/webpack.mix.jsmix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css') .version();上記はresources/js/app.jsをトランスパイルしてpublic/jsのapp.jsというファイルで保存されるよというソースです。
.version()はトランスパイルされる時に毎回idを採番する役割ですが、これは同じidの古いjavascriptをブラウザキャッシュに残さないためです。.gitignoreを編集
下記はjavascriptが編集される都度トランスパイルされてファイルが作成・更新されていくため、
管理対象から外しておきます。laravel/.gitignore/node_modules /public/css # 追加 /public/hot /public/js # 追加 /public/mix-manifest.json # 追加トランスパイルの実行
$ docker-compose exec workspace npm run watch-pollDONE Compiled successfullyと表示されればトランスパイル成功です。
上記のコマンドはjavascriptが編集されたら自動でトランスパイルしてくれます。app.blade.phpを編集
laravel/resources/views/app.blade.php{{--省略--}} <body> <div id="app"> {{--追加--}} @yield('content') </div> {{--追加--}} <script src="{{ mix('js/app.js') }}"></script> {{--追加--}} {{--省略--}} </body>BladeにVueコンポーネントを組み込む
laravel/resources/views/posts/index.blade.php<div class="card-body pt-0 pb-2 pl-3"> <div class="card-text"> <sample-like> </sample-like> </div> </div>組み込むときはケバブケースで記述する。
これでハートボタンとダミーの10が表示でき、Vueコンポーネントを組み込めたかと思います。