O VueJS na sua versão 3.0 mudou um pouco como definir a forma de reatividade do dados que são criados e utilizados nos componentes, vamos ver um pouco como está funcionando com essas mudanças.
ES6 Proxy
O ES6 trouxe uma nova funcionalidade na linguagem chamada Proxy.
Também em Design Patterns em Orientação a Objetos temos um padrão chamado Proxy, esse padrão estrutural fornece uma interface de acesso, um controlador de acesso, um interceptor, a um objeto.
E é exatamente isso que essa nova funcionalidade nos fornece, uma maneira de adicionar um comportamento customizados ao
acessar ou modificar um objeto. Duas das funções principais são get
e set
utilizadas para recuperar o valor de
uma propriedade e alterar/definir uma propriedade e seu valor respectivamente.
const obj = {
name: "Marcelo",
age: 20
}
const objProxy = new Proxy(obj, {
// target é o objeto original ao qual foi criado o proxy (obj)
// propertie é a propriedade que estamos tentandop acessar (name ou age)
get: (target, propertie) => {
console.log(`Acessando a propriedade ${propertie}`)
return target[propertie]
},
// target é o objeto original ao qual foi criado o proxy (obj)
// propertie é a propriedade que estamos tentandop acessar (name ou age)
// value é o novo valor que será atribuida a propriedade propertie
set: (target, propertie, value) => {
console.log(`Alterando o valor da propriedade ${propertie}`)
target[propertie] = value
}
})
As funções get
e set
serão executadas toda vez que tentarmos acessar ou alterar uma propriedade a partir do
proxy criado, e podemos definir qualquer tipo de lógica para esse Proxy.
objProxy.name // Acessando a propriedade name Marcelo
objProxy.age = 25 // Alterando o valor da propriedade age 25
O funcionamento do Proxy do ES6 é a base do funcionamento da reatividade no Vue 3 implementada com algumas funções
fornecidas pela Composition API
do VueJS 3.0.
reactive
Utilizado quando precisamos adicionar reatividade em um objeto natural qualquer que tivermos, reactive
cria um wrapper
proxy para esse objeto, a partir dai podemos trabalhar apenas com o objeto proxy para termos um comportamento reativo.
import { reactive } from "vue"
const state = {
userName: "Marcelo",
userAge: 23
}
const stateProxy = reactive(state)
// OU
const statePx = reactive({
userName: "Marcelo",
userAge: 23
})
Desta forma o stateProxy
estará com comportamento reativo e qualquer alteração dos dados será refletido onde for
utilizado esse objeto, uma alteração feita pelo proxy resultará em uma alteração no objeto original.
ref
Cria um objeto ref
com comportamento reativo a partir de um valor primitivo ou array, esse objeto tem um única
propriedade chamada value
que contém o valor definido, se um objeto for passado como valor, será criado um proxy
com a função reactive
e esse proxy será atribuído ao value
da ref
que criamos.
import { ref } from "vue"
const age = ref(23)
console.log(age.value) // 23
console.log(age) // RefImpl {
// __v_isRef: true
// _rawValue: 23
// _shallow: false
// _value: 23
// value: 23
// __proto__: Object
// }
const state = ref({ age: 23 })
console.log(state.value) // Proxy {
// [[Handler]]: Object
// [[Target]]: Object
// age: 23
// __proto__: Object
// [[IsRevoked]]: false
// }
console.log(state.value.age) // 23
toRef
Podemos utilizar toRef
para criar um ref
a partir de uma propriedade de um objeto proxy reactive
, ou seja,
que foi criado com a função reactive
, esse novo ref
mantém a conexão com o proxy original, então caso haja uma
alteração em qualquer um dos objetos essa alteração será refletida no outro objeto.
import { reactive, toRef } from "vue"
const objProxy = reactive({ userName: "Marcelo", userAge: 23 })
const userName = toRef(objProxy, "userName")
console.log(userName.value) // Marcelo
console.log(userName) // ObjectRefImpl {
// __v_isRef: true
// _key: "userName"
// _object: Proxy - Referência ao objeto proxy de origem -
// [[Handler]]: Object
// [[Target]]: Object
// [[IsRevoked]]: false
// value: "Marcelo"
// __proto__: Object
// }
userName.value = "João"
console.log(objProxy.userName) // João
toRefs
toRefs
é semelhante ao toRef
, com toRefs
podemos passar um objeto proxy rective
e irá ser criado um
objeto simples com cada propriedade existente do proxy sendo um ref.
Se aplicarmos destructuring a um proxy reactive perdemos a reatividade desses dados.
Mas utilizando toRefs
podemos aplicar destructuring e manter a característica de reatividade
dos dados.
import { reactive, toRefs } from "vue"
const objProxy = reactive({ userName: "Marcelo", userAge: 23 })
const refsObject = toRefs(objProxy)
console.log(refsObject) // {
// userAge: ObjectRefImpl
// __v_isRef: true
// _key: "userAge"
// _object: Proxy {userName: "Marcelo", userAge: 23}
// value: 23
//
// userName: ObjectRefImpl
// __v_isRef: true
// _key: "userName"
// _object: Proxy {userName: "Marcelo", userAge: 23}
// value: "Marcelo"
// }
const { userName, userAge } = toRefs(objProxy)
console.log(userName) // ObjectRefImpl {
// __v_isRef: true
// _key: "userName"
// _object: Proxy {userName: "Marcelo", userAge: 23}
// value: "Marcelo"
// }
console.log(userAge) // ObjectRefImpl {
// __v_isRef: true
// _key: "userAge"
// _object: Proxy {userName: "Marcelo", userAge: 23}
// value: 23
// }
Referências:
- https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- https://v3.vuejs.org/api/basic-reactivity.html
- https://v3.vuejs.org/api/refs-api.html