7-异步更新队列-nextTick的使用及应用

287 阅读1分钟

nextTick的使用

当你设置 vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

<body>
    <div id="app">
        <h3>{{ msg }}</h3>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                msg: 'tom'
            }
        })

        vm.msg = 'new msg';
        console.log(vm.$el.textContent);//tom

        Vue.nextTick(() => {
            console.log(vm.$el.textContent);//new msg
        })
    </script>
</body>

可以看到虽然我们已经对 vm.msg = 'new msg';进行更新,但是如果直接console.log(vm.$el.textContent);获取的还是原来的值,而通过使用Vue.nextTick(callback)我们可以准确的获取到我们想要的更新后的值。

nextTick应用

需求:在页面拉取一个接口,这个接口返回一些数据,这些数据是这个页面的一个浮层组件要依赖的,然后在接口一返回数据就展示了这个浮层组件,展示的同时,上报一些数据给后台(这些数据是父组件从接口拿的),这个时候,神奇的事情发生了,虽然拿到数据了,但是浮层展现的时候,这些数据还未更新到组件上去,上报失败。

解决:

<body>
    <div id="app">
        <App></App>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        const Pop = {
            data() {
                return {
                    isShow: false
                }
            },
            template: `
            <div v-if='isShow'>
                {{ msg }}
            </div>
            `,
            props: {
                msg: {
                    type: String,
                    default: ''
                }
            },
            methods: {
                show() {
                    this.isShow = true;
                    console.log(this.msg);
                }
            },
        }

        const App = {
            data() {
                return {
                    name: ''
                }
            },
            template: `
            <Pop :msg='name' ref='pop'></Pop>
            `,
            components: {
                Pop
            },
            created() {
                //模拟异步请求
                setTimeout(() => {
                    //数据更新
                    this.name = 'tom';
                    this.$nextTick(() => {
                        this.$refs.pop.show();
                    })
                }, 1000);
            },
        }

        const vm = new Vue({
            el: '#app',
            components: {
                App
            }
        })
    </script>
</body>

这边可能细心的朋友已经注意到,直接通过 Vue.nextTick()调用时nextTick前没有$符,而通过this.$nextTick()调用时nextTick前面是有一个$符的,感觉可以稍微注意一下。