vuejs nextTick的一个疑惑

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id='app'>
        <ul>
            <li v-for='i in items'><h1>{{i}}</h1></li>
        </ul>
    </div>

    <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.js'></script>
    <script>
        new Vue({
             el:'#app',
             data:function(){
                  return {
                    items:[]
                  };
             },
             ready:function(){
               for (var i = 0; i < 3000; i++) {
                 this.items.push( i );
               }
                       
                 
               this.$nextTick(function(){
                 var h = document.body.scrollHeight - window.innerHeight;
                 window.scrollTo(0,h);
               });
                        
                    
            }    
            
        });
    </script>
</body>
</html>

我希望完成一个效果,当数据返回以后 进行渲染 然后浏览器的滚动条滚动到底部,但是上面这样实现不成功,我试了一下用 setTimeout是可以的,但是看文档说nextTick里面已经有了setTimeout ,上面的代码为什么不行?

更新:系统 osx 10.11.4
chrome版本 50.0.2661.102 (64-bit) 测试无效
火狐 , Safari有效。

阅读 8.7k
5 个回答

不知道题主是用的什么环境和浏览器,我这边chrome测试是可以的,原样复制你的代码的.

问题过了很久,但是仍然想回答一波。这个问题不在于vuevue1会优先使用MutationObserversetTimeout只是一个回退替代的方案。所以问题在于的是chrome下MutationObserver配合window.scrollTo有些问题,应该是浏览器的问题,而非是vue的问题.
大家可以根据下面这个例子进行一下测试,第一次进入页面时正常,但是在此基础上进行页面刷新时应该就会失效:

<!DOCTYPE html>
<html>
  <head>
      <meta charset="UTF-8" />
      <title>Test</title>
      <style type="text/css">
        #ul{
          font-size: 55px;
        }
      </style>
  </head>
  <body>
    <div id='app'>
        <ul id="ul"></ul>
    </div>
    <script>
      window.onload = function () {
        var cache = document.createDocumentFragment(),
          ul = document.querySelector("ul");
        for (var i = 0; i < 30; i++) {
          var li = document.createElement("li");
          li.innerText = i;
          cache.appendChild(li);
        }
        function hasUpdated() {
          document.body.style.background = "red";
          window.scrollTo(0,800);
        }
        // 利用MutationObserver,在chrome下,window.scrollTo也是无效的
        var mo = new MutationObserver(hasUpdated);
        var option = {
          'childList': true, 
          'subtree': true
        };
        mo.observe(ul, option);
        var p = Promise.resolve();
        p.then(hasUpdated);
        ul.appendChild(cache);
      };
    </script>
  </body>
</html>

今天也遇到类似的问题,就是发现当nextTick用在ready或者vue-router的data钩子里面的时候,其实并不能如我们所想的那样保证回调是在dom的数据渲染完毕之后再执行,
找了很久的答案终于看到一个相关的:尤大大在vue-router的一个issue下面回复:

nextTick is intended to be used right after you modified some reactive data.

nextTick是计划在当你更改了某些响应式的数据时使用的。
也就是说,nextTick应该被用在某些计算属性或者watch再或者某个按钮click事件绑定的methods当中。这时,nextTick才能保证你的数据更新完成之后再执行你绑定的函数.

新手上路,请多包涵

在Chrome Version 51.0.2704.106 (64-bit)里观察到同样问题,nextTick是用MutationObserver实现的,也许DOM变动还没完成?虽然document.body.scrollHeight的计算是正确的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题