Inertia.js 持久布局实现原理

Inertia.js 持久布局实现原理

这段代码是 Inertia.js 专属的持久布局方案 ,核心原理是:把布局组件作为页面组件的静态属性挂载,让 Inertia 框架在渲染时复用同一个布局,而非每次切换页面都重新创建 / 销毁布局

复制代码

|---|----------------------------------------------------------------|
| | import Layout from './Layout' |
| | |
| | const Welcome = ({ user }) => { |
| | return ( |
| | <> |
| | <h1>Welcome</h1> |
| | <p>Hello {user.name}, welcome to your first Inertia app!</p> |
| | </> |
| | ) |
| | } |
| | |
| | Welcome.layout = Layout |
| | |
| | export default Welcome |


1. 先看代码做了什么

复制代码

|---|----------------------------------------------------------------|
| | // 1. 导入布局组件(整个页面的外壳:导航、侧边栏、页脚等) |
| | import Layout from './Layout' |
| | |
| | // 2. 定义页面组件(只有页面内容:欢迎语) |
| | const Welcome = ({ user }) => { |
| | return ( |
| | <> |
| | <h1>Welcome</h1> |
| | <p>Hello {user.name}, welcome to your first Inertia app!</p> |
| | </> |
| | ) |
| | } |
| | |
| | // 3. 关键:把 Layout 赋值给 Welcome 的静态属性 layout |
| | Welcome.layout = Layout |
| | |
| | // 4. 导出页面组件 |
| | export default Welcome |

核心动作 :给页面组件 Welcome 绑定了一个静态属性 layout,值就是你的布局组件。


2. 底层核心原理(Inertia 渲染机制)

Inertia 是单页应用(SPA) 框架,它不会像传统多页应用那样刷新整个浏览器 ,而是通过客户端路由局部更新页面内容。

它的渲染流程是这样的:

  1. 框架层统一渲染:Inertia 有一个根渲染器,负责渲染所有页面;

  2. 读取页面布局 :渲染前,先检查当前页面组件是否有 layout 静态属性

  3. 嵌套渲染

    • layout → 用布局组件包裹页面组件渲染;
    • layout → 直接渲染页面组件;
  4. 持久化关键

    • 切换页面时,布局组件只会创建一次
    • 只有布局内部的页面内容(子组件)会被替换
    • 布局的状态、DOM 节点、事件监听完全保留,不销毁、不重建

3. 为什么这叫「持久布局」?

对比两种渲染方式,你立刻就懂:

❌ 传统方案(非持久)

每个页面自己写布局:

复制代码

|---|-------------------------------------|
| | // Welcome 页面 |
| | const Welcome = () => { |
| | return ( |
| | <Layout> {/* 每次渲染都新建一个 Layout */} |
| | <h1>Welcome</h1> |
| | </Layout> |
| | ) |
| | } |

切换页面时:旧布局销毁 → 新布局创建,导航 / 侧边栏会重新渲染,状态丢失,体验差。

✅ Inertia 方案(持久)

复制代码

|---|---------------------------|
| | Welcome.layout = Layout |

切换页面时:

  • 布局组件始终保留在 DOM 中(不卸载、不重绘);
  • 只有 <h1>Welcome</h1> 这部分内容被替换;
  • 布局的状态(如折叠侧边栏、滚动位置)完全保留。

这就是持久布局 的本质:布局只初始化一次,全局复用,页面切换不影响布局


4. 补充:Layout 组件长什么样?

为了让你彻底理解,布局组件通常是这样的:

复制代码

|---|--------------------------------------|
| | // Layout.js |
| | const Layout = ({ children }) => { |
| | return ( |
| | <div className="layout"> |
| | {/* 公共导航栏(持久不变) */} |
| | <nav>导航栏</nav> |
| | |
| | {/* 页面内容(切换页面时这里会变) */} |
| | <main>{children}</main> |
| | |
| | {/* 公共页脚(持久不变) */} |
| | <footer>页脚</footer> |
| | </div> |
| | ) |
| | } |
| | export default Layout |

  • children 就是你的页面组件(Welcome 等);
  • 导航 / 页脚是持久部分children动态切换部分

5. 极简总结

  1. 原理一句话

    给页面组件绑定静态 layout 属性,Inertia 框架识别后,

    全局复用布局组件,只更新页面内容

  2. 核心优势

    布局不销毁、不重建,状态保留,页面切换更流畅,是 SPA 最佳实践。

  3. 为什么用静态属性

    不污染组件实例,让框架能直接读取布局配置,简洁高效。

总结

  • 实现方式:页面组件.layout = 布局组件(静态属性绑定)
  • 核心原理:Inertia 统一渲染,布局复用,内容替换
  • 最终效果:真正的持久化布局,SPA 流畅体验

彻底搞懂 JS 静态属性、实例属性、静态方法、实例方法

JS 新手最容易混淆的知识点

先给你一个总纲,记住这个就不会乱:

  • 静态:属于类本身,直接用 类名。调用
  • 实例:属于对象,必须 new 之后,用 对象。调用

一、先看最核心的区别(一句话)

