Mesop 多页面应用实战:页面注册、导航跳转与跨页状态共享

发布时间:2026/9/17 15:00:02
Mesop 多页面应用实战:页面注册、导航跳转与跨页状态共享 Mesop 多页面应用实战页面注册、导航跳转与跨页状态共享【免费下载链接】mesopRapidly build AI apps in Python项目地址: https://gitcode.com/GitHub_Trending/me/mesop多页面Multi-Page是 Mesop 构建真实 Web 应用的核心能力只需用me.page装饰器为不同 URL 路径注册页面函数再通过me.navigate在页面间跳转即可快速搭建包含登录页、列表页、详情页的完整 AI 应用。读完本文你将掌握 Mesop 的页面注册机制、me.navigate的完整参数用法、跨页面复用 State 的方法以及on_load页面加载钩子等进阶技巧。从单页到多页用 me.page 注册页面Mesop 中每个页面本质上是一个被me.page装饰的 Python 函数该函数会成为特定 URL 路径的根组件root component。在 核心概念 中你已经见过单页应用而多页应用只是注册多个带不同path的页面函数而已import mesop as me me.page(path/1) def page1(): me.text(page 1) me.page(path/2) def page2(): me.text(page 2)运行后访问/1会渲染page1访问/2会渲染page2。几点关键说明如果不传path参数默认等价于me.page(path/)即根路径页面参见 页面 API 文档每个me.page装饰的页面函数应当是独立的根组件页面内部可以继续组合其他组件或用户自定义组件同一个文件中可以注册任意多个页面Mesop 会把它们统一登记到运行时runtime的路径映射表中。页面注册的底层机制从源码看me.page装饰器最终调用runtime().register_page()完成注册见 mesop/features/page.pyruntime().register_page( pathpath, page_configPageConfig( page_fnwrapper, titletitle or fMesop: {path}, stylesheetsdeepcopy(stylesheets or default_stylesheets), security_policydeepcopy(security_policy) if security_policy else SecurityPolicy(), on_loadon_load, ), )注册的PageConfig定义于 mesop/runtime/runtime.py包含page_fn、title、stylesheets、security_policy和on_load五个字段页面路径与配置的映射存放在_path_to_page_config字典中。值得注意的安全约束register_page会检查_has_served_traffic标记一旦服务器开始处理流量就禁止再注册新页面见 mesop/runtime/runtime.pyif self._has_served_traffic: raise MesopDeveloperException( Cannot register a page after traffic has been served. You must register all pages upon server startup before any traffic has been served. This prevents security issues. )这意味着所有页面必须在服务启动时一次性完成注册。如果访问了一个未注册的路径run_path会抛出MesopUserException并把当前已注册的路径列表打印出来提示你见 mesop/runtime/runtime.py例如Accessed path: /foo not registered Try one of the following paths: /1 /2页面配置项详解me.page支持以下关键字参数完整签名见 mesop/features/page.py参数类型默认值说明pathstr/页面绑定的 URL 路径如/1、/multi_page_nav/page_2titlestr \| NoneNone页面标题为None时自动生成Mesop: {path}stylesheetslist[str] \| NoneNone需要加载的外部样式表 URL 列表security_policySecurityPolicy \| NoneNone页面级安全策略为None时使用默认严格策略on_loadOnLoadHandler \| NoneNone页面首次加载时执行的事件处理函数其中SecurityPolicy见 mesop/security/security_policy.py支持配置cross_origin_opener_policy、allowed_iframe_parents、allowed_connect_srcs、allowed_script_srcs、allowed_worker_srcs、allowed_trusted_types、allowed_font_srcs等 CSP内容安全策略相关字段以及一个强烈不建议开启的dangerously_disable_trusted_types开关。页面间导航me.navigate 的完整用法多页应用必然需要页面跳转。Mesop 提供me.navigate(/to/path)在浏览器中导航到其他页面通常放在事件处理器中例如按钮的on_click回调里。完整的导航示例可见 mesop/examples/navigate.pyimport mesop as me def navigate(event: me.ClickEvent): me.navigate(/examples/navigate/about) me.page(path/examples/navigate/home) def home(): me.text(This is the home page) me.button(navigate to about page, on_clicknavigate) me.page(path/examples/navigate/about) def about(): me.text(This is the about page)navigate 函数签名me.navigate的完整签名定义于 mesop/commands/navigate.pydef navigate( url: str, *, query_params: dict[str, str | Sequence[str]] | QueryParams | None None, open_in_new_tab: bool False, ) - None参数说明参数说明url目标地址支持绝对 URL如http://example.com/page和以/开头的根相对 URL如/page。不支持文档相对 URL如page、./pagequery_params要携带的查询参数可以是字典也可以是me.query_params。查询参数应通过该参数传递如果直接拼在 URL 里会被剥离并发出警告open_in_new_tab是否在新标签页打开默认False。为True时会保留当前页面的查询参数除非显式覆盖关于查询参数的实现细节navigate内部会调用remove_url_query_param清理 URL 中内嵌的查询串如果发现 URL 与清理后不一致会打印警告并建议改用query_params关键字参数见 mesop/commands/navigate.pyUsed me.navigate to navigate to a URL with query params. The query params have been removed. Instead pass the query params using the keyword argument like this: me.navigate(url, query_params{key: value})新标签页打开与跨域跳转open_in_new_tabTrue常用于在新标签页查看详情等场景仓库中的 mesop/examples/navigate_new_tab.py 给出了完整示范def navigate_about_new_tab(e: me.ClickEvent): me.navigate(/navigate_new_tab/about, open_in_new_tabTrue) def navigate_example_new_tab(e: me.ClickEvent): me.navigate(https://example.com, open_in_new_tabTrue) def navigate_with_params_new_tab(e: me.ClickEvent): me.navigate( /navigate_new_tab/about, query_params{foo: bar, baz: qux}, open_in_new_tabTrue, )而 mesop/examples/navigate_absolute.py 演示了如何跳转到https://、http://等绝对地址包括在生成器事件处理器中先yield再导航的写法。navigate 的底层实现从源码看mesop/commands/navigate.pynavigate的调用链是若传入了QueryParams对象先展开为{key: values}字典若不在新标签页打开则清空当前上下文的查询参数runtime().context().query_params().clear()因为查询参数要么被新参数替换、要么被清空调用runtime().context().navigate(cleaned_url, query_params, open_in_new_tab)下发导航命令。Context.navigate见 mesop/runtime/context.py会把 URL 与查询参数拼装成完整的full_url对 key/value 做 URL 编码支持一个 key 对应多个值然后追加一条pb.Command(navigate...)命令由浏览器端执行实际跳转。跨页面共享 State事件驱动导航实战多页应用一个非常实用的特性是状态可以跨页面复用。官方指南以 mesop/examples/docs/multi_page_nav.py 为例展示了如何在页面 A 中累加计数跳转到页面 B 后依然能读到同一个State#countimport mesop as me def on_click(e: me.ClickEvent): state me.state(State) state.count 1 me.navigate(/multi_page_nav/page_2) me.page(path/multi_page_nav) def main_page(): me.button(Navigate to Page 2, on_clickon_click) me.page(path/multi_page_nav/page_2) def page_2(): state me.state(State) me.text(fPage 2 - count: {state.count}) me.stateclass class State: count: int这个例子的执行流程值得仔细拆解用户在/multi_page_nav页面点击按钮触发on_click事件处理器处理器通过me.state(State)获取当前浏览器会话的State实例将count加 1然后调用me.navigate(/multi_page_nav/page_2)浏览器跳转到/multi_page_nav/page_2后page_2组件同样通过me.state(State)取到同一个会话的同一份状态因此能读到刚才递增后的count值。State 的会话隔离与序列化me.stateclass是一个类似 Pythondataclass的类装饰器但它会根据类型注解自动设置默认值并允许 Mesop 注入类实例详见 核心概念。有两个与跨页共享直接相关的实现细节每个会话独立Runtime.create_context见 mesop/runtime/runtime.py会为每个会话context基于所有已注册的 state 类新建一份实例避免不同用户之间的状态串扰必须可序列化State 内容会在服务器与浏览器之间传输通过serialize_state/diff_state做序列化与增量同步见 mesop/runtime/context.py因此 state 类中的一切字段都必须是可序列化的。另外需要注意一个安全约定来自 核心概念不应当在组件函数渲染函数内部修改 State所有状态变更必须发生在事件处理器中。页面加载钩子on_load 的使用如果希望在页面首次加载到会话时执行一些数据处理比如从数据库或外部 API 拉取数据可以在me.page中传入on_load参数。简单处理器on_load处理器与普通事件处理器类似可以修改状态见 mesop/examples/on_load.pyimport mesop as me def on_load(e: me.LoadEvent): me.state(State).default_values [a, b] me.page(path/on_load, on_loadon_load) def app(): me.button(navigate to /on_load_generator, on_clicknavigate) me.text(/on_load str(me.state(State).default_values)) with me.box(): me.text(make sure this diffs - 2) def navigate(e: me.ClickEvent): me.navigate(/on_load_generator) me.stateclass class State: default_values: list[str]生成器处理器流式输出on_load还可以是生成器函数适合调用较慢或流式 API 的场景——在数据全部到达前先渲染中间结果。官方示例 mesop/examples/docs/on_load_generator.pyimport time import mesop as me def on_load(e: me.LoadEvent): state me.state(State) state.default_values.append(a) yield time.sleep(1) state.default_values.append(b) yield me.page(path/docs/on_load_generator, on_loadon_load) def app(): me.text(onload) me.text(str(me.state(State).default_values)) me.stateclass class State: default_values: list[str]从类型定义看mesop/runtime/runtime.pyOnLoadHandler可以是普通函数、生成器函数Generator、异步生成器AsyncGenerator或协程CoroutineContext.run_event_handler会按类型分别处理这几种返回形态见 mesop/runtime/context.py。进阶导航时携带查询参数多页应用中常常需要在跳转时传递查询参数比如列表页跳详情页时带上条目 ID。Mesop 推荐用me.navigate的query_params参数而不是把参数拼在 URL 字符串里。仓库中的 mesop/examples/query_params.py 给出了丰富的用法# 传递单个值与多个值 me.navigate( /examples/query_params/page_2, query_params{page2: [1, 2], single: a}, ) # 透传当前页面的全部查询参数 me.navigate(/examples/query_params/page_2, query_paramsme.query_params) # 携带需要 URL 编码的特殊字符 me.navigate( /examples/query_params/page_2, query_params{ url_encoded: should-be-escapedtrue, url_encoded_values: [value1a1, value2a2], }, )Context.navigate在拼装 URL 时会对 key 与 value 做urlparse.quote编码因此像should-be-escapedtrue这样的特殊字符也能安全传递见 mesop/runtime/context.py。若要在新标签页打开且保留当前查询参数使用me.navigate(url, open_in_new_tabTrue)即可同一会话的me.query_params还支持直接读写与删除配合on_load可以做页面加载即写参数等交互。小结至此你已掌握 Mesop 多页面应用的完整链路注册用me.page(path...)为每个 URL 路径注册页面组件所有页面须在服务启动时完成注册配置path、title、stylesheets、security_policy、on_load五个配置项覆盖了路由、标题、样式、安全与加载钩子导航me.navigate(url, query_params..., open_in_new_tab...)支持根相对路径、绝对 URL、查询参数传递与新标签页打开状态通过me.stateclass定义的状态在每个浏览器会话内唯一天然支持跨页面共享加载钩子on_load支持普通函数与生成器两种形态可做初始化与流式数据处理。更详细的 API 说明可继续阅读 页面 API 文档 与 导航命令文档如果你想了解单页应用的组件、State 与事件机制可回顾 核心概念。【免费下载链接】mesopRapidly build AI apps in Python项目地址: https://gitcode.com/GitHub_Trending/me/mesop创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考