計算されたプロパティでの$ refの使用


87

$refs計算された内部にアクセスするにはどうすればよいですか?計算されたプロパティが最初に実行されるときは、常に未定義です。


6
はい、最初のレンダリングループが完了したときにのみ定義されます。価値があるので、計算されたプロパティ内で$ refを使用することは、反応しないため、明示的にはお勧めしません。vuejs.org/v2/guide/components.html#Child-Component-Refsあなたがより良いパターンを見つけなければならないことがあります...
Cobaltway

マウントされた内部でウォッチ機能を使用する:ここにリンクの説明を入力してください
PhongTran20年

回答:


135

ここで私自身の質問に答えようとすると、他のどこにも満足のいく答えを見つけることができませんでした。計算を行うために、dom要素にアクセスする必要がある場合もあります。うまくいけば、これは他の人に役立つでしょう。

コンポーネントがマウントされたら、Vueをだまして計算されたプロパティを更新する必要がありました。

Vue.component('my-component', {
    data(){
        return {
            isMounted: false
        }
    },
    computed:{
        property(){
            if(!this.isMounted)
                return;
            // this.$refs is available
        }
    },
    mounted(){
        this.isMounted = true;
    }
})

2
まったく同じ要件があり、これが私が見つけた唯一の実行可能なソリューションでした。クラスプロパティを計算プロパティにバインドし、ネストされたコンポーネント(参照)にいくつかのプロパティが設定されている場合は、いくつかのクラスを適用する必要がありました。
ChristopheGeers19年

@Bondsmith笑申し訳ありませんが、私はアスカーと回答だ、と思い、私は私自身の答え受け入れることを忘れてしまった
エリック・関

気づかなかった。それは面白いツ
ボンドスミス

ヘルプ他人に自分自身の質問に答えるために時間を割いて非常に役立つ、感謝の@EricGuan
timmyLtus

すごいとても役に立ちました
熱心な学習者

20

Vuejsガイドを引用することが重要だと思います:

$ refは、コンポーネントがレンダリングされた後にのみ入力され、リアクティブではありません。これは、子を直接操作するためのエスケープハッチとしてのみ意図されています。テンプレートまたは計算されたプロパティ内から$ refにアクセスすることは避けてください。

したがって、それはあなたがすることになっていることではありませんが、いつでもそれを回避する方法をハックすることができます。


15

$refsアフターが必要な場合v-ifは、updated() フックを使用できます。

<div v-if="myProp"></div>


updated() {
    if (!this.myProp) return;
    /// this.$refs is available
},

きちんとしたトリック!v-if条件をcomputed'sロジックに組み込んで、依存関係として登録されるようにします。正確を持つ要素の好奇心への答えrefとによって切り替えv-if
plong0

9

私はこれと同じ問題を抱えていて、これが計算されたプロパティが機能しないタイプの状況であることに気づきました。

現在のドキュメント(https://vuejs.org/v2/guide/computed.html)によると:

「[...]計算されたプロパティの代わりに、メソッドと同じ関数を定義できます。最終結果として、2つのアプローチは実際にはまったく同じです。ただし、計算されたプロパティは、反応性に基づいてキャッシュされるという違いがあります。依存関係。計算されたプロパティは、そのリアクティブな依存関係の一部が変更された場合にのみ再評価されます。

したがって、これらの状況で(おそらく)発生するのは、コンポーネントのマウントされたライフサイクルを終了し、参照を設定することは、計算されたプロパティの依存関係に対する反応的な変更としてカウントされないということです。

たとえば、私の場合、参照テーブルに選択された行がないときに無効にする必要があるボタンがあります。したがって、このコードは機能しません。

<button :disabled="!anySelected">Test</button>

computed: {
    anySelected () {
      if (!this.$refs.table) return false

      return this.$refs.table.selected.length > 0
    }
}

できることは、計算されたプロパティをメソッドに置き換えることです。これは正しく機能するはずです。

<button :disabled="!anySelected()">Test</button>

methods: {
    anySelected () {
      if (!this.$refs.table) return false

      return this.$refs.table.selected.length > 0
    }
}

3
このアプローチはこれまでで最高のアプローチだと思います。それはに指示を広げていないdata()updated()と他の部分。清潔で簡潔。
MongoLato

3

いくつかのデータをpropに渡す必要がある私のような他のユーザーのために、私はdata代わりに使用しましたcomputed

Vue.component('my-component', {
    data(){
        return {
            myProp: null
        }
    },    
    mounted(){
        this.myProp= 'hello'    
        //$refs is available              
        // this.myProp is reactive, bind will work to property
    }
})

1

必要に応じて、プロパティバインディングを使用します。:disabled propは、この場合はリアクティブです

<button :disabled="$refs.email ? $refs.email.$v.$invalid : true">Login</button>

しかし、2つのフィールドをチェックするために、ダミーの方法として他の方法は見つかりませんでした。

<button
    :disabled="$refs.password ? checkIsValid($refs.email.$v.$invalid, $refs.password.$v.$invalid) : true">
            {{data.submitButton.value}}
</button>

methods: {
   checkIsValid(email, password) {
      return email || password;
   }
}

0

私も同様の状況にあり、次の方法で修正しました。

  data: () => {
   return { 
    foo: null,
   }, // data

そして、変数を監視します。

    watch: {
     foo: function() {
       if(this.$refs)
        this.myVideo = this.$refs.webcam.$el;
       return null;
      },
    } // watch

お知らせifのexistanceを評価しているthis.$refsし、それはあなたがあなたのデータを取得変更したとき。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.