前言
項目中乘陪,我們希望在html加載完成后獲取某個元素的寬度,把獲取寬度的方法寫在mounted函數(shù)里,會發(fā)現(xiàn)很多時候會取不到正確的寬度冰更,這是什么原因呢产徊?
js里有個渲染線程類似于java里邊的主線程,主線程按順序執(zhí)行代碼蜀细,執(zhí)行完才會有空去看看任務(wù)棧里邊有沒有任務(wù)需要執(zhí)行舟铜,有的話就拿來到主線程里邊執(zhí)行,setTimeout就把里邊的代碼放到任務(wù)棧中(類似于子線程)了奠衔,所以setTimeout里邊這部分代碼會在主線程執(zhí)行完才會執(zhí)行谆刨。
而此時我們可以替換掉看起來比較low的setTimeout(fn, 0),而是用vue里面提供的this.$nextTick()归斤,也就好比我們將打印輸出的代碼放在setTimeout(fn, 0)中痊夭。
例1
<template>
<section>
<div ref="hello">
<h1>Hello World ~</h1>
</div>
<el-button type="danger" @click="get">點擊</el-button>
</section>
</template>
<script>
export default {
methods: {
get() {
}
},
mounted() {
console.log(333);
console.log(this.$refs['hello']);
this.$nextTick(() => {
console.log(444);
console.log(this.$refs['hello']);
});
},
created() {
console.log(111);
console.log(this.$refs['hello']);
this.$nextTick(() => {
console.log(222);
console.log(this.$refs['hello']);
});
}
}
</script>
可以根據(jù)打印的順序看到,在created()鉤子函數(shù)執(zhí)行的時候DOM 其實并未進(jìn)行任何渲染脏里,而此時進(jìn)行DOM操作并無作用她我,而在created()里使用this.$nextTick()可以等待dom生成以后再來獲取dom對象
例2
<template>
<section>
<h1 ref="hello">{{ value }}</h1>
<el-button type="danger" @click="get">點擊</el-button>
</section>
</template>
<script>
export default {
data() {
return {
value: 'Hello World ~'
};
},
methods: {
get() {
this.value = '你好啊';
console.log(this.$refs['hello'].innerText);
this.$nextTick(() => {
console.log(this.$refs['hello'].innerText);
});
}
},
mounted() {
},
created() {
}
}
</script>
根據(jù)上面的例子可以看出,在方法里直接打印的話迫横, 由于dom元素還沒有更新番舆, 因此打印出來的還是未改變之前的值,而通過this.$nextTick()獲取到的值為dom更新之后的值