Flet 是 Python 生态中用于快速构建跨平台应用的框架,默认提供的路由和视图管理方式在简单场景下足够使用,但当应用页面增多、逻辑变复杂时,函数式的写法会导致代码难以维护。基于类的路由与视图管理可以把单个页面的所有相关逻辑封装到独立的类中,让项目结构更清晰。

核心概念说明
基于类的视图管理核心是将每个页面抽象为一个类,类中包含页面的 UI 构建方法、事件处理逻辑、状态数据等。路由则负责将不同的路径映射到对应的视图类,在路径切换时自动实例化对应的视图类并渲染页面。
视图类的基本结构
一个基础的 Flet 视图类通常包含以下部分:
- 初始化方法:接收页面上下文、路由参数等必要信息
- build 方法:返回当前页面的 UI 组件树
- 事件处理方法:处理页面内按钮点击、输入变化等交互逻辑
- 状态属性:存储当前页面的临时状态数据
基础视图类实现
首先我们定义一个基础的视图基类,封装通用的页面初始化逻辑,后续所有页面视图类都继承这个基类:
import flet as ft
class BaseView:
def __init__(self, page: ft.Page, route_params: dict = None):
self.page = page
self.route_params = route_params if route_params else {}
self.controls = []
def build(self):
# 子类重写这个方法返回具体的页面组件
return ft.Column(controls=self.controls)
def update_page(self):
# 更新页面显示
self.page.controls.clear()
self.page.add(self.build())
self.page.update()
具体页面视图类实现
接下来实现两个具体的页面视图类,分别是首页和个人详情页,演示路由参数传递和页面切换逻辑:
class HomeView(BaseView):
def build(self):
# 构建首页UI
self.controls = [
ft.Text(value="首页", size=30, weight=ft.FontWeight.BOLD),
ft.ElevatedButton(
text="跳转到个人详情页",
on_click=self.go_to_profile
)
]
return ft.Column(controls=self.controls)
def go_to_profile(self, e):
# 跳转到个人详情页,携带用户ID参数
self.page.go("/profile/1001")
class ProfileView(BaseView):
def build(self):
# 从路由参数中获取用户ID
user_id = self.route_params.get("user_id", "未知")
self.controls = [
ft.Text(value=f"个人详情页", size=30, weight=ft.FontWeight.BOLD),
ft.Text(value=f"当前用户ID:{user_id}", size=20),
ft.ElevatedButton(
text="返回首页",
on_click=self.go_back_home
)
]
return ft.Column(controls=self.controls)
def go_back_home(self, e):
self.page.go("/")
基于类的路由配置
Flet 本身没有内置的类路由映射机制,我们需要自己实现一个简单的路由管理器,将路径规则映射到对应的视图类:
class Router:
def __init__(self, page: ft.Page):
self.page = page
# 定义路由规则,键是路径匹配规则,值是对应的视图类
self.routes = {
"/": HomeView,
"/profile/:user_id": ProfileView
}
# 监听页面路由变化事件
self.page.on_route_change = self.route_change
# 初始化时触发一次路由变化
self.page.go(self.page.route)
def parse_route(self, route_str: str):
# 解析路由字符串,提取路径和参数
for pattern, view_cls in self.routes.items():
# 处理带参数的路由规则
if ":user_id" in pattern:
# 分割路径和参数部分
pattern_parts = pattern.split("/")
route_parts = route_str.split("/")
if len(pattern_parts) == len(route_parts):
params = {}
match = True
for p_part, r_part in zip(pattern_parts, route_parts):
if p_part.startswith(":"):
# 提取参数名和参数值
param_name = p_part[1:]
params[param_name] = r_part
elif p_part != r_part:
match = False
break
if match:
return view_cls, params
elif pattern == route_str:
return view_cls, {}
# 没有匹配的路由,返回404视图
return None, {}
def route_change(self, e):
route_str = e.route
view_cls, params = self.parse_route(route_str)
if view_cls:
# 实例化视图类并渲染
view_instance = view_cls(self.page, params)
view_instance.update_page()
else:
# 处理404情况
self.page.controls.clear()
self.page.add(ft.Text(value="404 页面不存在", size=30))
self.page.update()
完整应用入口
最后编写应用入口代码,初始化页面和路由管理器:
def main(page: ft.Page):
page.title = "Flet 基于类的路由与视图管理示例"
page.window_width = 800
page.window_height = 600
# 初始化路由管理器
Router(page)
ft.app(target=main)
注意事项
在使用基于类的路由与视图管理时,需要注意以下几点:
- 路由参数解析逻辑需要根据实际项目的路由规则扩展,比如支持多个参数、可选参数等场景
- 视图类的状态如果需要跨页面共享,可以单独定义状态管理类,避免视图类之间直接耦合
- 页面切换时如果需要保留之前页面的状态,可以在视图类中添加状态缓存逻辑,或者在路由管理器中缓存视图实例
- 复杂的交互逻辑可以拆分到单独的 service 类中,保持视图类的职责单一
基于类的路由与视图管理不是 Flet 的强制要求,开发者可以根据项目规模选择是否使用,小型项目使用默认的函数式写法反而更简洁。