web-dev-qa-db-ja.com

VueJS非同期コンポーネントデータとpromise

VueJS 2.0 RCを試し、フェッチAPIを使用して一部のコンポーネントのデータをロードします。これはモックの例です:

const Component = {
  template: '#comp',
  name: "some-component",
  data: function () {
    return {
      basic: data.subset,
      records: function () {
        return fetch('/datasource/api', {
          method: 'get'
        }).then(function (response) {
          return response.json();
        }).then(function (response) {
          if (response.status == "success") {
            return response.payload;
          } else {
            console.error(response.message);
          }
        }).catch(function (err) {
          console.error(err);
        });
      }
    }
  }
};

dataオブジェクトは、アプリケーションの初期化の前に定義されるグローバルなアプリケーションの状態であり、そのサブセットのみがコンポーネント、つまりその部分で必要です。コンポーネントのデータのメインセットは、私が呼び出そうとしている別のエンドポイントからのものです。ただし、dataプロパティはオブジェクトを期待し、レンダリングなどのテンプレートのループのコンテキストで実際には使用できないPromiseを返します(例:v-for="record in records"

私はこれを間違った方法で行っていますか?データrecordsプロパティが完全にフェッチされた後で更新するためのアプローチは何ですか?約束が解決するまでコードを強制的に停止する方法はありますか(効果的に同期させる)?とにかくデータがないとコンポーネントは役に立たないので、関係なく使用できるようになるまでには待機期間があります。

Vue-asyncやvue-resourceなどのプラグインを使用せずにコンポーネントのデータフィールドに非同期にデータを入力する正しい方法とは何ですか?

(私はこれを行うために非約束のajax呼び出しのXHR/jQueryメソッドを使用できることを知っていますが、フェッチを使用してそれを行う方法を学びたいです)


更新:作成したフックとデータをロードするメソッドを定義しようとしました これのように ですがダイスはありません-私の実験では、一度ロードされると、recordsプロパティは更新に失敗します。データが正常にフェッチされた(コンソールへのログインに成功した)場合でも、変更されません。

通常のVueコンポーネントではなく、リンクをクリックしたときにトリガーするコンポーネントであるvue-routerおよびコンポーネントを使用して、私と何か関係がある可能性があります。さらに調査しています...


更新#2:上記のjsfiddleアプローチの調査を続行し、this.recordsおよびresponse.payloadをコンソールに記録すると、レコードオブジェクトが入力されていることが表示されます。ただし、これはテンプレートまたはコンポーネント自体の変更をトリガーしないようです-Vue dev toolsで検査すると、recordsプロパティは空の配列のままです。実際、メソッドlogstuffを追加するとそれを呼び出すテンプレートへのボタンと、このメソッドにコンソールにthis.recordsを記録させると、空の配列でオブザーバーが記録されます。

enter image description here

コンポーネントのデータプロパティが明示的に別の値に設定された後でも更新されないのはなぜでしょうか。 reloadメソッドをトリガーする$routeのウォッチャーを設定しようとしましたが、ダイスはありません-そのルートの後続のすべてのロードは実際にフェッチを再発行し、コンソールはthis.recordsを(フェッチ内から)として記録します)、ただし「実際の」this.recordsは空の配列のままです。

11
Swader

解決策は、ひねりを加えたjsfiddleアプローチでした。この部分:

_reload: function () {
      fetch('/data/api', {
        method: 'get'
      }).then(function (response) {
        return response.json();
      }).then(function (response) {
        if (response.status == "success") {
          this.records = response.payload;
        } else {
          console.error(response.message);
        }
      }).catch(function (err) {
        console.error(err);
      });
    }
_

次のように、フェッチ後に_this.records_値を設定する部分に.bind(this)が必要でした:

_reload: function () {
      fetch('/data/api', {
        method: 'get'
      }).then(function (response) {
        return response.json();
      }).then(function (response) {
        if (response.status == "success") {
          this.records = response.payload;
        } else {
          console.error(response.message);
        }
      }.bind(this)).catch(function (err) {
        console.error(err);
      });
    }
_

この投稿 が私にクリックしてもらいました。

教訓:最新のJSでは、常にスコープを念頭に置いてください。

5
Swader