Swiper和Vue配合使用的问题——Vue的异步更新DOM

Swiper是很常用的库,用于实现触摸滑动效果,为了让Swiper生效,需要执行类似下面的代码(摘自Swiper官方示例)

var mySwiper = new Swiper(‘.swiper-container‘, {
    autoplay: true,//可选选项,自动滑动
})

而该代码的执行时机必须在DOM渲染完成之后,因此Swiper的官方文档要求在window.onload或$(document).ready()(使用JQuery或Zepto时)调用。

但显然,这只适用于静态页面。

如果Swiper中的数据是动态渲染的,且可能会通过Ajax请求获得最新的值而不断变化,那我们在什么时机去调用呢?

是不是数据被修改了就可以调用呢?因为Vue.js的双向绑定特性,数据被修改页面就会被重新渲染。

答案是否定的。

可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.thenMutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

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

——摘自Vue.js官方文档

<br />因此我们就可以把Swiper的初始化放在<code>Vue.nextTick(callback)接收的回调函数中去。

如果你的Ajax请求直接在当前Vue示例的方法中调用(没有使用Vuex),那么可以在Ajax请求成功的回调中注册nextTick事件。

axios.get("/api/xxx").then(res=>{
   this.$nextTick(()=>{
        var mySwiper = new Swiper(‘.swiper-container‘, {
            autoplay: true,//可选选项,自动滑动
        })
    }) //this指当前Vue实例      
})

这样就能确保调用时页面的DOM已经被更新。

如果使用了Vuex,那么Ajax的操作一般会放在Vuex中的action里,因此我们在当前页面中就不能使用上面那种方法了。

需要给对应的数据加上一个watcher,这样action通过mutation更改数据时,我们的watcher监视器也会被调用,

我们可以在watcher里面去注册this.$nextTick事件,方法同上。

相关推荐