• nextTick


     nextTick

     

    <template>
        <view class="app">
            <view ref="msgview" style="color:red;">{{msg}}</view>
            <view v-if="msg1">Message got outside $nextTick: {{msg1}}</view>
            <view v-if="msg2">Message got inside $nextTick: {{msg2}}</view>
            <view v-if="msg3">Message got outside $nextTick: {{msg3}}</view>
            <button @click="changeMsg">
                Change the Message
            </button>
        </view>
    </template>
    
    <script>
        export default {
            data() {
                return {
                    msg: 'Hello Vue.',
                    msg1: '1',
                    msg2: '2',
                    msg3: '3'
                };
            },
            methods: {
                changeMsg() {
                    this.msg = "Hello world.";
                    this.msg1 = this.$refs.msgDiv.innerHTML;
                    console.log(this.$refs)
                    this.$nextTick(() => {
                        this.msg2 = this.$refs.msgDiv.innerHTML;
                    })
                    this.msg3 = this.$refs.msgDiv.innerHTML;
                }
            },
        }
    </script>

     图例

     Hello world.

     Message got outside $nextTick : Hello Vue

     Message got inside $nextTick Hello world

     Message got outside $nextTick: Hello Vue.

    由上可知,msg1和msg3显示的内容还是变换之前的,而msg2显示的内容是变换之后的。

    应用场景 :

        在vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,在created()钩子函数执行的时候DOM其实并未进行任何渲染, 而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js的代码放进Vue.nextTick()的回调函数中。与之对应的是mounted()钩子函数,因为该钩子函 数执行时所有的DOM挂载和渲染都已完成,此时在钩子函数中进行任何DOM操作都不会有问题。

        Vue异步执行DOM更新。只要观察到数据变化,Vue将开启一个队列,并缓冲在同一时间循环中发生的所有数据改变。如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作上非常重要。然后,在下一个的事件循环“tick”中,Vue刷新队列并执行实际已去重的工作。

        Vue在内部尝试使用对异步队列使用原生的promise.then和MessageChannel,如果执行环境不支持,会采用setTimeout(fn,0)代替。

    首先,先了解 nextTick 中定义的三个重要变量

    • callbacks

              用来存储所有需要执行的回调函数

    • pending

              用来标志是否正在执行回调函数

    • timerFunc

             用来触发执行回调函数

    接下来,了解 nextTickHandler() 函数。 

    function nextTickHandler () {
        pending = false
        const copies = callbacks.slice(0)
        callbacks.length = 0
        for (let i = 0; i < copies.length; i++) {
          copies[i]()
        }
      }
    <div id=app>
      <div id="div" v-if="showDiv">我是显示文本</div>
      <button @click="showAndGetText">获取内容</button >
    </div>
    <script>
    var app = new Vue({
      el: '#app',
      data () {
        return {
          showDiv : false
        },
        methods: {
          showAndGetText () {
            this.showDiv  = true
            let text = document.getElementById('div').innerHTML
            console.log(text)
          }
        }
      }
    })
    </script>

    这段代码并不难理解,但是控制台回抛出一个 innerHTML of null 的错误,因为此时页面并未完成渲染,它并没有获取到div元素,这里涉及到一个Vue的重要概念:异步更新队列。

    Vue在观察到数据变化时并不是直接更新DOM,而是开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。在缓冲时会去除重复的数据,这样避免了不必要的计算和DOM操作。然后,在下一个时间循环Tick中,Vue刷新队列并执行已去重的工作。所以,如果你用一个for循环来动态改变数据100次,其实它只会应用最后一次改变,如果没有这种机制,DOM就要重绘100次,这是我们不愿意看到的。

    知道了Vue异步更新DOM的原理之后,上面的现象就不难理解了,事实上在下面语句执行时,,div仍然是没有被创建出来的,下面的

    xthis.showDiv = true 
    let text =document.getElementById('div').innerHTML console.log(text);

    仍然读取的是这一次事件循环的DOM,而实际上在这一次事件循环中,DOM并没有更新,所以是读取不到的。我们需要等下一个Vue事件循环,DOM更新完成后再读取,就可以读取到了

  • 相关阅读:
    分布式文件存储系统-HDFS
    Java中的常用类
    分布式协调框架ZooKeeper
    【Redis】Redis慢查询
    kubectl工具管理应用
    kubectl命令管理
    To check your hdfs port use the following command in linux
    hadoop HDFS常用文件操作命令
    在scala中关于split以及正则表达式
    pandas入门之Series
  • 原文地址:https://www.cnblogs.com/zhishiyv/p/11878139.html
Copyright © 2020-2023  润新知