Używanie $ refs w obliczonej właściwości

85

Jak uzyskać dostęp do $refswewnątrz obliczonego? Jest to zawsze niezdefiniowane przy pierwszym uruchomieniu obliczonej właściwości.

Eric Guan
źródło
6
Tak, jest definiowany tylko po zakończeniu pierwszej pętli renderowania. Bez względu na to, co jest warte, wyraźnie nie zaleca się używania $ refs wewnątrz obliczonych właściwości, ponieważ nie jest reaktywny. vuejs.org/v2/guide/components.html#Child-Component-Refs Być może będziesz musiał znaleźć lepszy wzór ...
Cobaltway
Korzystanie z funkcji Watch wewnątrz zamontowanego: wprowadź opis linku tutaj
Phong Tran

Odpowiedzi:

129

Odpowiadając tutaj na własne pytanie, nigdzie indziej nie mogłem znaleźć satysfakcjonującej odpowiedzi. Czasami wystarczy mieć dostęp do elementu dom, aby wykonać obliczenia. Mam nadzieję, że jest to pomocne dla innych.

Musiałem oszukać Vue, aby zaktualizował obliczoną właściwość po zamontowaniu komponentu.

Vue.component('my-component', {
    data(){
        return {
            isMounted: false
        }
    },
    computed:{
        property(){
            if(!this.isMounted)
                return;
            // this.$refs is available
        }
    },
    mounted(){
        this.isMounted = true;
    }
})
Eric Guan
źródło
2
Miałem dokładnie takie same wymagania i było to jedyne działające rozwiązanie, jakie znalazłem. Powiązano właściwość klasy z obliczoną właściwością i trzeba było zastosować niektóre klasy, jeśli zagnieżdżony składnik (ref) miał ustawione właściwości.
Christophe Geers
@Bondsmith Przepraszam haha, jestem pytającym i odpowiadającym, chyba zapomniałem zaakceptować własną odpowiedź
Eric Guan
Nie zdawałem sobie sprawy. To zabawne ツ
Bondsmith
bardzo pomocny, dziękuję @EricGuan za poświęcenie czasu na odpowiedź na własne pytanie, aby pomóc innym
timmyLtus
18

Myślę, że warto zacytować przewodnik po Vue js :

$ ref są wypełniane dopiero po wyrenderowaniu komponentu i nie są reaktywne. Jest pomyślane tylko jako kreska ucieczki do bezpośredniej manipulacji podrzędnymi - należy unikać uzyskiwania dostępu do $ refs z poziomu szablonów lub obliczonych właściwości.

Dlatego nie jest to coś, co powinieneś robić, chociaż zawsze możesz to obejść.

Geoffroy
źródło
15

Jeśli potrzebujesz $refspo, v-ifmożesz użyć updated() haka.

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


updated() {
    if (!this.myProp) return;
    /// this.$refs is available
},
Facyo Kouch
źródło
sztuczka! Uwzględnij v-ifwarunki warunkowe w computedlogice, aby zostały zarejestrowane jako zależności. Dokładna odpowiedź na ciekawostkę elementu z refi przełączanego przezv-if
plong0
6

Właśnie przyszedłem z tym samym problemem i zdałem sobie sprawę, że jest to sytuacja, w której obliczone właściwości nie będą działać.

Zgodnie z aktualną dokumentacją ( https://vuejs.org/v2/guide/computed.html ):

„[…] Zamiast obliczonej właściwości możemy zdefiniować tę samą funkcję jako metodę. W przypadku końcowego wyniku oba podejścia są rzeczywiście dokładnie takie same. Różnica polega jednak na tym, że obliczone właściwości są buforowane na podstawie ich reaktywnej zależności. Obliczona właściwość zostanie ponownie oszacowana tylko wtedy, gdy niektóre z jej reaktywnych zależności ulegną zmianie

Tak więc (prawdopodobnie) zdarza się w takich sytuacjach, że zakończenie zamontowanego cyklu życia komponentu i ustawienie referencji nie jest liczone jako reaktywna zmiana w zależnościach obliczonej właściwości.

Na przykład w moim przypadku mam przycisk, który należy wyłączyć, gdy w mojej tabeli referencyjnej nie ma wybranego wiersza. Tak więc ten kod nie zadziała:

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

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

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

To, co możesz zrobić, to zamienić obliczoną właściwość na metodę, która powinna działać poprawnie:

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

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

      return this.$refs.table.selected.length > 0
    }
}
Bruno Soares
źródło
3
Myślę, że to podejście jest jak dotąd najlepsze. To nie rozprzestrzenia się z instrukcjami data(), updated()oraz inne części. Czyste i zwięzłe.
MongoLato
3

Dla innych użytkowników, takich jak ja, którzy muszą po prostu przekazać niektóre dane do prop, użyłem datazamiastcomputed

Vue.component('my-component', {
    data(){
        return {
            myProp: null
        }
    },    
    mounted(){
        this.myProp= 'hello'    
        //$refs is available              
        // this.myProp is reactive, bind will work to property
    }
})
Rodrigo Rodrigues
źródło
1

Jeśli chcesz, użyj powiązania właściwości. : wyłączona prop jest reaktywna w tym przypadku

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

Ale żeby sprawdzić dwa pola, nie znalazłem innego sposobu niż metoda fikcyjna:

<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;
   }
}
Overdozed
źródło