Usando $ refs en una propiedad calculada

85

¿Cómo $refsaccedo al interior calculado? Siempre está indefinido la primera vez que se ejecuta la propiedad calculada.

Eric Guan
fuente
6
Sí, se define solo cuando se realiza el primer bucle de renderizado. Por lo que vale, no se recomienda explícitamente usar $ refs dentro de las propiedades calculadas, ya que no es reactivo. vuejs.org/v2/guide/components.html#Child-Component-Refs Puede que tengas que encontrar un patrón mejor ...
Cobaltway
Usando la función Watch dentro del montado: ingrese la descripción del enlace aquí
Phong Tran

Respuestas:

129

Yendo a responder mi propia pregunta aquí, no pude encontrar una respuesta satisfactoria en ningún otro lugar. A veces, solo necesita acceder a un elemento dom para realizar algunos cálculos. Espero que esto sea útil para otros.

Tuve que engañar a Vue para que actualizara la propiedad calculada una vez que se montó el componente.

Vue.component('my-component', {
    data(){
        return {
            isMounted: false
        }
    },
    computed:{
        property(){
            if(!this.isMounted)
                return;
            // this.$refs is available
        }
    },
    mounted(){
        this.isMounted = true;
    }
})
Eric Guan
fuente
2
Tenía exactamente el mismo requisito y esta fue la única solución viable que encontré. Vinculaba la propiedad de clase a una propiedad calculada y tenía que aplicar algunas clases si un componente anidado (la referencia) tenía algunas propiedades establecidas.
Christophe Geers
@Bondsmith Lo siento, jaja, soy el que pregunta y responde, supongo que olvidé aceptar mi propia respuesta
Eric Guan
No me di cuenta. Eso es gracioso ツ
Bondsmith
muy útil, gracias @EricGuan por tomarse el tiempo para responder su propia pregunta para ayudar a otros
timmyLtus
18

Creo que es importante citar la guía de Vue js :

Los $ refs solo se completan después de que se haya renderizado el componente y no son reactivos. Solo está pensado como una vía de escape para la manipulación directa de niños; debe evitar acceder a $ refs desde plantillas o propiedades calculadas.

Por lo tanto, no es algo que se supone que debas hacer, aunque siempre puedes hackearlo.

Geoffroy
fuente
15

Si necesita el $refsdespués v-if, puede usar el updated() gancho.

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


updated() {
    if (!this.myProp) return;
    /// this.$refs is available
},
Facyo Kouch
fuente
buen truco! Incorpora los v-ifcondicionales en la computedlógica de para que se registren como dependencias. Exactamente la respuesta a la curiosidad de un elemento con refy alternado porv-if
plong0
6

Acabo de llegar con este mismo problema y me di cuenta de que este es el tipo de situación en la que las propiedades calculadas no funcionarán.

Según la documentación actual ( https://vuejs.org/v2/guide/computed.html ):

"[...] En lugar de una propiedad calculada, podemos definir la misma función como método. Para el resultado final, los dos enfoques son exactamente iguales. Sin embargo, la diferencia es que las propiedades calculadas se almacenan en caché en función de su dependencias. Una propiedad calculada solo se volverá a evaluar cuando algunas de sus dependencias reactivas hayan cambiado "

Entonces, lo que (probablemente) sucede en estas situaciones es que terminar el ciclo de vida montado del componente y configurar las referencias no cuenta como un cambio reactivo en las dependencias de la propiedad calculada.

Por ejemplo, en mi caso, tengo un botón que debe desactivarse cuando no hay una fila seleccionada en mi tabla de referencias. Entonces, este código no funcionará:

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

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

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

Lo que puede hacer es reemplazar la propiedad calculada por un método, y eso debería funcionar correctamente:

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

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

      return this.$refs.table.selected.length > 0
    }
}
Bruno Soares
fuente
3
Creo que este enfoque es el mejor hasta ahora. No se propaga a cabo las instrucciones a data(), updated()y otras partes. Limpio y conciso.
MongoLato
3

Para otros usuarios como yo que solo necesitan pasar algunos datos para prop, usé en datalugar decomputed

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
fuente
1

Utilice el enlace de propiedad si lo desea. : el accesorio desactivado es reactivo en este caso

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

Pero para verificar dos campos, no encontré otra forma como método ficticio:

<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
fuente