异步更新队列:
请记住: vue 是依靠数据驱动视图更新的, 该更新的过程是异步的. 即: 当侦听到你的数据发生变化时, Vue 将开启一个队列(该队列被 Vue 官方称为异步更新队列). 视图需要等队列中所有数据变化完成之后, 再统一进行更新. 示例:
- <div id="myApp">
- <input type="button" value="点我呀" @click="changeStr">
- <p ref="myP">{{str}}</p>
- </div>
- <script>
- new Vue({
- el:"#myApp",
- data:{
- str:"公众号 张培跃, 关注它的人很少!"
- },
- methods:{
- changeStr(){
- this.str = "欢迎关注公众号 张培跃, 收看更多精彩内容!";
- // 输出结果: 公众号 张培跃, 关注它的人很少!
- console.log(this.$refs.myP.innerText)
- }
- }
- })
- </script>
通过以上示例的输出结果可以有力证明: Vue 实现的响应式并不是数据发生变化之后视图立即变化.
获取更新之后的 DOM
Vue 官方为了避免开发者直接接触视图, 鼓励大家以 "数据驱动" 的方式进行思考. 但, 现在的我们想基于更新后的视图来搞点事情, 该如何下手?
我们可以使用 $nextTick(callback). 这里的回调函数 (callback) 将在数据更新完成, 视图更新完毕之后被调用.
更改上个示例中的 changeStr 方法如下:
- changeStr(){
- this.str = "欢迎关注公众号 张培跃, 收看更多精彩内容!";
- this.$nextTick(()=>{
- // 输出结果: 我爱你中国, 我亲爱的母亲!
- console.log(this.$refs.myP.innerText);
- });
- this.str = "我爱你中国, 我亲爱的母亲!"
- }
从输出的结果可以看出: 我们可以通过 $nextTick() 获取到更新之后的 DOM.
因为 $nextTick() 返回一个 Promise 对象, 所以我们也可以使用 async/await 语法完成相同的事情:
- changeStr:async function(){
- this.str = "欢迎关注公众号 张培跃, 收看更多精彩内容!";
- this.str = "我爱你中国, 我亲爱的母亲!"
- await this.$nextTick();
- console.log(this.$refs.myP.innerText);
- }
或者
- changeStr(){
- this.str = "欢迎关注公众号 张培跃, 收看更多精彩内容!";
- this.$nextTick().then(()=>{
- // 输出结果: 我爱你中国, 我亲爱的母亲!
- console.log(this.$refs.myP.innerText);
- });
- this.str = "我爱你中国, 我亲爱的母亲!"
- }
应用场景
1, 如果要在 created()钩子函数中进行的 DOM 操作, 由于 created()钩子函数中还未对 DOM 进行任何渲染, 所以无法直接操作, 需要通过 $nextTick()来完成.
- created(){
- this.$nextTick(()=>{
- this.$refs.myP.innerText = "我是一只小小小小鸟, 想要飞, 却怎么样也飞不高!";
- });
- }
注: 在 created()钩子函数中进行的 DOM 操作, 不使用 $nextTick()会报错:
- // Error in created hook: "TypeError: Cannot set property'innerText'of undefined"
- created(){
- this.$refs.myP.innerText = "我是一只小小小小鸟, 想要飞, 却怎么样也飞不高!";
- }
2, 更新数据后, 想要使用 JS 对新的视图进行操作时. 示例(略)
3, 在使用某些第三方插件时 , 这些插件需要 dom 动态变化后重新应用该插件, 这时候就需要使用 $nextTick()来重新应用插件的方法. 示例(略)
-----END-----
来源: http://www.jianshu.com/p/2322a567827b