Série de código-fonte de análise-Vue.set / vm.$set
Detailed
Artigo Diretório
Descrição da função e do conceito
Adicione uma propriedade ao objeto responsivo e certifique-se de que essa nova propriedade também seja responsiva e acione a atualização da visualização. Deve ser usado para adicionar novas propriedades ao objeto reativo, porque o Vue não pode detectar novas propriedades comuns (como this.myObject.newProperty = 'hi')
Limitações Não é
permitido adicionar dinamicamente atributos responsivos de nível raiz. tal como:
// 错误写法
this.$set(this, 'newkey', 1111)
// 正确写法
this.$set(this.obj, 'newkey', 111)
// 取值: this.obj.newkey => 111
resumo
Vue.set
E osvm.$set
métodos são realmente os mesmos, mas o texto não é o mesmo- O efeito é adicionar atributos dinamicamente à página, e os atributos adicionados dinamicamente também são atributos responsivos
Por que usar set para adicionar atributos responsivos
Olhe para o princípio responsivo vue: o princípio de ligação de dados bidirecional vue
pode ser visto na verdade confiar em um responsivo Object.defineProperty
e Object.defineProperty
apenas ouvir um dos atributos de um objeto, se houver várias propriedades, precisa ouvir
Veja uma demonstração para entender:
var data = {
}
Object.defineProperty(data, 'data1', {
get: function() {
console.log('get data1')
return this.value
},
set: function(newVal) {
console.log('set data1')
this.value = newVal
}
})
data.data1 = 111 // 将会打印 set data1
console.log(data.data1) // 先打印 get data1 然后才是 111
data.data2 = 222 // 无打印,无报错
console.log(data.data2) // 直接打印222。表示没有进过 `Object.defineProperty`
Comece a olhar para o código-fonte
Aqui está uma demonstração para depuração
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
addData: {
}
}
})
debugger
app.$set(app.addData, 'newkey', 1111)
</script>
O primeiro a inserir os $set
métodos da vez, primeiro veio para a seção de valor padrão, desta vez para retornar um valor nulo, após o retorno, reinserir $set
é a parte que precisamos depurar
No modo de depuração, insira o método definido
Linha 2 1081 um método para detectar o tipo de dados do nó alvo, ou seja, $set
a detecção do primeiro parâmetro
- 1085-1089 determinar o tipo de array.Afinal, como o tipo especial
Object.defindPropety
não pode detectar a mudança do array, a mudança do array é atualizada manualmente. - 1090-1093 é determinar se o atributo já existe antes, e não há necessidade de repetir o monitoramento se ele existir
- 1095--1100 é determinar o nó raiz não pode
this.data
ser adicionado diretamente aos dados - Observe que a variável de 1094 linhas
ob
é observada (observador) para breve. Também é usado para determinar se a variável foi monitorada - Os valores que foram monitorados e não precisam ser monitorados repetidamente serão devolvidos diretamente aos correspondentes
val
. Ele também$set
retorna um valor de retorno do atual - Se o objeto for novo, ele foi para o
defineReactive$$1
método de 1106 linhas
Adicionar um defineReactive$$1
método de ouvinte
- 1021 inicializar a
new Dep
visualização a análise da análise de dep look é necessária. Isso envolve muitos dos seguintes processos. O csdn não suporta navegação hash, então você precisa deslizar manualmente para baixo e dar uma olhada ~ - 1023-1026 Determine se o objeto é legível e gravável
- 1019--1033 obter no objeto
get
eset
método de destino . - 1035 Há uma variável superficial em nosso código anterior nesta variável não existe
!shallow
isso é verdade. Portanto, a implementação de umobserve
método para visualizar a análise de observação csdn não suporta a navegação hash, você precisa deslizar manualmente para baixo sob o seu próprio para ver ~ - Depois de ler a
observe
análise acima , sabemosobserve
que propriedade para seu filho, o ciclismo adiciona a escuta. - A linha 1039 está ligada ao evento que obtém o valor do atributo.Ao obter o valor correspondente, eu
Dep.target
apenas o vi como um observador globalwatch
. Portanto, se houverdep.target
uma chamada de destino para odepend
método atual , que é doDep
herdado. Equivale a registrar um callback para assistir ao evento (que é estimadowatch
ecomputed
um prenúncio enterrado) set
Método da linha de partida 1052 . Também inicie o seu própriogetter
para obter o valor atual dentro- Linha 1069, se estivermos copiando um objeto de novo, ele tem que adicionar novamente um armazenamento de dados para esses objetos em um loop, se já foi mantido, pode ser pulado, que é o código acima
- As últimas 1070 linhas são chamadas após o conjunto
dep.notify()
. Ele armazena a hora em que a atualização do objeto correspondente precisa ser disparada (modo de observador de assinatura). Agora que o valor está atualizado, ele é acionado para a função de inscrição relevante (o relógio também é acionado neste momento e a visualização também é atualizada neste momento) . E temos que obter o valor definido antes da frente, para que oswatch
métodos internosnewVal
eoldVal
estejam sendo registrados neste momento - Finalmente, o valor atual é retornado
$set
e a execução do método termina
análise dep
O código dep não é muito longo. dep é equivalente a uma central de assinaturas
- Na linha 717, você pode ver que cada depósito tem um ID correspondente e é auto-crescente
- A linha 718 pode ser considerada um centro de eventos, e todo o monitoramento é armazenado aqui
- Você pode ver que existem vários métodos no protótipo do dep
addSub
removeSub
depend
notify
. Eles são todos usados para operar o monitor correspondente, adicionar / excluir, encontrar a dependência correspondente e notificar esses métodos - 725 linha
Dep.target
tem notas muito detalhadas, visualizador globalmente único
O núcleo é lembrar alguns addSub
removeSub
depend
notify
métodos. Em seguida, continue a olhar para o código agora
observar a análise
Notas especialmente pensativas
Tente criar uma instância do observador para um valor,
tente criar valor para que a instância do observador
retorne o novo observador se observado com sucesso,
se observado com sucesso, o novo visualizador é retornado
ou o observador existente se o valor já tiver um.
Ou Observador existente de (se o valor já contiver um)
-
Parece
value.__ob__
se houver, então essa propriedade teria sido um observador, e este é o nosso$set
primeiro passo em um julgamento sobre__ob__
o -
Em seguida, diferencie a matriz, a matriz não tem observadores
-
Principalmente para ver a linha 1003, crie uma nova
new Observe
nota de observador na capital, não no objeto atual -
new Observe
Na Figura 2 abaixo, não vou falar sobre isso separadamente. -
926 linhas. Para
__ob__
adicionar propriedades, não se engane e__ob__
defina-o como um tipo não enumerável. Para obter detalhes, você pode ver o código que vai em 926 -
927-933 são todos para operações de array
-
Linha 935, o método de caminhada do objeto atual. Colando o código diretamente, podemos ver que é um loop, percorrendo nosso objeto uma vez e chamando-o para cada objeto
defineReactive$$1
. Como você pode ver, este método só será chamado se o valor for um tipo de objeto. -
Uma vez que é chamado
defineReactive$$1
. Então, uma recursão é formada aqui, a cabeça da recursão é parar de chamar quando o atributo não for mais um objetodefineReactive$$1
. -
Depois de ver isso, a próxima etapa deve voltar para adicionar um método para ouvir a linha 1035 de defineReactive $$
/**
* Walk through all properties and convert them into
* getter/setters. This method should only be called when
* value type is Object.
*/
Observer.prototype.walk = function walk(obj) {
var keys = Object.keys(obj)
for (var i = 0; i < keys.length; i++) {
defineReactive$$1(obj, keys[i])
}
}
Resumindo
-
O princípio responsivo vue depende
Object.defindPropety
dos métodosget
eset
, respectivamente, nesses dois métodos para acionar o evento correspondente -
Por causa do JS e das
Object.defindPropety
restrições que não podem ser adicionadas dinamicamente, precisamos monitorar a propriedade, então devemos usarVue.set()
o método -
Vue.set()
O interior do método é um processo de processamento cíclico. Se o novo monitor atual for um objeto, ele continuará a se chamar para formar uma recursão até que o último subatributo seja um数组/非对象类型
parâmetro, a recursão termina e, em seguida, adiciona um monitor para você mesmo, no monitor Ele irá disparar outros métodos relacionados (eventos registrados no Dep serão disparados). Forme nossa ligação de dados bidirecional comum -
Uma vez que a
Object.defindPropety
mudança só pode monitorar o objeto, então o valor de um índice específico dentro da mudança do array não está escutando, então deve ser usadoVue.set
para acionar manualmente uma atualização, desta vezVue.set
apenas faça o valor atualizado e não repetirá o monitoramento de Novo Aumento
Artigo original primeiro: Analise o código-fonte series-Vue.set / vm.$set
Explicação detalhada Este é o novo endereço do blog, você pode dar uma olhada se estiver interessado