Vue - 有没有办法在渲染完成后引入代码?

4

我知道mountedcreated是生命周期钩子函数,并且已经尝试过它们。我也尝试在mounted中使用$nextTick,但这并不能准确地渲染。我现在正在尝试在初始渲染之后从一个DOM节点中访问一些数据。以下是我代码的关键部分:

mounted() {
  console.log(this.$el.getBoundingClientRect().top);
},

这给我提供了错误的数据。然而,使用以下代码:

mounted() {
  setTimeout(() => {
    console.log(this.$el.getBoundingClientRect().top);
  }, 1000)
},

在我开始获取正确的数据之前,阈值大约为700-900毫秒。

问题1

为什么生命周期在一切都没有完全渲染时被调用?

问题2

这是否与尚未完全挂载的同级组件有关,可能会推动维度?

问题3

是否有解决方案,可以挂钩到一个事件上,基本上表示“页面上的所有内容都已呈现”。

我不喜欢我想出的setTimeout解决方案,因为显然存在问题。


1
问题2:回答“是”。 - Roy J
你有第三个问题的答案吗?@RoyJ - Andrew Kim
2个回答

1
由于事物是异步渲染的,您可能无法确定位置不会改变。 每次更新时,您可能需要获取位置。 您可以使用自定义指令来执行此操作,当更新时,其update函数将被调用。
这是一个小演示:

new Vue({
  el: '#app',
  data: {
    ht: 100,
    top: null
  },
  directives: {
    bounding(el, binding, vnode) {
      vnode.context[binding.expression] = el.getBoundingClientRect().top;
    }
  },
  mounted() {
    let times = 5;
    const i = setInterval(() => {
      this.ht += 10;
      if (--times < 1) {
        clearInterval(i);
      }
    }, 1000);
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div :style="{height: `${ht}px`}">Hi</div>
  <div v-bounding="top">{{top}}</div>
</div>


1

问题1: 生命周期钩子只关注组件实例本身,而不是DOM的其余部分。因此,在组件完全挂载时,页面的其余部分可以保持挂起状态。

问题2: 与问题1相同。

问题3: 您可以使用以下代码:

document.addEventListener("DOMContentLoaded", function(event) {
    console.log(this.$el.getBoundingClientRect().top);
});

针对更深入的回答:没有使用jQuery时的$(document).ready等效方法

编辑

你应该使用这个替代方案:

window.addEventListener("load", function(event) {
    console.log(this.$el.getBoundingClientRect().top);
});

我忘记了外部资源。 DOMContentLoaded 在 dom 即 html 加载完成后触发。 load 在外部资源加载完成后触发。 进一步阅读:https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload

不幸的是,这会得到相同的结果。显然DOM已经挂载。 - Andrew Kim
抱歉..我忘记了外部资源。看看我的编辑以查看更改 :) - Rudi Ørnhøj
到目前为止,这绝对是最干净的解决方案。 - DemiA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接