6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【vue.js】mountedでリロード時にapiを叩く処理でthisの取り扱いにハマった

6
Last updated at Posted at 2019-11-10

mountedを使って画面読み込み時にapiから取得した値をreleasesオブジェクトにバインディングしたかったけど、thisのスコープを理解していないためハマった。

成功例

キモは次の.bind(this)である。ここでbind関数を指定しない場合、mounted内のthisはwindowオブジェクトを参照してしまう。

this.releases = response.data;
          }.bind(this))
index.html.erb

 <ul>
  <li class="content" v-for="(release, index) in releases" v-bind:key="release.id">
    <div class="subContent">
      <img class="content-image" v-bind:src="release.image" v-on:click="openModal(index)">
      <h3>{{release.title}}</h3>
      <h3>{{release.name}}</h3>

対応するvueは次の通り。

index.js
document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '#app',
    data: {
      releases:{}
    },
    mounted:function(){
        axios.get(`/api/releases`).then(function(response){
          console.log(response);
          for(let i = 0; i < response.data.length; i++) {
            response.data[i].showContent = false;
          }
          this.releases = response.data;
          }.bind(this))
          .catch(function(error) {
            console.log(error);
          });
    },
    methods:{
      openModal: function(index){
        //console.log(this.releases[index].showContent)
        this.releases[index].showContent = true
      },
      closeModal: function(index){
        this.releases[index].showContent = false
      }
      
    }
  })
})

image.png

失敗例

index.js
document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '#app',
    data: {
      releases:{}
    },
    mounted:function(){
        axios.get(`/api/releases`).then(function(response){
          console.log(response);
          for(let i = 0; i < response.data.length; i++) {
            response.data[i].showContent = false;
          }
          this.releases = response.data;
          })
          .catch(function(error) {
            console.log(error);
          });
    },
    methods:{
      openModal: function(index){
        //console.log(this.releases[index].showContent)
        this.releases[index].showContent = true
      },
      closeModal: function(index){
        this.releases[index].showContent = false
      }
      
    }
  })
})

typeerrorが出力される。この場合releasesオブジェクトにapiから取得した値をバインディングできていない
image.png

なんで

次の箇所でコールバックさせているのがダメっぽい

mounted:function(){
        axios.get(`/api/releases`).then(function(response){
          console.log(response);
          for(let i = 0; i < response.data.length; i++) {

JavaScript中級者への道【2. 4種類のthis】

hoge関数の引数のcallbackがコールバック関数と呼ばれるものです。
ここで、以下のような形でオブジェクトのメソッドを渡すと失敗します。

// 名前と、それを表示するメソッドを持つオブジェクトを作成する
var obj = {
  name : 'matsuby',
  sayName : function () {
    console.log(this.name);
  }
};

>// コールバック関数にメソッドを渡すと…
hoge(obj.sayName);  // => undefined

いつの間にかthisがグローバルオブジェクトを指しているというパターンです。
そこでbind()を使ってthisを任意のオブジェクトに束縛することで解決出来ます。

JavaScript の超便利なメソッド bind で this を制御する
などを読んで対処

thisのスコープには気をつけようね、ということ

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?