类型 归属 调用方式 关键词
静态属性 / 方法 属于类 / 构造函数本身 类名.属性 类名.方法() static
实例属性 / 方法 属于new 出来的对象 对象.属性 对象.方法() 无 / this

二、用最简单的代码讲清楚

我们用一个 User 类来举例:

1. 静态属性 / 静态方法

加了 static → 属于类,不属于某个具体对象

所有对象共享这一个属性 / 方法。

复制代码

|---|-----------------------------------------------|
| | class User { |
| | // 静态属性 |
| | static className = "用户类"; |
| | |
| | // 静态方法 |
| | static getInfo() { |
| | return "我是静态方法,属于 User 类"; |
| | } |
| | } |
| | |
| | // ✅ 直接用 类名. 调用 |
| | console.log(User.className); // "用户类" |
| | console.log(User.getInfo()); // "我是静态方法..." |
| | |
| | // ❌ 不能用对象调用(会报错/undefined) |
| | const user = new User(); |
| | console.log(user.className); // undefined |

2. 实例属性 / 实例方法

不加 static → 属于 new 出来的对象

每个对象都有自己独立的一份。

复制代码

|---|-------------------------------------------|
| | class User { |
| | // 实例属性 |
| | name = "张三"; |
| | |
| | // 实例方法 |
| | sayHi() { |
| | return `你好,我是 ${this.name}`; |
| | } |
| | } |
| | |
| | // ❌ 不能用类名调用 |
| | console.log(User.name); // 不是你想要的 |
| | |
| | // ✅ 必须 new 出对象,用 对象. 调用 |
| | const user = new User(); |
| | console.log(user.name); // "张三" |
| | console.log(user.sayHi()); // "你好,我是张三" |


三、回到React 组件的静态属性

复制代码

|---|------------------------------------|
| | const Welcome = () => { ... } |
| | |
| | // 给 Welcome 这个函数,挂一个静态属性 layout |
| | Welcome.layout = Layout; |

这里的本质:

  1. Welcome 是一个函数(组件本质就是函数 / 类)
  2. Welcome.layout 就是给函数本身挂一个静态属性
  3. 不属于组件渲染出来的对象 ,属于组件函数本身
  4. Inertia 直接读取 Welcome.layout 就能拿到布局,不需要渲染组件

这就是为什么要用静态属性

想让框架在渲染组件之前,就能读取到组件的配置(布局)


四、最关键的一张图

复制代码

|---|-----------------------------|
| | 类/函数(Welcome) |
| | ↳ 静态属性/方法(Welcome.layout) |
| | ↑ 直接访问 |
| | ↳ new 创建实例(组件渲染对象) |
| | ↳ 实例属性/方法(this.xxx) |
| | ↑ 必须用对象访问 |


五、常见使用场景

1. 静态属性 / 方法 用在什么地方?

  • 工具方法(不需要创建对象就能用)
  • 全局共享配置
  • 组件配置(React/Vue 里的 layout、title、权限)
  • 例子:axios.defaultsMath.random() 都是静态

2. 实例属性 / 方法 用在什么地方?

  • 每个对象独立的数据(用户姓名、年龄、状态)
  • 组件内部的 this.statethis.props
  • 组件里的事件处理函数

六、你最容易混淆的 3 个问题

1. 静态属性能被实例继承 / 访问吗?

不能!

实例访问不到静态属性,静态属性只属于类。

2. 静态方法里能用 this 吗?

能用,但 this 指向的是类,不是实例!

复制代码

|---|--------------------------------------------------|
| | class User { |
| | static className = "123"; |
| | static fn() { |
| | console.log(this.className); // 这里 this = User |
| | } |
| | } |

3. 为什么 React 组件要用静态属性?

因为:

  • 我们不想把布局变成组件的内部状态
  • 我们想让框架直接读取组件本身的配置
  • 这是一种组件元信息(描述组件自身的信息)

最终极简总结

  1. 静态(static) :属于类 / 函数本身 ,直接 类名. 调用,共享一份

  2. 实例 :属于new 出来的对象 ,必须 对象. 调用,每个对象独立

  3. 你的代码 Welcome.layout = Layout

相关推荐
不会写DN2 小时前
如何在纯前端中通过手势交互来控制星球的转动
前端·交互
w2sfot2 小时前
反AI逆向JS加密
javascript·人工智能·反ai
liliangcsdn2 小时前
sentence-transformer如何离线加载和使用模型
开发语言·前端·php
东宇科技3 小时前
如何使用js进行抠图。识别商品主体
开发语言·javascript·ecmascript
不会写DN3 小时前
Vue3中的computed 与 watch 的区别
javascript·面试·vue
qq_381338503 小时前
TypeScript 类型安全与类型体操实战:从入门到精通
javascript·安全·typescript
朦胧之3 小时前
AI 编程工具使用浅谈
前端·后端
柳杉3 小时前
HTML-in-Canvas:让 Canvas 完美渲染 HTML 的 Web 新标准
前端·javascript
cTz6FE7gA3 小时前
WebGL实战:用Three.js创建3D场景,实现沉浸式Web体验
前端·javascript·webgl