解决 SSR 框架的布局不一致思路

首先使用项目实例,介绍需求和遇到的问题

使用Nuxt的时候常常会遇到潜在的闪烁 / 布局不一致

平台:Nuxt

包文件: Splitpanes

xml 复制代码
​
<script setup lang="ts">
// @ts-expect-error missing type
import { Pane, Splitpanes } from 'splitpanes'
​
const ui = useUiState()
const play = usePlaygroundStore()
</script>
​
<template>
  <Splitpanes
  >
    <Pane :size="ui.panelDocs" min-size="10">
      <PanelDocs />
    </Pane>
    <Pane :size="100 - ui.panelDocs">
      <Splitpanes
        horizontal
      >
        <Pane :size="ui.panelEditor" min-size="10">
          <PanelEditor :files="play?.files" />
        </Pane>
        <Pane :size="ui.panelPreview" min-size="10">
          <PanelPreview />
        </Pane>
        <Pane :size="100 - ui.panelEditor - ui.panelPreview">
          <PanelTerminal />
        </Pane>
      </Splitpanes>
    </Pane>
  </Splitpanes>
</template>
​

ui为设置的页面size, 在nuxt平台, 如果包含client.vue文件, 需要等待这些文件 JS 内容执行完成才会从初始状态到达我们的预设。 通过使用计算属性并将它们绑定到 style 属性,修改后的代码可确保服务器呈现的 HTML 反映基于 ui 状态的预期初始布局。这消除了 SSR 期间潜在的布局闪烁或不一致。

Nuxt平台, 要充分利用SSR渲染的优势, 就要先给布局设置固定的style。

xml 复制代码
<script setup lang="ts">
// @ts-expect-error missing type
import { Pane, Splitpanes } from 'splitpanes'
​
const ui = useUiState()
const play = usePlaygroundStore()
​
const isMounted = useMounted()
const panelInitDocs = computed(() => isMounted.value || {
  width: `${ui.panelDocs}%`,
})
const panelInitRight = computed(() => isMounted.value || {
  width: `${100 - ui.panelDocs}%`,
})
const panelInitEditor = computed(() => isMounted.value || {
  height: `${ui.panelEditor}%`,
})
const panelInitPreview = computed(() => isMounted.value || {
  height: `${ui.panelPreview}%`,
})
const panelInitTerminal = computed(() => isMounted.value || {
  height: `${100 - ui.panelEditor - ui.panelPreview}%`,
})
</script>
​
<template>
    <splitpanes>
        <pane :size="ui.panelDocs" min-size="10" :style="panelInitDocs">
            <PanelGuide />
        </pane>
        <PanelSplitter />
        <pane :style="panelInitRight">
            <splitpanes horizontal>
                <Pane min-size="10" :size="ui.panelEditor" :style="panelInitEditor">
                    <PanelEditor :files="play.files" />
                </Pane>
                <PanelSplitter />
                <Pane min-size="10" :size="ui.panelPreview" :style="panelInitPreview">
                    <PanelPreview />
                </Pane>
                <PanelSplitter />
                <Pane min-size="10" :size="100 - ui.panelEditor - ui.panelPreview" :style="panelInitTerminal">
                    <PanelTerminal />
                </Pane>
            </splitpanes>
        </pane>
    </splitpanes>
</template>
    
​
​

PanelSplitter.vue

该文件防止布局拖动的布局消失

xml 复制代码
<script setup lang='ts'>
</script>
<template>
    <div class="splitpanes__splitter">
    </div>
</template>

这样随着 dom 被 mount之后, 就会立即更新需要的布局。

相关推荐
郝亚军3 小时前
webstorm如何创建vue 3.js
javascript·vue.js·webstorm
用户83134859306985 小时前
Cesium 实现行政区内部遮罩
vue.js·webgl·cesium
卤蛋fg66 小时前
vxe-table 自定义复制粘贴逻辑:精确控制单元格数据转换
vue.js
张人玉8 小时前
基于 Vue 3 + ECharts + Express + SQLite 构建的新能源汽车销量数据分析与可视化平台——新能源汽车销量数据分析系统
数据库·vue.js·sqlite·echarts
清风programmer10 小时前
H5与小程序通信
前端·vue.js·uni-app
Cobyte11 小时前
通过 Vite 运行手写的模板编译器
前端·javascript·vue.js
张人玉11 小时前
基于 Vue 3 + ECharts + Express + SQLite 构—— LDA 模型的新闻舆论主题识别与情感分析系统
vue.js·echarts·express
无人生还11 小时前
从 Vue3 到 React · 快速上手系列第 4 篇:条件渲染与列表渲染
前端·vue.js·react.js
咩咩啃树皮11 小时前
第46篇:Vue3 Router工程化进阶——懒加载+嵌套路由+全局守卫+权限控制
javascript·vue.js·ecmascript
咩咩啃树皮12 小时前
第44篇:Vue3侦听器完全精讲——watch与watchEffect区别、深度监听、异步业务落地
前端·javascript·vue.js