O que é nextTick ou o que ele faz em VueJs

104

Eu li a documentação, mas não consigo entender. Eu sei o que os métodos de dados, calculados e observados fazem, mas para que serve nextTick()em vuejs?

hidar
fonte
17
O conceito principal a ser entendido é que o DOM é atualizado de forma assíncrona . Quando você altera um valor no Vue, a alteração não é imediatamente processada no DOM. Em vez disso, o Vue enfileira uma atualização do DOM e, em seguida, em um cronômetro, atualiza o DOM. Normalmente, isso acontece tão rápido que não faz diferença, mas, às vezes, você precisa atualizar o DOM renderizado após Vue tê-lo renderizado, o que você não pode fazer imediatamente em um método porque a atualização não aconteceu ainda. Nesses casos, você usaria nextTick. Documentado aqui .
Bert
Complementando o que @Bert disse em https://stackoverflow.com/q/47634258/9979046 acima, o nextTick () será usado em Testes de Unidade, quando você precisar verificar se existe um elemento no DOM (HTML), por exemplo, se você obtiver alguma informação sobre um pedido do Axios.
Oscar Alencar

Respostas:

139

nextTick permite que você faça algo depois de alterar os dados e o VueJS atualizar o DOM com base na alteração dos dados, mas antes que o navegador renderize as alterações na página.

Normalmente, os desenvolvedores usam a função JavaScript nativa setTimeout para atingir um comportamento semelhante. Mas, o uso setTimeoutcede o controle ao navegador antes de devolver o controle a você por meio do retorno de chamada.

Digamos que você alterou alguns dados. O Vue atualiza o DOM com base nos dados. Lembre-se de que as alterações do DOM ainda não foram renderizadas na tela pelo navegador. Se você usou nextTick, seu retorno de chamada será chamado agora. Em seguida, o navegador atualiza a página. Se você usou setTimeout, seu retorno de chamada seria chamado apenas agora.

Você pode visualizar esse comportamento criando um pequeno componente como o seguinte:

<template>
  <div class="hello">
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
        msg: 'One'
    }
  },
  mounted() {
      this.msg = 'Two';

      this.$nextTick(() => {
          this.msg = 'Three';
      });
  }
}
</script>

Execute seu servidor local. Você verá a mensagem Threesendo exibida.

Agora, substitua seu this.$nextTickporsetTimeout

setTimeout(() => {
    this.msg = 'Three';
}, 0);

Recarregue o navegador. Você vai ver Two, antes de ver Three.

Verifique este violino para vê-lo ao vivo

Isso porque, Vue atualizou o DOM para Two, deu o controle ao navegador. Navegador exibido Two. Em seguida, ligou para seu retorno de chamada. Vue atualizou o DOM para Three. Que o navegador exibiu novamente.

Com nextTick. Vue atualizou o DOM para Two. Ligou para seu retorno de chamada. Vue atualizou o DOM para Three. Em seguida, passou o controle para o navegador. E, o navegador exibido Three.

Espero que tenha ficado claro.

Para entender como o Vue implementa isso, você precisa entender o conceito de loop de eventos e microtarefas .

Depois de ter esses conceitos claros (er), verifique o código-fonte para nextTick .

Prashant
fonte
4
Uma coisa que não entendo é quando você diz, "vue atualiza os dados" você está se referindo à atualização feita com ex: this.name = 'foo'ou você está se referindo à injeção de elementos html na página?
hidar
Eu não vejo nenhum lugar na história desta questão onde ele diga "vue atualiza os dados" ... Ele diz "Vue atualiza DOM com base nos dados". O que significa que quando você define dados via this.name = 'foo'vue, atualiza o modelo de objeto do documento para refletir as alterações feitas nos dados com base no modelo e nas funções que você configura.
ADJenks
24

O conteúdo foi retirado de Por Adrià Fontcuberta

A documentação da Vue diz:

Vue.nextTick ([callback, contexto])

Adie o retorno de chamada a ser executado após o próximo ciclo de atualização do DOM. Use-o imediatamente após alterar alguns dados para aguardar a atualização do DOM.

Hmm ..., se parecer intimidante no começo, não se preocupe, vou tentar explicar da forma mais simples possível. Mas primeiro existem 2 coisas que você deve saber:

  1. Seu uso é incomum. Como uma daquelas cartas mágicas de prata. Eu escrevi vários Vueaplicativos e encontrei nextTick () uma ou duas vezes.

  2. É mais fácil entender depois de ver alguns casos de uso reais. Depois de ter a ideia, o medo irá embora e você terá uma ferramenta útil na mão.

Vamos em frente, então.

Compreendendo $ nextTick

Somos programadores, não somos? Usaremos nossa amada abordagem de dividir e conquistar para tentar traduzir a descrição .nextTick()pouco a pouco. Começa com:

Adie o retorno de chamada

Ok, agora sabemos que ele aceita um retorno de chamada. Então fica assim:

Vue.nextTick(function () {
  // do something cool
});

Ótimo. Este retorno de chamada é adiado (é assim que a geração do milênio diz atrasada) até ...

o próximo ciclo de atualização do DOM.

OK. Sabemos que o Vue realiza atualizações DOM de forma assíncrona . Apresenta uma forma de manter essas atualizações “armazenadas” até que seja necessário aplicá-las. Ele cria uma fila de atualizações e a libera quando necessário. Em seguida, o DOM é “corrigido” e atualizado para sua versão mais recente.

O que?

Deixe-me tentar novamente: imagine que seu componente faz algo realmente essencial e inteligente, como o this.potatoAmount = 3.Vue não renderiza novamente o componente (e, portanto, o DOM) automaticamente. Ele irá enfileirar a modificação necessária. Então, no próximo “tique” (como em um relógio), a fila é esvaziada e a atualização é aplicada. Tada!

