聊聊面试常考的nextTick

浅聊一下

临近年关,许多小伙伴归心似箭,导致有些公司正在急招干活的人,所以面试机会非常的多,那么我们就来聊聊面试中常考的nextTick

nextTick详解

要详解nextTick,就不得不走我们的三部曲:

  1. 什么是nextTick?
  2. 为什么要用nextTick?
  3. 如何手写nextTick?

什么是nextTick?

nextTick 是 Vue.js 提供的一个异步方法,用于在 DOM 更新后执行延迟回调。它可以让我们在下次 DOM 更新循环结束之后执行一些操作。

什么意思?nextTick在DOM更新以后执行回调函数,起到了等待DOM渲染完成的作用

我们来看看下面的例子:

这里我们暂且先不使用nextTick

js 复制代码
<template>
  <div>
    <p ref="refP">消息:{{message}}</p>
  </div>
</template>
<script setup>
import {ref} from 'vue'
const message = ref('Hello World')
const refP = ref(null)
console.log(refP.value);//
</script>

掘友们猜猜,这console.log()到底打印的是个什么玩意?

打印了一个null,因为在vue的生命周期里面,setup是最先执行的

此时,当我们的console.log()执行的时候,template甚至都还没有挂载,refP就当然为null了

加上nextTick

js 复制代码
nextTick(()=>{
  console.log(refP.value);
})

nextTick保证在渲染完成以后再调用里面的函数,此时页面已经渲染完毕,打印<p ref="refP">消息:{{message}}</p>

为什么要使用nextTick?

我们从一个应用场景上来分析为什么需要使用nextTick...

这里有一个可以滚动的列表,有一个按钮,每当我点击这个按钮,都给我的列表添加十条数据,并且自动滚动到最后一个li节点,这里我并没有使用nextTick

js 复制代码
<template>
    <div>
        <button @click="updateList">更新列表</button>
        <ul>
            <li v-for="item in list">{{item}}</li>
        </ul>
    </div>
</template>
<script setup>
import { nextTick,ref } from 'vue';
import {myNextTick} from '../components/nextTick'
const list = ref(new Array(20).fill(0))
const updateList = ()=>{
    list.value.push(...new Array(10).fill(1))
    const liItem = document.querySelector('li:last-child')
    liItem.scrollIntoView({behavior:'smooth'})
}
</script>
<style lang="css" scoped>
li{
    height: 100px;
    margin: 10px;
    background: red;
}
</style>

当我点击更新以后:

按道理,我们应该是滚动到最后一个1的,但是这里却滚动到了最后一个0,为什么呢?因为当我点击更新触发updateList方法的时候,DOM改变,而这个方法并不会等到DOM渲染完毕以后再执行,所以里面取到的最后一个li结点是0...

当我们使用上nextTick

js 复制代码
const updateList = ()=>{
    list.value.push(...new Array(10).fill(1))
    
    nextTick(()=>{
        const liItem = document.querySelector('li:last-child')
        liItem.scrollIntoView({behavior:'smooth'})
    })
}

看,nextTick保证了我们的方法在DOM渲染完毕以后再调用,来到了我们的最后一个li结点

怎么手写一个nextTick?

我们先理清楚nextTick到底干了一个什么事:

nextTick监听DOM结构,当DOM渲染完成以后,调用函数

那这就好办了

js 复制代码
export function myNextTick(fn){
   let app = document.getElementById('app')
   var observerOptions = {
      attributes: true,//观察属性变动
      childList: true,//观察目标子节点的变化,是否有添加或删除
      subtree: true//观察后代节点,默认为false
   }
   //创建一个DOM监听器,让fn()在DOM更新完成时触发
   let observer = new MutationObserver((el)=>{
    //当被监听的DOM更新完成时,改回调会触发
        fn()
   })

   observer.observe(app,observerOptions)
}

函数接受一个参数fn,表示需要在DOM更新后执行的函数。函数内部首先通过getElementById方法获取到id为'app'的DOM元素,并创建了一个MutationObserver实例用于监听该元素的变化。监听选项包括观察属性变动、目标子节点的变化以及后代节点的变化。当被监听的DOM更新完成后,回调函数fn会被执行。最后通过observer.observe方法将回调函数与目标元素关联起来,实现监听功能。

效果:

结尾

分享完毕,在放假的时候也要好好准备面试...

相关推荐
软件技术NINI7 分钟前
html css网页制作成品——HTML+CSS盐津铺子网页设计(5页)附源码
前端·css·html
mapbar_front1 小时前
面试问题—我的问题问完了,你还有什么想问我的吗?
前端·面试
倔强青铜三1 小时前
苦练Python第67天:光速读取任意行,linecache模块解锁文件处理新姿势
人工智能·python·面试
quweiie2 小时前
thinkphp8+layui多图上传,带删除\排序功能
前端·javascript·layui
李鸿耀2 小时前
React 项目 SVG 图标太难管?用这套自动化方案一键搞定!
前端
闲蛋小超人笑嘻嘻2 小时前
树形结构渲染 + 选择(Vue3 + ElementPlus)
前端·javascript·vue.js
我是华为OD~HR~栗栗呀2 小时前
华为od-21届考研-C++面经
java·c语言·c++·python·华为od·华为·面试
叶梅树2 小时前
从零构建A股量化交易工具:基于Qlib的全栈系统指南
前端·后端·算法
巴博尔2 小时前
uniapp的IOS中首次进入,无网络问题
前端·javascript·ios·uni-app
焚 城2 小时前
UniApp 实现双语功能
javascript·vue.js·uni-app