Vue.jsの書き方実例集(随時追加)※逆引きリファレンス的な

  • 7
    Like
  • 0
    Comment

Vue.jsで色々書き方のルールがあるようで、備忘録として実際に使ったものをここにまとめていきます。
最初は少ないですが随時追加していく予定です。

1.propsで受け取った変数の中身を表示

{{ }}を使う

<template lang="html">
    <div>
        <p>{{ message.message }}</p>
        <small>{{ message.user.name }}</small>
    </div>
</template>

<script>
    export default {
        props:["message"]
    }
</script>

2.propsで受け取った変数をimgタグのsrc属性に指定

v-bindを使う。 {{}} で囲わずそのまま指定する。

<template lang="html">
    <div>
        <img v-bind:src="message.user.img_path">
        <!--<img :src="message.user.img_path">-->
    </div>
</template>

<script>
    export default {
        props:["message"]//ChatLog.vueからmesssageを受け取る
    }
</script>

3.Laravelから受け取ったデータをVueコンポーネントで使う

<!-- room.blade.php -->
<!-- v-bindディレクティブにblade記法で使いたい値を入れる -->
<chat-log v-bind:user-id="{{ $user->id }}"></chat-log>

ここで v-bind に入れた値がVueコンポーネント ChatLog.vue に伝わる。

<!-- ChatLog.vue -->
<!-- propsで受け取ってtemplate内で表示 -->
<template lang="html">
    <div class="chat-log">
         <p>{{ userId }}</p>
    </div>
</template>

<script>
    export default {
        props:["userId"]
    }
</script>

※ v-bindを使う際の注意点

v-bindに指定する変数名はケバブケース

v-bind:user-id

propsで受け取る際はキャメルケース

props["userId"]

で表現する。

4.Vueテンプレート描画後に描画された要素に対して処理を行う

以下のライフサイクルを参考に、描画が終了したタイミングで処理を行うよう記述する。
lifecycle.png

mountedでVueインスタンス生成時に指定したelvm.$el(ルートな DOM 要素)が入れ替わるようなので、その後のbeforeUpdateに記述する。
以下は、描画後に画面下部にスクロールする処理

//resources/assets/js/app.js
const app = new Vue({
    el: '#app',
    beforeUpdate(){
        var bodyHeight = $('body').height();
        $('body').scrollTop(bodyHeight);
    }
});

これでうまくいきました。
ちなみにmounted()に記述しても動作しなかった。
チャット等でメッセージが追加された後に一番下の最新メッセージを表示したい場合は、updated()に上記のコードを記述する。

5.入力フォームの値の取得 + 非同期で送信

フォームに入力された値を取得するにはv-modelを利用します。
v-modelにキー名を指定することで指定したキーで入力値を取得可能です。
以下の例では、<button>をクリックすることでeditName()という非同期で入力値をPOSTするメソッドを呼び出し、その中でv-modelで指定したnameという名前でデータを取得しています。

<!-- resources/assets/js/components/ProfName.vue -->
<template>
    <div>
         <input v-model="name" placeholder="ニックネーム" required>
         <button v-on:click="editName">変更</button>
    </div>
</template>
<script>
    data: function(){
        return{
            //postで送信するためのリクエストデータ初期化
            request:{
                name:''
            }
        }
    },
    methods: {
        editName(){
            //リクエストデータに入力値を代入
            this.request.name = this.name;
            //axiosでリクエストデータ送信
            axios.post('/users', this.request).then(res => {
                console.log(res.data);
            });
        }
    }
</script>

ちなみに、既に登録済みのデータを初期値としてフォームに表示することも可能です。

<!-- profile.blade.php(Laravel) -->
<!-- usersテーブルから取得した$userをv-bindでコンポーネントに渡す-->
<prof-name v-bind:user="{{ $user }}"></prof-name>
<!-- resources/assets/js/components/ProfName.vue -->
<!-- templateはさっきと同じ -->
<template>
    <div>
         <input v-model="name" placeholder="ニックネーム" required>
         <button v-on:click="editName">変更</button>
    </div>
