解决 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之后, 就会立即更新需要的布局。

相关推荐
资源大佬星 课it1 小时前
重学C++ ,重构你的C++知识体系
vue.js·docker·django
Eason_Lou3 小时前
【无标题】
前端·vue.js·html
Eason_Lou5 小时前
vue flow使用注意事项
前端·vue.js
马可家的菠萝9 小时前
Vue3 + Canvas 手绘笔记工程化实践:别把画布只当成一张 PNG
前端·vue.js·算法
用户841794814569 小时前
如何用 vue 甘特图来实现计划和实际双任务条进度展示
vue.js
京东云开发者13 小时前
【全栈实践】第一个 AI Agent 项目:从零搭建 AI 音频创作助手【最终版】
前端·vue.js·音视频开发
一颗烂土豆13 小时前
ECharts 太平面?试试这款 Vue 3D 图表库
前端·vue.js·echarts
宿67414 小时前
vscode文件夹
前端·vue.js·vscode
sosohotsummer14 小时前
Vue多级路由嵌套,keep-alive缓存问题
前端·javascript·vue.js
雪芽蓝域zzs15 小时前
新建前端pnpm(vue js ) 仿若依项目(一)
前端·javascript·vue.js