API de Reatividade: Avançado
shallowRef()
Versão superficial de ref()
.
Tipo
tsfunction shallowRef<T>(value: T): ShallowRef<T> interface ShallowRef<T> { value: T }
Detalhes
Ao contrário de
ref()
, o valor interno duma referência superficial é armazenado e exposto como é, e não será profundamente reativa. Apenas o acesso de.value
é reativo.shallowRef()
é normalmente usado para otimizações de desempenho de grandes estruturas de dados ou integração com sistemas externos de gestão de estado.Exemplo
jsconst state = shallowRef({ count: 1 }) // NÃO aciona mudança state.value.count = 2 // aciona mudança state.value = { count: 2 }
Consulte também:
triggerRef()
Força o acionamento de efeitos que dependem duma referência superficial. Isso é normalmente usado depois de fazer-se mutações profundas no valor interno duma referência superficial.
Tipo
tsfunction triggerRef(ref: ShallowRef): void
Exemplo
jsconst shallow = shallowRef({ greet: 'Hello, world' }) // Regista "Hello, world" uma vez para o primeiro ensaio watchEffect(() => { console.log(shallow.value.greet) }) // Isto não acionará o efeito porque a referência é superficial shallow.value.greet = 'Hello, universe' // Regista "Hello, universe" triggerRef(shallow)
customRef()
Cria uma referência personalizada com controlo explícito sobre o rastreio de dependência e acionamento de atualizações.
Tipo
tsfunction customRef<T>(factory: CustomRefFactory<T>): Ref<T> type CustomRefFactory<T> = ( track: () => void, trigger: () => void ) => { get: () => T set: (value: T) => void }
Detalhes
customRef()
espera uma função de fábrica, que recebe as funçõestrack
etrigger
como argumentos e deve retornar um objeto com os métodosget
eset
.Em geral,
track()
deve ser chamado dentro deget()
, etrigger()
deve ser chamado dentro deset()
. No entanto, temos controlo total sobre quando devem ser chamados ou se devem ser chamados.Exemplo
Criação duma referência de velocidade reduzida que apenas atualiza o valor após uma certa pausa após a última chamada definida:
jsimport { customRef } from 'vue' export function useDebouncedRef(value, delay = 200) { let timeout return customRef((track, trigger) => { return { get() { track() return value }, set(newValue) { clearTimeout(timeout) timeout = setTimeout(() => { value = newValue trigger() }, delay) } } }) }
Uso no componente:
vue<script setup> import { useDebouncedRef } from './debouncedRef' const text = useDebouncedRef('hello') </script> <template> <input v-model="text" /> </template>
shallowReactive()
Versão superficial de reactive()
.
Tipo
tsfunction shallowReactive<T extends object>(target: T): T
Detalhes
Ao contrário de
reactive()
, não existe conversão profunda: apenas as propriedades de nível raiz são reativas para um objeto reativo superficial. Os valores de propriedade são armazenados e expostos como são - isto também significa que as propriedades com valores de referência não serão desembrulhados automaticamente.Use com Cautela
Estruturas de dados superficiais devem ser usadas apenas para o estado de nível de raiz num componente. Evite encaixá-lo dentro dum objeto reativo profundo, visto que cria uma árvore com comportamento de reatividade inconsistente que pode ser difícil de entender e depurar.
Exemplo
jsconst state = shallowReactive({ foo: 1, nested: { bar: 2 } }) // a mutação das propriedades do próprio estado é reativa state.foo++ // ...mas não converte objetos encaixados isReactive(state.nested) // false // NÃO é reativo state.nested.bar++
shallowReadonly()
Versão superficial de readonly()
.
Tipo
tsfunction shallowReadonly<T extends object>(target: T): Readonly<T>
Detalhes
Ao contrário de
readonly()
, não existe conversão profunda: apenas propriedades de nível de raiz são tornadas de somente leitura. Os valores de propriedade são armazenados e expostos como são - isto também significa que as propriedades com valores de referência não serão desembrulhados automaticamente.Use com Cautela
Estruturas de dados rasas devem ser usadas apenas para o estado de nível de raiz num componente. Evite encaixá-lo dentro dum objeto reativo profundo, visto que cria uma árvore com comportamento de reatividade inconsistente que pode ser difícil de entender e depurar.
Exemplo
jsconst state = shallowReadonly({ foo: 1, nested: { bar: 2 } }) // a mutação das propriedades do próprio estado falhará state.foo++ // ...mas funciona sobre objetos encaixados isReadonly(state.nested) // false // funciona state.nested.bar++
toRaw()
Retorna o puro, objeto original duma delegação criada pela Vue.
Tipo
tsfunction toRaw<T>(proxy: T): T
Detalhes
toRaw()
pode retornar o objeto original a partir das delegações criadas porreactive()
,readonly()
,shallowReactive()
oushallowReadonly()
.Isto é uma escotilha de fuga que pode ser usada para ler temporariamente sem ficar sujeito ao acesso da delegação ou custos de rastreio ou escrever sem acionar mudanças. Não é recomendado segurar uma referência persistente ao objeto original. Use com cautela.
Exemplo
jsconst foo = {} const reactiveFoo = reactive(foo) console.log(toRaw(reactiveFoo) === foo) // true
markRaw()
Marca um objeto para nunca ser convertido à uma delegação. Retorna o próprio objeto.
Tipo
tsfunction markRaw<T extends object>(value: T): T
Exemplo
jsconst foo = markRaw({}) console.log(isReactive(reactive(foo))) // false // também funciona quando encaixado dentro dos outros objetos reativos const bar = reactive({ foo }) console.log(isReactive(bar.foo)) // false
Use com Cautela
markRaw()
e as APIs superficiais tais comoshallowReactive()
permitem-nos abandonar seletivamente a conversão profunda reativa ou de somente leitura padrão e fixar objetos brutos não delegados no nosso grafo de estado. Eles podem ser usados por várias razões:Alguns valores simplesmente não deveriam ser reativos, por exemplo, uma instância de classe de terceiros complexa ou um objeto de componente Vue.
Ignorar a conversão de delegação pode fornecer melhorias de desempenho quando interpretamos grandes listas com fontes de dados imutáveis.
Eles são considerados avançados porque o puro abandono é apenas ao nível de raiz, então se definirmos um objeto puro não marcado encaixado num objeto reativo e então acessá-lo novamente, recebemos de volta a versão delegada. Isto pode conduzir à riscos de identidade - por exemplo, executar uma operação que depende da identidade do objeto porém usando ambas a pura e versão delegada do mesmo objeto:
jsconst foo = markRaw({ nested: {} }) const bar = reactive({ // apesar de `foo` ser marcada como pura, `foo.nested` não é. nested: foo.nested }) console.log(foo.nested === bar.nested) // false
Os riscos de identidade são em geral raros. No entanto, para usar adequadamente estas APIs enquanto evitar-se riscos de identidade com segurança exige um conhecimento sólido de como o sistema de reatividade funciona.
effectScope()
Cria um objeto de âmbito de efeito que pode capturar os efeitos reativos (por exemplo, propriedades computadas e observadores) criados dentro dela para que estes efeitos possam ser colocados juntos. Para casos de uso detalhados desta API, consulte seu RFC correspondente.
Tipo
tsfunction effectScope(detached?: boolean): EffectScope interface EffectScope { run<T>(fn: () => T): T | undefined // `undefined` se o âmbito estiver inativo stop(): void }
Exemplo
jsconst scope = effectScope() scope.run(() => { const doubled = computed(() => counter.value * 2) watch(doubled, () => console.log(doubled.value)) watchEffect(() => console.log('Count: ', doubled.value)) }) // colocar todos efeitos no âmbito scope.stop()
getCurrentScope()
Retorna o âmbito de efeito ativo atual, se existir um.
Tipo
tsfunction getCurrentScope(): EffectScope | undefined
onScopeDispose()
Regista uma função de resposta de despacho no âmbito de efeito ativo atual. A função de resposta será invocada quando o âmbito de efeito associado for parado.
Este método pode ser usado como uma substituição não associada ao componente de onUnmounted
nas funções de composição reutilizáveis, uma vez que a função setup()
de cada componente da Vue também é invocada num âmbito de efeito.
Tipo
tsfunction onScopeDispose(fn: () => void): void