O uso e o princípio de Vue.set (análise da série de código-fonte)

Série de código-fonte de análise-Vue.set / vm.$setDetailed

Descrição da função e do conceito

Documento oficial: Vue-set

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.setE os vm.$setmé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.definePropertyapenas 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 $setmé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, $seta detecção do primeiro parâmetro

  • 1085-1089 determinar o tipo de array.Afinal, como o tipo especial Object.defindPropetynã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.dataser 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 $setretorna um valor de retorno do atual
  • Se o objeto for novo, ele foi para o defineReactive$$1método de 1106 linhas

Adicionar um defineReactive$$1mé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 gete setmétodo de destino .
  • 1035 Há uma variável superficial em nosso código anterior nesta variável não existe !shallowisso é verdade. Portanto, a implementação de um observemé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 observeanálise acima , sabemos observeque 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.targetapenas o vi como um observador global watch. Portanto, se houver dep.targetuma chamada de destino para o dependmétodo atual , que é do Depherdado. Equivale a registrar um callback para assistir ao evento (que é estimado watche computedum prenúncio enterrado)
  • setMétodo da linha de partida 1052 . Também inicie o seu próprio getterpara 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 os watchmétodos internos newVale oldValestejam sendo registrados neste momento
  • Finalmente, o valor atual é retornado $sete 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.targettem notas muito detalhadas, visualizador globalmente único

O núcleo é lembrar alguns addSub removeSub depend notifymé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 $setprimeiro 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 Observenota 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 objeto defineReactive$$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.defindPropetydos métodos gete set, respectivamente, nesses dois métodos para acionar o evento correspondente

  • Por causa do JS e das Object.defindPropetyrestrições que não podem ser adicionadas dinamicamente, precisamos monitorar a propriedade, então devemos usar Vue.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.defindPropetymudanç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 usado Vue.setpara acionar manualmente uma atualização, desta vez Vue.setapenas 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.$setExplicação detalhada Este é o novo endereço do blog, você pode dar uma olhada se estiver interessado

Acho que você gosta

Origin blog.csdn.net/Jioho_chen/article/details/107005845
Recomendado
Clasificación