OK! Portanto, sabemos que podemos usar nextTick()para passar uma função de retorno de chamada que é executada logo após os dados serem definidos e o DOM atualizado.

Como eu disse antes ... não com tanta frequência. A abordagem de “fluxo de dados” que impulsiona Vue, React e o outro do Google, que não vou mencionar, torna-a desnecessária na maioria das vezes. No entanto, às vezes precisamos esperar que alguns elementos apareçam / desapareçam / sejam modificados no DOM. É aí que nextTick se torna útil.

Use-o imediatamente após alterar alguns dados para aguardar a atualização do DOM.

Exatamente! Esta é a última definição que a Vue docs nos forneceu. Dentro de nosso retorno de chamada, o DOM foi atualizado para que possamos interagir com a versão “mais atualizada” dele.

Provar

Está bem, está bem. Consulte o console e você verá que o valor de nossos dados é atualizado apenas dentro do retorno de chamada de nextTick:

const example = Vue.component('example', {
  template: '<p>{{ message }}</p>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  mounted () {
    this.message = 'updated'

        console.log(
        'outside nextTick callback:', this.$el.textContent
    ) // => 'not updated'

    this.$nextTick(() => {
      console.log(
        'inside nextTick callback:', this.$el.textContent
      ) // => 'not updated'
    })
  }
})


new Vue({
  el: '#app',
    render: h => h(example)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.10/vue.js"></script>
<div id="app"></div>

Um caso de uso

Vamos tentar definir algum caso de uso útil para nextTick.

Imagine que você precisa realizar alguma ação quando um componente é montado. MAS! não apenas o componente. Você também precisa esperar até que todos os seus filhos estejam montados e disponíveis no DOM. Droga! Nosso gancho montado não garante que toda a árvore de componentes seja renderizada.

Se ao menos tivéssemos uma ferramenta para esperar pelo próximo ciclo de atualização do DOM ...

Hahaa:

mounted() {
  this.$nextTick(() => {
    // The whole view is rendered, so I can safely access or query
    // the DOM. ¯\_(ツ)_/¯
  })
}

Em poucas palavras

Portanto: nextTické uma maneira confortável de executar uma função depois que os dados foram configurados e o DOM foi atualizado.

Você precisa esperar pelo DOM, talvez porque você precise realizar alguma transformação ou precisa esperar que uma biblioteca externa carregue seu material? Em seguida, use nextTick.

Algumas pessoas também usam nextTick em seus testes de unidade como uma forma de garantir que os dados foram atualizados. Desta forma, eles podem testar a “versão atualizada” do componente.

Vue.nextTick () ou vm. $ NextTick ()?

Não se preocupe. Ambos são (quase) iguais. Vue.nextTick()refere-se ao método API global, enquanto vm.$nextTick()é um método de instância. A única diferença é que vm.$nextTicknão aceita um contexto como segundo parâmetro. Ele está sempre vinculado a this(também conhecido como a própria instância).

Um último pedaço de frescor

Observe que nextTickretorna um Promise, para que possamos ficar totalmente tranquilos async/awaite melhorar o exemplo:

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}
Humoyun Ahmad
fonte
2
Basta adicionar o Autor original e o link, no topo da "sua" explicação.
Renan Cidale
1
Que explicação incrível! Muito obrigado pelo seu tempo e esforço.
Muaath Alhaddad
16

Next Tick basicamente permite que você execute algum código, após o vue ter renderizado novamente o componente quando você tiver feito algumas alterações em uma propriedade reativa (dados).

// modify data
vm.msg = 'Hello'
// DOM not updated yet
Vue.nextTick(function () {
  // this function is called when vue has re-rendered the component.
})

// usage as a promise (2.1.0+, see note below)
Vue.nextTick()
  .then(function () {
      // this function is called when vue has re-rendered the component.
})

Da documentação do Vue.js:

Adie o retorno de chamada a ser executado após o próximo ciclo de atualização do DOM. Use-o imediatamente após alterar alguns dados para aguardar a atualização do DOM.

Leia mais sobre isso aqui .

Daksh Miglani
fonte
2
atualizá-lo como? isso é o que eu não entendo. se eu atualizar o vm.msg, o dom já está atualizado porque há um novo texto '' olá ".. então, como posso atualizá-lo novamente? você pode postar um violino com um exemplo, por
favor
ok, vou editar a resposta e tentar explicar melhor.
Daksh Miglani
@hidar, você pode usá-lo em situações em que precisa fazer várias atualizações, mas deseja renderizar explicitamente um ao outro em diferentes ciclos de dom
Daksh Miglani
Não é para permitir que você atualize o DOM em si, mas para fazer qualquer coisa com ele (seja atualizar, ler informações dele, etc) depois de ter sido afetado / modificado por mudanças feitas pelo Vue (porque você alterou um valor de propriedade reativa , etc).
zenw0lf
Esse foi um exemplo para simplificar.
Daksh Miglani
7

Para tornar a resposta de Pranshat sobre a diferença entre usar nextTick e setTimeout, mais explícita, bifurquei seu violino: aqui

mounted() {    
  this.one = "One";
 
  setTimeout(() => {
    this.two = "Two"
  }, 0);
  
  //this.$nextTick(()=>{
  //this.two = "Two"
  //})}

Você pode ver no violino que, ao usar setTimeOut, os dados iniciais piscam rapidamente assim que o componente é montado antes de adaptar a mudança. Considerando que, ao usar nextTick, os dados são sequestrados, alterados, antes de serem processados ​​para o navegador. Assim, o navegador mostra os dados atualizados sem qualquer conhecimento dos antigos. Espero que isso esclareça os dois conceitos de uma só vez.

Wale
fonte