资讯动态

Gutenberg 视口数据模块(core/viewport)完全指南:isViewportMatch 选择器、断点体系与响应式组件实践

发布时间:2026/9/16 18:44:10 来源:尧图企业网站定制
Gutenberg 视口数据模块core/viewport完全指南isViewportMatch 选择器、断点体系与响应式组件实践【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg本文围绕 Gutenberg 编辑器项目中的视口数据模块core/viewport展开系统讲解其数据存储结构、isViewportMatch选择器的查询语法与实现原理、标准断点体系以及基于该数据层构建响应式组件的两种高阶组件HOC用法。读完本文你将能够在自己的编辑器扩展中准确判断当前视口尺寸区间并写出随断点自动变化的 UI 逻辑。模块概览什么是 core/viewportcore/viewport是 Gutenberg 内置的视口数据模块负责响应浏览器视口尺寸的变化。它监听标准断点集合对应的媒体查询Media Query将匹配结果写入自有的 Redux store并对外暴露数据选择器与高阶组件供其他模块和自定义扩展实现随视口变化而改变行为的能力。其完整实现位于 packages/viewport 包模块注册后可通过wordpress/data的select()直接访问命名空间为core/viewport。包的对外入口 packages/viewport/src/index.ts 同时导出了 store 定义、withViewportMatch与ifViewportMatches两个高阶组件。// 注册位置packages/viewport/src/store/index.ts const STORE_NAME core/viewport; export const store createReduxStore( STORE_NAME, { reducer, actions, selectors, } ); register( store );从源码结构看该模块由 storereducer / actions / selectors与视口监听器listener两部分组成监听器把媒体查询结果灌入 store选择器则从 store 中读取布尔值供组件消费。标准断点体系与查询运算符视口模块预定义了一套标准断点阈值与编辑器样式变量_breakpoints.scss保持一致定义在 packages/viewport/src/index.ts断点名称像素宽度生效起点huge1440wide1280large960medium782small600mobile480查询由运算符 空格 断点名称组成运算符支持两种映射关系见 packages/viewport/src/types.ts运算符对应媒体查询条件max-width小于该宽度min-width大于等于该宽度默认运算符为。例如medium与 medium完全等价。核心选择器isViewportMatchisViewportMatch是core/viewport命名空间下唯一需要关心的选择器定义于 packages/viewport/src/store/selectors.ts。签名与行为参数stateViewportState视口状态对象是查询字符串 - 布尔值的映射参数queryViewportQuery查询字符串包含运算符与断点名称以空格分隔运算符默认返回值boolean表示当前视口是否匹配该查询。实现逻辑很直接若查询字符串中没有空格即省略了运算符自动补上前缀然后从 state 中按下标取值并转为布尔值export function isViewportMatch( state: ViewportState, query: ViewportQuery ): boolean { // 省略运算符时默认补 if ( query.indexOf( ) -1 ) { query query; } return !! state[ query ]; }在 React 组件中使用标准用法是通过useSelect订阅 store并在断点变化时自动触发重渲染packages/viewport/src/store/selectors.ts 中的官方示例import { store as viewportStore } from wordpress/viewport; import { useSelect } from wordpress/data; import { __ } from wordpress/i18n; const ExampleComponent () { const isMobile useSelect( ( select ) select( viewportStore ).isViewportMatch( small ), [] ); return isMobile ? ( div{ __( Mobile ) }/div ) : ( div{ __( Not Mobile ) }/div ); }; small表示视口宽度小于 600px此时组件渲染Mobile提示否则渲染Not Mobile。在非组件代码中读取由于core/viewport是标准的 Redux store也可以在非组件上下文如事件回调、工具函数中用select()同步读取当前视口状态import { select } from wordpress/data; import { store } from wordpress/viewport; const { isViewportMatch } select( store ); const isSmall isViewportMatch( medium ); // 宽度 782px const isWideOrHuge isViewportMatch( wide ); // 宽度 1280px // 等价写法const isWideOrHuge isViewportMatch( wide );注意与useSelect不同select()返回的是某一时刻的快照不会在断点变化后自动触发 UI 更新因此更适合用于一次性判断或命令式逻辑。状态数据的形状store 中的状态以规范化查询字符串为键。查询字符串由监听器统一生成形如 wide、 wide。这一点在测试用例中有明确体现packages/viewport/src/store/test/selectors.js// 传入 state 时省略运算符的 wide 会被归一化为 wide const result isViewportMatch( { wide: true, wide: false, }, wide ); expect( result ).toBe( true );底层原理媒体查询如何流入 store理解isViewportMatch的值从哪来有助于正确使用该模块。监听器matchMedia 与事件绑定模块入口 packages/viewport/src/index.ts 在加载时会调用addDimensionsEventListener( BREAKPOINTS, OPERATORS )其实现位于 packages/viewport/src/listener.ts。核心步骤将 6 个断点与 2 个运算符两两组合生成 12 个媒体查询字符串例如screen and (min-width: 782px)、screen and (max-width: 782px)用window.matchMedia为每个查询创建MediaQueryList并监听其change事件同时监听window的orientationchange事件以便移动设备旋转时及时刷新通过防抖函数setIsMatching收集所有查询的matches结果dispatchSET_IS_MATCHINGaction 写入 store初始化时立即执行一次并flush()保证首次读取即有正确值。值得注意的细节媒体查询被限定为screen and (...)作用域。源码注释解释了原因——打印页面时浏览器会按页面盒page box匹配若不限定screen打印状态会被误判为更窄的视口。Reducer 与 Actionreducerpackages/viewport/src/store/reducer.ts只处理一种 action 类型SET_IS_MATCHING直接将action.values整体替换为新的状态对象。对应的 action 创建函数setIsMatching定义于 packages/viewport/src/store/actions.ts并在 JSDoc 中标注ignore——因为它是内部专用不进入公开文档。这也印证了数据文档中的说明该模块的 actions 不应被直接使用开发者只需通过选择器读取状态即可。类型系统约束packages/viewport/src/types.ts 将断点名称限定为联合类型huge | wide | large | medium | small | mobile查询类型限定为BreakpointName | BreakpointName | BreakpointName。在 TypeScript 环境下拼写错误的断点名或非法运算符会在编译期直接报错这为查询字符串提供了静态安全保障。高阶组件把视口查询变成 props除了手动调用选择器wordpress/viewport还提供了两个高阶组件HOC把视口查询注入到组件的 props 中适合类组件或希望将响应式逻辑与渲染逻辑解耦的场景。withViewportMatch注入多个查询结果withViewportMatch接受一个prop 名 - 查询字符串的对象将每个查询的匹配结果作为对应 prop 传入被包裹组件实现见 packages/viewport/src/with-viewport-match.tsimport { withViewportMatch } from wordpress/viewport; function MyComponent( { isMobile } ) { return divCurrently: { isMobile ? Mobile : Not Mobile }/div; } MyComponent withViewportMatch( { isMobile: small } )( MyComponent );内部实现上它会在 HOC 渲染函数中把每个查询拆分为运算符 断点名并逐一调用wordpress/compose提供的useViewportMatchHook。源码中的注释特别指出由于查询来自静态配置、永不变化Hook 的调用顺序始终稳定因此没有违反 React Hooks 规则。ifViewportMatches条件渲染ifViewportMatches( query )返回一个 HOC 创建器当查询匹配时才渲染被包裹组件否则返回nullpackages/viewport/src/if-viewport-matches.tsfunction MyMobileComponent() { return divIm only rendered on mobile viewports!/div; } MyMobileComponent ifViewportMatches( small )( MyMobileComponent );它本质上是withViewportMatch与wordpress/compose中ifCondition的组合先注入isViewportMatchprop再根据该 prop 的真假决定是否渲染。Actions 与内部接口说明数据文档明确标注core/viewport的 actions 不应被直接使用。从代码看确实如此——唯一的 actionsetIsMatching只被内部监听器调用且被ignore标记为不公开。如果你需要响应视口变化正确做法是在组件中用useSelect( ( select ) select( viewportStore ).isViewportMatch( query ) )订阅状态在非组件逻辑中用select( store ).isViewportMatch( query )读取快照需要条件渲染时使用ifViewportMatches需要注入 props 时使用withViewportMatch。常见查询组合速查目标场景查询字符串含义仅手机竖屏小屏 small宽度 600px手机及以上 small或small宽度 600px平板及以上 medium宽度 782px桌面 large宽度 960px宽屏桌面 wide宽度 1280px超大屏 huge宽度 1440px需注意断点判断基于像素宽度阈值而非设备类型 medium与mobile设备在横屏时可能同时成立设计响应式 UI 时应结合具体内容布局取舍。延伸阅读包级完整文档含安装方式npm install wordpress/viewport与全部 APIpackages/viewport/README.md选择器实现packages/viewport/src/store/selectors.ts断点与运算符定义packages/viewport/src/index.ts类型定义packages/viewport/src/types.ts媒体查询监听原理packages/viewport/src/listener.ts选择器单元测试验证默认运算符行为packages/viewport/src/store/test/selectors.js【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价