当前位置: 首页 > 知识库问答 >
问题:

javascript - 如何在 Vue.js 中解决异步数据加载导致的布局偏移问题?

孟建木
2024-06-28

布局偏移该怎么解决?

初始加载页面的时候,需要先请求数据,然后再显示。此时就会出现一个问题,在请求未响应的时候数据为空,显示区域未空,当得到数据之后,显示区域数据扩充,这就造成了数据便宜。

该显示区域的大小由数据决定,不能设置一个固定的大小。
我想如果可以在挂载之前获取这个数据的话,应该可以避免这个布局偏移。但是获取数据的操作是异步的,不会等待获取完之后再挂载。或者说在路由跳转的时候获取这个数据。(这个数据不多)

image.png

共有4个答案

冀景明
2024-06-28

我的想法还是数据prefetch,有几种方案供参考:

  1. 用 SWR 库进行数据请求,可以一定程度减少数据请求耗时
const { data, error, isLoading, isValidating, mutate } = useSWR(key, fetcher, options)
  1. 用preload属性放html上,进行数据提前加载

    <link rel="preload" href="/api/data" as="fetch" crossorigin="anonymous">
  2. 将数据请求的代码单独抽离到一个prefetch.js文件里面,然后利用打包配置,分包到单独一个init chunk

    // webpack.config.js
    
    entry: {
      prefetch: './prefetch.js'
    }
    
    splitChunks: {
      cacheGroups: {
     common: {
        name: 'common',
        chunk: 'initial',
        minChunks: 2,
        minSize: 0
     }
      }
    }
    
  3. 终极解决方案就是上SSR了,在中间层获取数据后,放页面上,一起返回给浏览器。

其它方案ai Bot里面列出来了:

  1. 骨架屏、过渡动画
  2. before路由钩子里面获取。
傅毅然
2024-06-28

看你图例觉得是占位问题,不是位移。如果你觉得页面突然被撑开,用户体验不好,有两个办法

1、设置一个空状态或loading状态设置一个最小高度。

min-height:xxx

2、另外就是移动端或者pc端用的骨架屏,暂估你这个区域显示10条数据或20条等,骨架屏循环10条或20条就可以了。

参考:https://1x.antdv.com/components/skeleton-cn/


陆栋
2024-06-28

OP你的 布局偏移 指的是啥?是说一开始没数据,所以本来应该展示在第二屏的区域展示在第一屏了,然后数据回来之后会突然出现第一屏的内容的这个位移问题,还是指什么问题?

如果是这个的话,可以把第一屏的内容做 骨架屏 的处理。这样会在请求的数据响应之前保持一定的内容占位。

如果是其他的问题,那得OP你补充具体的问题描述了。

谢铭
2024-06-28

在 Vue.js 中解决异步数据加载导致的布局偏移问题,通常有以下几种策略:

  1. 骨架屏/占位符
    在数据加载之前,使用占位符或骨架屏来占据页面的空间。这样,即使数据还未加载完成,页面的布局也不会发生突然的变化。
  2. 条件渲染
    使用 v-ifv-show 指令来根据数据是否加载完成来渲染组件。这样,只有当数据加载完成后,相关的组件才会被渲染到页面上。
  3. Vue 的 v-cloak 指令
    这个指令用于在 Vue 实例编译结束前隐藏元素。结合 CSS,你可以隐藏正在加载的数据区域,直到数据加载完成。
  4. 异步组件和加载器
    对于大型组件,可以使用 Vue 的异步组件功能,结合 Webpack 的代码分割,来按需加载组件。同时,你可以显示一个加载器来提示用户数据正在加载。
  5. 路由守卫
    在 Vue Router 中使用路由守卫(如 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave)来在路由跳转之前获取数据。这样,当路由切换时,数据已经准备好,可以直接渲染到页面上。
  6. 使用状态管理工具
    如果你的项目已经使用了 Vuex 或其他状态管理工具,你可以在这些工具中管理数据的加载状态。然后,在组件中根据这个状态来决定是否渲染数据。
  7. CSS 动画和过渡
    使用 CSS 动画和过渡来平滑地显示加载完成后的数据。这样,即使数据加载导致了布局变化,用户也不会感到突兀。

示例代码(使用条件渲染)

<template>
  <div>
    <!-- 使用 v-if 来根据数据是否加载完成来渲染组件 -->
    <div v-if="dataLoaded">
      <!-- 这里是显示数据的组件或模板 -->
      <div v-for="item in data" :key="item.id">
        {{ item.name }}
      </div>
    </div>
    <!-- 加载器或占位符 -->
    <div v-else>
      <p>数据正在加载...</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dataLoaded: false,
      data: [],
    };
  },
  async created() {
    // 在组件创建时获取数据
    const response = await fetchData(); // 假设 fetchData 是你的数据获取函数
    this.data = response.data;
    this.dataLoaded = true;
  },
};
</script>

在这个示例中,当数据还未加载完成时(dataLoadedfalse),只显示一个加载器或占位符。当数据加载完成后(dataLoaded 变为 true),才渲染显示数据的组件或模板。

 类似资料:
  • 一个select框组件,其中的数据是从后端返回的,打开这个组件时往里传入了value值,但是页面打开时也会显示这个value值,等后端结果返回才能显示对应的label值,如何让组件先不渲染value直接渲染label? 将请求的生命周期放在async created中没用

  • 这是方法体 这是在created调用这个方法 问题: 通过这个方法获取的数据,我在这个方法的.then后面进行console对res.rows进行输出时,数据是存在的。 将这个Patientdata变量加载进页面时 数据也是存在的。 但是我现在想在created或者是mounted对Patientdata数据进行操作后再加载进页面内,在写操作数据的方法时,发现怎么都获取不到Patientdata的

  • 本文向大家介绍Javascript vue.js表格分页,ajax异步加载数据,包括了Javascript vue.js表格分页,ajax异步加载数据的使用技巧和注意事项,需要的朋友参考一下 分页一般和表格一起用,分页链接作为表格的一部分,将分页链接封装成一个独立的组件,然后作为子组件嵌入到表格组件中,这样比较合理。 效果: 代码: 1.注册一个组件 js 模板: HTML: 当点击分页链接的时候

  • 当前代码如下,需要实现不同页面的切换,并且实现缓存效果,但目前缓存效果未实现。 在onMounted中输出1来判断是否缓存成功,即首次加载该页面输出1,进入二级界面后返回将不在输出1。尝试修改后如下 缓存虽然实现了,但是页面切换变得混乱。如何同时保留页面切换与缓存的效果呢?

  • 本文向大家介绍vue.js 表格分页ajax 异步加载数据,包括了vue.js 表格分页ajax 异步加载数据的使用技巧和注意事项,需要的朋友参考一下 Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API。 分页一般和表格一起用,分页链接作为表格的一部分,将分页链接封装成一个独立的组件,然后作为子组件嵌入到表格组件中,这样比较合理。 1.注册一个组件 js 模板: H

  • 本文向大家介绍JavaScript异步加载问题总结,包括了JavaScript异步加载问题总结的使用技巧和注意事项,需要的朋友参考一下 同步加载的问题 默认的js是同步加载的,这里的“加载”可以理解成是解析、执行,而不是“下载”,在最新版本的浏览器中,浏览器对于代码请求的资源都是瀑布式的加载,而不是阻塞式的,但是js的执行总是阻塞的。这会引起什么问题呢?如果我的index页面要加载一些js,但是其