【vue.js入門 #4】初心者向けvue.js解説!vue.setメソッドでプロパティを追加する方法

前回、vue.jsの最大の強みであるリアクティブシステムについて解説をしました。
【vue.js入門 #3】初心者向けにvue.jsの基本を解説!ライフサイクルフックとリアクティブ

しかし、リアクティブを正しく動作させるためには制約があります。

自由にコードを書いて、なんでもかんでもリアクティブシステムとして動くわけではありません。

今回のvue.js入門の内容は、正しく動かないvue.jsのリアクティブシステムのコードについてと、その対処法について解説していきます。

ポイントになるのはvue.setというメソッドです。

このようなコードは正しく動作をしません

html

<div id="app">
   <p>{{author.test}}</p>
</div>

js

var app = new Vue({
   el: '#app',
   data: {
       author: {
       }
   },
   created: function () {
       let that = this
       setTimeout(function () {
           that.author.test = '3秒後に変更'
       }, 3000)
   }
})

本来なら3秒後にtestプロパティを追加しているので、3秒後にブラウザの表示が変わるはずなのですが、この書き方だと変わりません。

dataオブジェクトにプロパティを予め準備していないので、vue.jsが変更を検知することができないのです。

正しく動作させる場合はこちら。

js

var app = new Vue({
   el: '#app',
   data: {
       author: {
              test: ''//ここが必要
       }
   },
   created: function () {
       let that = this
       setTimeout(function () {
           that.author.test = '3秒後に変更'
       }, 3000)
   }
})

dataオブジェクトに登録しておくことで、vue.jsが変更を検知できるようになるのです。

しかし、dataオブジェクトに予めプロパティを全て登録が必要というのも、ちょっと使い勝手が悪いですよね。

プロパティの追加を後からvue.jsに通知する書き方もあります。

それが、vue.setメソッドです。

vue.setメソッドを使って後からプロパティを追加

vue.setメソッドを使うことで、dataオブジェクトに登録されていないプロパティを後から追加し、リアクティブデータとすることができるのです。

var app = new Vue({
   el: '#app',
   data: {
       author: {
       }
   },
   created: function () {
       let that = this
       setTimeout(function () {
           //Vue.setを使ってプロパティを追加
           Vue.set(that.author, 'test', '3秒後に変更')
       }, 3000)
   }
})

しかし、vue.setを使う場合は、data直下のプロパティは変更することが出来ません。

ここでは、authorの下層のプロパティを変更しています。

リアクティブシステムの非同期更新とは?

リアクティブシステムを理解するためには、非同期通信というものについても知っておかなければなりません。

vue.jsはデータの変更を検知しても、すぐに反映されるわけではないのです。

連動して発生する様々な変更を考慮した上で、最終的に反映されているのです。

なので、このコードは正しく要素を取得することが出来ません。

js

var app = new Vue({
   el: '#app',
   data: {
       author: {
           test: ''
       }
   },
   mounted: function () {
       Vue.set(this.author, 'test', 'テスト')
   }
})

//取得できない
console.log(app.$el.textContent)

mountedというのは、ライフサイクルフックの一つで、インスタンスがページに紐付いた後に差し込むフックです。

$elはhtmlタグを取得するもので、ここではid=”app”のhtmlタグを取得しています。

そして、textContentはその中からテキストを取得するものです。

しかし、ここではうまく取得することができません。

vue.setメソッドを使い、testプロパティを変更しているので、ブラウザでは変更された内容が表示されています。

しかし、console.logは空白のままになっています。

vue.setでの変更が非同期であるため取得できないのです。

これを、取得するために必要になってくるののは$nextTickメソッドというものです。

$nextTickメソッドで更新を待って実行

$nextTickメソッドはvue.setで変更されたものの更新を待ってから処理を実行させることができるようになります。

js

var app = new Vue({
   el: '#app',
   data: {
       author: {
           test: ''
       }
   },
   mounted: function () {
       Vue.set(this.author, 'test', 'テスト')
   }
})

//更新を待ってから実行
app.$nextTick().then(function () {
   console.log(app.$el.textContent)
})

console.logで変更は確認できたでしょうか?

vue.jsでは$elにアクセスして操作をすることはほとんどありませんが、非同期で処理がされているというイメージが出来たのではないかと思います。

正社員という奴隷制度に中指を立てるWebエンジニアです。PHPが得意。繋がれた鎖を断ち切るために、自由を取り戻すために、プログラミングスキルを磨く日々です。プログラミングと個人でもできるビジネスについて、情報発信しています。

詳しくはこちら