我阅读了文档,但我无法理解。我知道什么数据,计算,观察,方法,但nextTick()
在vuejs中使用的是什么?
答案 0 :(得分:75)
nextTick允许您在更改数据后执行某些操作,并且VueJS已根据您的数据更改更新了DOM,但在浏览器在页面上更改了这些更改之前。
通常,devs use native JavaScript function setTimeout可以实现类似的行为。但是,使用setTimeout
放弃对浏览器的控制权,然后通过回调将控制权交给您。
比方说,你改变了一些数据。 Vue根据数据更新DOM。请注意,浏览器尚未将DOM更改呈现给屏幕。如果您使用nextTick
,则会立即调用您的回调。然后,浏览器更新页面。如果您使用setTimeout
,则只会立即调用您的回调。
您可以通过创建如下所示的小组件来可视化此行为:
<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>
运行本地服务器。您将看到正在显示消息Three
。
现在,将您的this.$nextTick
替换为setTimeout
setTimeout(() => {
this.msg = 'Three';
}, 0);
重新加载浏览器。在看到Two
之前,您会看到Three
。
将此小提琴检查到see it live
那是因为,Vue将DOM更新为Two
,控制了浏览器。浏览器显示Two
。然后,调用你的回调。 Vue将DOM更新为Three
。哪个浏览器再次显示。
nextTick
。 Vue将DOM更新为Two
。叫你的回调。 Vue将DOM更新为Three
。然后控制浏览器。并且,浏览器显示Three
。
希望很清楚。
要了解Vue如何实现这一点,您需要了解Event Loop和microtasks的概念。
一旦您明确了这些概念(呃),请检查source code for nextTick。
答案 1 :(得分:8)
下一个Tick基本上允许你在vue重新渲染组件之后运行一些代码,当你对一个被动属性(数据)做了一些更改。
// 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.
})
来自Vue.js文档:
将回调推迟到下一个DOM更新周期后执行。在更改了一些数据以等待DOM更新后立即使用它。
详细了解here。
答案 2 :(得分:5)
为了让Pranshat回答有关使用nextTick和setTimeout之间的区别,更明确一点,我已经分享了他的小提琴: here
mounted() {
this.one = "One";
setTimeout(() => {
this.two = "Two"
}, 0);
//this.$nextTick(()=>{
//this.two = "Two"
//})}
你可以在小提琴中看到,当使用setTimeOut时,一旦组件被安装,初始数据会非常短暂地闪烁,然后再适应变化。然而,当使用nextTick时,数据在渲染到浏览器之前被劫持,更改。因此,浏览器显示更新的数据,甚至不知道旧的。 希望一举清除这两个概念。
答案 3 :(得分:2)
我已经创建了一个有用的演示,我们可以在 Vuejs 中使用 nextTick 的情况下,如果您想在 DOM 更新后立即更新或运行某些内容,请参阅 addMessage 函数,其中我正在调用另一个函数,其中我正在使用 nextTick 函数更新滚动以查看最新消息。
<!DOCTYPE html>
<html>
<head>
<title>CDN VUE 3</title>
</head>
<body>
<div id="app">
<div ref="scrolledList" style="height: 100px; width: 150px; border:1px solid red; overflow: auto; margin-bottom: 15px; padding: 5px;">
<ul ref="scrolledHeight" style="margin: 0; padding: 0;">
<li v-for="msg in messages">
{{msg}}
</li>
</ul>
</div>
<input type="text" placeholder="Add Message" v-model="message" />
<button @click="addMessage" @keyup.enter="addMessage"> Add Message</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data() {
return {
message: '',
messages: [1,2,3,4,5,6,7,8,9,10]
}
},
mounted() {
this.updateScrollNextTick()
},
methods: {
addMessage() {
if(this.message == ''){
return
}
this.messages.push(this.message)
this.message = ""
this.updateScrollNextTick()
},
updateScrollNextTick () {
this.$nextTick( () => {
let scrolledHeight = this.$refs.scrolledHeight.clientHeight
this.$refs.scrolledList.scrollTo({
behavior: 'smooth',
top: scrolledHeight
})
})
}
},
})
.mount("#app")
</script>
</body>
</html>
答案 4 :(得分:1)
Vue文档说:
Vue.nextTick([回调,上下文])
推迟下一个DOM更新周期后执行的回调。采用 在您更改了一些数据以等待DOM之后 更新。
嗯...,如果刚开始觉得很吓人,请不要担心,我会尽力解释得尽可能简单。但是首先,您应该知道两件事:
它的用法很少见。就像其中的一张银色魔术卡一样。我已经编写了几个Vue
应用程序,并且一次或两次遇到了nextTick()。
一旦您看到了一些实际的用例,就更容易理解。有了这个主意,恐惧就会消失,并且您会得到一个方便的工具。
那就去吧。
我们是程序员,不是吗?我们将使用我们钟爱的分而治之的方法尝试一点一点地翻译.nextTick()
的描述。它始于:
推迟回调
好的,现在我们知道它接受了回调。所以看起来像这样:
Vue.nextTick(function () {
// do something cool
});
太好了。此回调被延迟(这就是千禧一代所说的延迟),直到…
下一个DOM更新周期。
好的。我们知道 Vue异步执行DOM更新。它具有一种将这些更新“存储”到需要应用它们的方式。它创建更新队列,并在需要时刷新它。然后,对DOM进行“修补”并更新为最新版本。
什么?
让我再试一次:假设您的组件确实完成了一些必不可少的事情,例如this.potatoAmount = 3.
Vue不会自动重新渲染该组件(以及DOM)。它将排队进行所需的修改。然后,在下一个“滴答声”中(如在时钟中),刷新队列,并应用更新。多田!
好吧!因此,我们知道我们可以使用nextTick()
传递一个回调函数,该函数在设置数据并更新DOM后 后立即执行。
正如我之前所说的...并不经常。我不会提到的“数据流”方法可以驱动Vue,React和Google的另一种方法,这在大多数情况下都是不必要的。但是,有时我们需要等待某些元素在DOM中出现/消失/被修改。这是nextTick派上用场的时候。
更改某些数据以等待DOM后立即使用它 更新。
是的!这是Vue文档提供给我们的最后一个定义。在回调中,DOM已更新,因此我们可以与它的“最新”版本进行交互。
证明
好的,好的。查看控制台,您会看到我们的数据值仅在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>
用例
让我们尝试为nextTick
定义一些有用的用例。
想象一下,在安装组件时需要执行一些操作。但!不仅是组件。您还需要等待,直到所有子级都已安装并在DOM中可用为止。该死的!我们安装的挂钩不能保证整个组件树都能呈现。
如果只有我们有一个工具可以等待下一个DOM更新周期……
哈哈:
mounted() {
this.$nextTick(() => {
// The whole view is rendered, so I can safely access or query
// the DOM. ¯\_(ツ)_/¯
})
}
简而言之
因此:nextTick
是在设置数据和更新DOM之后执行函数的一种简便方法。
您需要等待DOM,也许是因为您需要执行一些转换,还是需要等待外部库加载其内容?然后使用nextTick。
某些人还在其单元测试中使用nextTick,以确保已更新数据。这样,他们可以测试组件的“更新版本”。
Vue.nextTick()或vm。$ nextTick()吗?
别担心。两者(几乎)相同。 Vue.nextTick()
是指全局API方法,而vm.$nextTick()
是实例方法。唯一的区别是vm.$nextTick
不接受上下文作为第二个参数。它始终绑定到this
(也称为实例本身)。
最后一点凉意
请注意,nextTick
返回了Promise
,因此我们可以对async/await
进行全面介绍,并改进示例:
async mounted () {
this.message = 'updated'
console.log(this.$el.textContent) // 'not updated'
await this.$nextTick()
console.log(this.$el.textContent) // 'updated'
}
The content has been taken from由AdriàFontcuberta