</template>
<script>
    //propsでバインドされた$userのデータを受け取る
    props:["user"]
    data: function(){
        return{
            //nameにpropsで受け取ったuser.nameを格納
            //これで入力フォームには初期値としてuser.nameの値が表示されます
            name:this.user.name,
            //postで送信するためのリクエストデータ初期化
            request:{
                name:''
            }
        }
    },
    methods: {
        editName(){
            //リクエストデータに入力値を代入
            this.request.name = this.name;
            //userのidを指定してpatchで送信(patchも出来るようです)
            axios.patch('/users/' + this.user.id, this.request).then(res => {
                console.log(res.data);
            });
        }
    }
</script>

6.v-on:clickに指定したメソッドに引数を渡す

template内の要素にv-on:clickでクリックイベントが発生した際に実行するメソッドを指定できるが、そのメソッドに引数を渡す例です。
v-forでitemリストを表示し、一つ一つのリストにクリックイベントを設定しています。
メソッドの括弧内に引数としてitemを渡しています。

<div>
    <p v-for="item in items">
        <span v-on:click="addAct(item)">{{ item.name }}</span>
    </p>
</div> 

7.axiosでdeleteメソッドを使う時にデータを送りたい

以下のように送信するデータをdataオブジェクトにして送る必要があるみたい。

axios.delete('/users' + item.id, {data:{item:'item'}}).then(res => {
    console.log('成功');
});

8.非同期で追加した要素を削除(見た目とレコード両方)

以下のようにv-forで表示したitemリストをクリックすると、そのリストのみ削除するdeleteItem
メソッドを実行するようにしています。
deleteItemは非同期でクリックしたItemを削除します。

<div>
    <p v-for="item in items">
        <span v-on:click="deleteItem(item)">{{ item.name }}</span>
    </p>
</div>

deleteItemメソッドで非同期でDBからItemを削除すると同時に、表示されているアイテムも削除する例がこちらです。
javascriptには配列を値から削除する関数が無いらしいので、一旦indexOfでキーを取得した上で、キーを元に配列から要素を削除します。

deleteItem(item){
    // 引数に渡したitemのitemsの中でのキーを取得しdelIdに格納
    this.delId = this.items.indexOf(item);
    // delIdをキーにitemsの配列から該当のitemを取り除く
    this.items.splice(this.delId,1);
    axios.delete('/users/' + item.id, {data:{idol:'idol'}}).then(res => {
        console.log('成功');
    });
},

9.都道府県等のselectボックスをv-forで作る

templateに全てのoptionタグ直接書いても出来ますが、コンポーネント内のdataオブジェクトで定義した上でそれをv-forを使ってtemplateに表示するやり方をしました。

・テンプレート側

<select v-model="selected">
    <option v-for="pref in prefs" v-bind:value="pref.value">{{ pref.text }}</option>
</select>

・dataオブジェクト
selectedの初期値の設定をしないと初期状態で何も表示されないので注意

export default {
    data:function(){
        return {
            //selectタグのv-modelに指定したselectedで初期値のvalueを指定する
            //これにより最初に表示される値を指定できる
            selected:1,
            prefs:[ 
                {text:'東京都',value:1},
                {text:'福岡県',value:2},
                {text:'長野県',value:3}
            ]
        }
    }
}

10.LaravelからVue.jsにv-bindで配列を渡す

以下のようにして普通に渡そうとしたらエラーになります。

<!-- profile.blade.php -->
<prof> v-bind:arr="{{ $arr }}"></prof>

理由は、Laravelのbladeテンプレートでは{{}}で囲んだ変数を自動でhtmlspecialchars()でエスケープするのですが、この関数のエスケープ対象に配列を指定することが出来ないからです。

対策としては、bladeテンプレートに引数を渡す前段階で配列をJSON形式に変換します。

//UserControll.php
$arr = json_encode($arr);
return view('profile')->with('arr',$arr);

これで以下のようにしてもエラーにならなくなります。

<!-- profile.blade.php -->
<prof> v-bind:arr="{{ $arr }}"></prof>