20210726のvue.jsに関する記事は3件です。

Vue.js基礎

Vue.jsの基礎 環境と参考文献 Vue.jsの学習における基礎の振り返りと脳内整理の為に記す。 環境 M1 MacBookAir Vue.js Ver 3.15 参考文献: Vue.js プロフェッショナル Webプログラミング 基本的にCDNでVue.jsをインポート componentについては別途、書いていこうと思います。 dataプロパティ Vueインスタンス作成時にdataオプションにオブジェクトを返す関数を定義することで、dataの状態を定義できる このデータを更新、加工して基本的にVue.jsはデータを扱う Vue.createApp({ data: function() { return { key: '値' } } }) Vueアプリケーションはオブジェクトのプロパティがアクセス、変更されることを検知できるようになる。 HTMLに出力するには <div id="app"> {{ key }} </div> マウントした要素ないであれば {{ }} でHTMLに出力ができる。 computedプロパティ 管理しているデータを加工、検証する場合に有効なプロパティである。 Vue.createApp({ data: function() { return { key: '値' } }, computed: { key: function() { //処理 }, }, }) なお、後述するmethodsとはプロパティとメソッドと明確な違いがあるが、使い分けで混乱するので、 プロパティ操作はcomputed アクション処理はmethodで初心者は使い分けを行うのが無難であると思う。 また、computedプロパティは、監視している値に変化がない場合はキャッシュ(前回の値)を返す為、 ユーザ操作による値の変更がない処理などは一度しか実行されないので注意。 例:日時処理をするdataFormatプロパティは実行した日時を元に処理している為、 一度しか実行されない。 methodsプロパティ 何らかの処理をする際に使用する。 例えば、ユーザがボタンを押した際にdataを変更したり、dataの変更と同時に他の処理をしたい場合に使用 あくまで、メソッドなので処理後に値を保持することはない。逆にcomputedプロパティはプロパティなので、値を保持することが 可能である。要は、毎回実行されるため、キャッシュを使用せずに、処理した結果が帰ってくる。 Vue.createApp({ data: function() { return { key: '値' } }, methods: { key: function() { 処理 } } }) watchプロパティ dataやcomputedのプロパティの値を監視して、変更があれば任意の処理を実行させる事ができる。 値にはオブジェクトを取り、監視したいdataやcomputedのプロパティ名をそのまま指定して、 関数を指定するのが基本形である。 引数には第一引数に新しい値と第二引数に古い値を受け取る事ができる Vue.createApp({ data: function() { return { key: '値' } }, watch: { key: function(新しい値, 古い値) { 処理 }, }, }) 一つのオブジェクトの監視という点では、上記の指定で監視を行えるが、 配列にまとめたオブジェクト(ネストされたオブジェクト)の監視を行うには別途、指定が必要となる。 handlerオプションとdeepオプションの指定を行う。 Vue.createApp({ data: function() { return { keys: [ { key: 1, }, { key: 2, }, ], } }, watch: { keys: { handler: function(新しい値, 古い値) { 処理 }, deep: true, }, }, }) watchへネストされたオブジェクトを指定して、handlerオプションで処理を指定。 deepオプションをtrueにすることで、ネストの深さに関係なく、オブジェクトの値を監視対象へ含めることが可能となる。 ディレクティブ DOM 要素に対して何かを実行することをライブラリに伝達する、マークアップ中の特別なトークンである。 HTMLに直接記述できる属性であり、省略形が存在するディレクティブもあるが、基本 v- から始まる。 v-bind HTMLの属性を状態に応じて変更できる //通常 v-bind:属性="値または式" //省略形(:だけでもOK) :属性="値または式" 値または式の部分には、dataやcomputedプロパティのオブジェクトのプロパティ名や、 methodsのプロパティ名に( )をつけた、関数呼び出しの式を指定する事ができる。 要は各プロパティに指定したオブジェクトを指定する。 ボタンの不活性化を例にすると 通常 <button v-bind:desabled="isDesablet">ボタン</button> 省略形 <button :desabled="isDesablet">ボタン</button> Vue.createApp({ data: function() { return { isDesablet: true, }, }. }) ここに、条件処理を追加すれば、ボタンの不活性化を制御できる。 class属性にv-bindを使用する際は、少し特殊で値に配列やオブジェクトも指定する事ができる。 配列 //参考コード: Vue.js プロフェッショナル Webプログラミング //v-bind:class="[プロパティ名、式]"の形で指定する //HTML <div :class="[className, 'selected', classNameComputed, classNameMethods()]}}"> //Vue.js Vue.createApp({ data: function() { return{ className: 'from-data-class-name', } }, computed: { classNameComputed: function() { return 'from-computed-class-name' }, }, methods: { classNameMethod: function() { return 'from-methods-class-name' } }, }).mount('#app') //出力されるHTML <div class="form-data-class-name selected form-computed-class-name from-methods-class-name" ></div> 上記を見ると dataプロパティに指定した className 通常のHTMLのclass属性にクラス名を与えた selected computedプロパティに指定した classNameComputed methodsに指定した classNameMethod をまとめて配列で指定しているが、出力後のHTMLを見るとしっかりクラス名として出力されている。 逆にVue.js側に配列を持たせて、HTMLのクラス属性にプロパティ名を指定しても、問題なく配列はクラス属性の値として出力される。 オブジェクト v-bind:class="[プロパティ名:値]"//の形で指定する 先程の配列の場合は[プロパティ名、式]のどちらでも指定できたのに対し、 オブジェクトの場合は[プロパティ名:値]となる。 値にはdata,computedオブジェクトのプロパティ名,( )をつけたmethodsのプロパティ名などを指定する。 この値が、true or falseでクラス名が付与されるかを制御する。 //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <div :class="'is-active': isActive, 'isinactive': !isActive"></div> //Vue.js Vue.createApp({ data: function() { return { isActive: true, } }, }).mount('#app') //出力されるHTML <div class="is-active"></div> オブジェクトの場合、dataの状態によってクラス名を動的に制御する事が多い為、computedのプロパティに オブジェクト部分を指定する場合は多い //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <div :class="className"></div> //Vue.js Vue.createApp({ data: function() { return{ isActive: false, } }, computed: { className: function() { return { 'is-active': this.isActive, 'is-inactive': !this.isActive, } }, }, }) また、HTMLの通常のクラス属性とv-bind:classは併用も可能で、 併用した場合は、通常のクラス属性で指定した値とv-bind:classで指定した値は両方とも クラス属性に付与されて出力される為、併用の問題は可読性を下げる以外にあまりない。 style属性は割愛する。 v-on DOMのイベントを感知して、指定した処理を実行する事ができる。 //通常 v-on:イベント名="メソッド名" //省略形 @:イベント名="メソッド名" //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <button type="button" @click="onClickCountUp">CountUp</button> //若くはHTML単体のみで動作できるなら(この場合は下のmethodsプロパティは丸ごといらない) <button type="button" @click="count += 1">CountUp</button> <p>{{ count }}</p> //Vue.js Vue.createApp({ data: function() { return { count: 0 } }, methods: { onClickCountUp: function() { this.count += 1 }, }, }) 基本的な使い方は上記の通りだが、上記の場合は暗黙的にmethodsプロパティのonClickCountUpに引数として$eventが渡されている。 渡さない方法、明示的に渡す方法を下記に簡単にまとめておく //onClickCountUpに()を付けない場合は暗黙的に$eventが引数に渡される <button type="button" @click="onClickCountUp">CountUp</button> //onClickCountUpに()を付ける場合は$eventが引数に渡されない。というか何も渡してないので何も渡されない <button type="button" @click="onClickCountUp()">CountUp</button> //onClickCountUpに($event)を付ける場合は$eventが明示的に引数に渡される。 <button type="button" @click="onClickCountUp($event)">CountUp</button> v-model v-bindとv-onをまとめて書きたい場合はv-modelでv-bindとv-onの機能を使用できる v-model="プロパティ名" //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <input type="text" v-model="message"> <p>{{ message }}</p> //Vue.js Vue.createApp({ data: function() { return { message: '', } }, }).mount('#app') 上記はv-modelでinputイベントを取得し、messageへ反映している。 inputに文字を打てば、それに追従して、pタグの{{message}}が打った文字を反映して画面へ出力する。 下記記事を参考に、ここでは割愛する。 https://qiita.com/simezi9/items/c27d69f17d2d08722b3a v-for 配列やオブジェクトのデータを繰り返して、出力する事が可能である。 配列 v-for="要素 in 配列" //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <div v-for="item in items">{{ item }}</div> //Vue.js Vue.createApp({ data: function() { return { items: ['item-1', 'item-2'] } }, }).mount('#app') //出力されるHTML <div>item-1</div> <div>item-2</div> またindexが必要な場合はv-for="(要素, index) in 配列"として定義すれば、indexも使用できる。 オブジェクト v-for="要素 in オブジェクト" //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <div v-for="value in object">{{ value }}</div> //Vue.js Vue.createApp({ data() { return { object: { name: 'NAME', age: 20, } } }, }).mount('#app') //出力されるHTML <div>NAME</div> <div>20</div> オブジェクトを扱う場合はkey,value,indexを使用して繰り返し処理をすることもできる。 その場合は、v-for="(value, key, index) in object"で使用できる。 ここで言う、valueは'NAME'や20 keyはname, ageとなる。 indexは配列と同様にindex番号である。 :keyを指定して、効率化を図る 繰り返し処理は便利なのだが、配列、オブジェクト内の一つの値が変化すると基本的には配列全てを繰り返し処理を行わなければならない。 そこで、一意のkeyを用意することで、配列、オブジェクト内の要素を区別することができるようになる。 keyを付与すると、Vueは要素の変更前後の差分を検出し、効率のいい処理を行う事が可能となる。 ※keyにはindexを使用しないこと。ソートやフィルターを使用して配列の順番が変化すると、意図した制御ができない可能性がある為、基本的には使用を避けること. //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML //v-bind:keyでidを取得することで、一意のデータとして紐つけできる <div v-for="item in items" :key="item.id">{{ item.name }}></div> //Vue.js Vue.createApp({ data: function() { return { items: [ { id: 1, name:'item-1', }, { id:2, name:'item2' } ] } } }).mount('#app') v-show v-show="値または式" 値にはdata,computedのプロパティ名、( )を付与した関数呼び出しのmethodsのプロパティ名を指定する事ができる。 HTMLの要素を表示非表示の切り替えが可能であり、CSSのdisplayプロパティを変更している。 つまりDOMは生成される。 単純にDOMに組み込まれて、CSSを変更しているだけなので、表示・非表示の切り替え頻度の高いものに対しては処理が軽いため、有効である。 //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <div v-if="isShow"></div> //Vue.js Vue.createApp({ data: function() { return { isShow: false, } }, }).mount('#app') //HTML出力結果 //表示されない v-if v-if="値または式" v-else-if="値または式" v-else //条件指定以外 基本的な使い方はv-showと変わらない。 ただ、v-ifの場合には、条件に合わないものは、DOMに組み込まれない。 要はv-ifはHTMLの出力そのものを制御する。 v-ifは描画負荷が高い分、切り替え頻度の低いものに対して使用することが望ましい。 ただ、条件分岐が簡単に行えるので、そこは、v-showには無い利点である。 //参考コード: Vue.js プロフェッショナル Webプログラミング //HTML <div v-if="value >= 10">10以上</div> <div v-else-if="value >= 5">5以上</div> <div v-else>5未満</div> //Vue.js Vue.createApp({ data: function(){ return { value: 7, } }, }).mount('#app') //HTML出力結果 <div>5以上</div> 終わりに Vue.js初学者なので、間違い等あったらご教授願えると幸いです。 かなり初歩的な部分を忘備録として書きましたが、ここまで読んで頂き、 長々とありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[vuejs]buttonのtypeを忘れていた。[html]

はじめに 最近タスクが落ち着いてきてそれなりの頻度で書くことができています。(当社比) くるしめられた! とあるページで、取得してきた画像を削除するページがありましたとさ・・・ button.vue <template> <div v-for="(image, index) in images" :key="index"> <img :src="image.file_path" /> <button @click="onDeleteImage(image.id)"></button> </div> </template> <script> export default { data () { return { images: [], } }, methods: { async onDeleteImage(id) { if (!confirm('削除してもよろしいですか?')) { return } try { const resp = await axios.delete('/api/image/'+id) if (resp.data.result) { alert('削除しました。') this.getItems() } else { // error message } } catch (error) { console.error(error); } } } } </script> imagesは画面読み込み時(getItems)で取得されている想定です。 delete前 delete後 削除後、alertのみで遷移の命令とか出してないな・・・って思ったんだけど、、、 初歩的なミス・・・ <button type="button" ~~~ だった・・・ どうやらbuttonタグは typeがないと初期でsubmitになるらしく、 buttonにもtype="button"と指定してあげないと画面遷移?が入るみたいでした。 まとめ buttonなんだから初期でbuttonにしろと思ったのは僕だけではないはず。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue3でHTMLをinclude的に外部から読み込む

「静的な環境ででかいwebサイトを配給したい」という謎の状態が発生したため,ファイルを送りつけるだけのサーバーからクライアントサイドでパーツを組み立てたいという記事です. 対象とする読者はHTML聞いたことある,本格的ではないページを作って遊びたい,くらいの人です.巷の†駆け出しエンジニア†みたいな薄っぺらい記事なので高度な問題は解決しません. まとめ HTML内にVueのコンポーネントを記述し,scriptでテンプレートを記述してあるjsを読み込んで展開する. <!DOCTYPE html> <div id="src_expand"> <compornent_nanka></compornent_nannka> </div> <script src="https://unpkg.com/vue@3"></script> <script src="./src_compornent.js"></script> src_compornent.js const app_src_expand = Vue.createApp({}) app_src_expand.component('compornent_nanka', { data() { return { num: 108 str: 'kenmochi' } }, template: ` <div v-bind:class="str+num+'haishin'"> 内容 {{ str+(num-3) }} </div> ` }).mount('#src_expand') 生成されるHTMLファイル <!DOCTYPE html> <div id="src_expand"> <div class="kenmochi108haishin"> 内容 kenmochi105 </div> </div> <script src="https://unpkg.com/vue@3"></script> <script src="./src_compornent.js"></script> 何が起こっているか まず,HTMLにidを持つ要素を作る.今回はdivだがheaderでもspanでも良い.ここが展開先になる.classでも動作確認できたが,公式ドキュメントが全部idだったのでそれに従った. 次に,ファイルsrc_compornent.jsに定数app_src_expand = Vue.createApp({})としてVueのオブジェクトを宣言してつくる.変数名は何でもいい. 次に,app_src_expandからコンポーネントのコンストラクタを呼び出す.第一引数にコンポーネント名を書く. data ()関数とテンプレートを作る.data ()ではテンプレート内で使う変数などを記述できる.テンプレートではHTMLファイルに展開するHTML記述を書く.ここで要素内の属性(classやhrefなど)に変数を使う場合は<div v-bind:class"">のようにv-bind:をつける.それ以外のプレーンテキストでは{{ }}で囲んでjsの式を評価して展開できる. 次に,app_src_expand.mount('#src_expand')でコンポーネントを使いたい要素のidを文字列で渡してマウントする.これで<div id="src_expand">で第一引数で宣言した文字列のコンポーネントを使える. 最後にHTML内の<div id="src_expand">に<compornent_nanka> </compornent_nannka>を書くことで,テンプレートの評価結果の文字列が展開される. 感想 サーバーサイドが使えるなら間違いなくphpとかで処理したほうがいい.今回はのっぴきならない事情でクライアントサイドを用いて保守性を最低限意識できるようにと思ってこの形を取った.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む