Gutenberg FontFamilyControl 组件实战:基于 typography.fontFamilies 预设的字体族选择器
2026/9/17 1:17:07 网站建设 项目流程

Gutenberg FontFamilyControl 组件实战:基于 typography.fontFamilies 预设的字体族选择器

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

导读

FontFamilyControl是 Gutenberg 块编辑器(@wordpress/block-editor包)提供的一个 React 组件,它渲染一个下拉选择控件,让用户在编辑器侧边栏或自定义块设置面板中挑选字体族。该组件的核心数据来源是全局样式(Global Styles)中的typography.fontFamilies预设,并允许通过fontFamiliesprop 覆盖预设值。阅读完本文,你将掌握该组件的完整 Props 契约、在自定义块与全局样式排版面板中的接入方式,以及它在仓库源码中的真实实现与设置解析链路。

实验性功能警告:该组件当前仍处于实验阶段(experimental)。“实验性”意味着它是早期实现,未来可能发生大幅度的破坏性变更,在生产环境中使用时请关注版本升级日志。

FontFamilyControl 是什么

FontFamilyControl渲染一个用于选择字体族的用户界面,用户可以从由typography.fontFamilies预设定义的一组预置字体族中选择其一。可选地,你可以通过fontFamiliesprop 传入自定义字体族集合,从而覆盖预置字体族。

在仓库中,该组件位于 packages/block-editor/src/components/font-family/index.jsx,并从包入口 packages/block-editor/src/components/index.js 以实验性 API 形式导出:

export { default as __experimentalFontFamilyControl } from './font-family';

因此在业务代码中通常这样引入:

import { __experimentalFontFamilyControl as FontFamilyControl } from '@wordpress/block-editor';

基本用法

在自定义块(Block)的edit函数中,配合useState使用即可实现一个受控的字体族选择器:

import { useState } from 'react'; import { __experimentalFontFamilyControl as FontFamilyControl } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; // ... const MyFontFamilyControl = () => { const [ fontFamily, setFontFamily ] = useState( '' ); return ( <FontFamilyControl value={ fontFamily } onChange={ ( newFontFamily ) => { setFontFamily( newFontFamily ); } } /> ); }; // ... <MyFontFamilyControl />

核心要点:

  • value初始值为空字符串'',此时下拉框默认显示 “Default”(默认)选项;
  • onChange会在用户选中某个字体族后收到新的字体族值(即对应的fontFamilyCSS 值);
  • 当用户选择 “Default” 时,onChange会被调用但不带任何参数(见下文 Props 说明),业务侧应根据该语义执行“重置”逻辑。

Props 契约

组件接受以下 Props:

onChange(必填)

接收新字体族值的回调函数。

  • 类型:function
  • 必填:是

如果onChange被调用且未携带任何参数,则应当重置该值——具体“重置”的语义由使用场景决定,例如将字体族设为undefined,或恢复为某个起始值。

fontFamilies(可选)

用户提供的字体族集合,用于覆盖来自预设(presets)的预置字体族。

  • 类型:Array
  • 必填:否

字体族以对象数组形式提供,schema 如下:

属性描述类型
fontFamily字体族,用法与 CSS 中的取值一致string
name字体族的可选显示名称string

例如:

const fontFamilies = [ { fontFamily: '"Inter", sans-serif', name: 'Inter' }, { fontFamily: '-apple-system,system-ui,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif', name: 'System Font', }, ];

仓库中的 Storybook 示例 packages/block-editor/src/components/font-family/stories/index.story.jsx 展示了更贴近真实场景的数据结构——除了fontFamilyname外,还可以携带slug以及fontFace(字面量fontFamily描述 +src字体文件地址等),例如:

{ fontFace: [ { fontFamily: 'Inter', fontStretch: 'normal', fontStyle: 'normal', fontWeight: '200 900', src: [ 'file:./assets/fonts/inter/Inter-VariableFont_slnt,wght.ttf' ], }, ], fontFamily: '"Inter", sans-serif', name: 'Inter', slug: 'inter', }

value(可选)

当前字体族的值。

  • 类型:String
  • 必填:否
  • 默认值:''

其他 Props

其余所有未列出的 Props 都会被透传(spread)给底层的CustomSelectControl实例,例如labelclassNamesize等均可按需覆盖。

源码级实现剖析

FontFamilyControl的实现非常精简,完整逻辑集中在 packages/block-editor/src/components/font-family/index.jsx 一个文件中,可拆解为以下四个步骤:

1. 读取全局设置中的预设字体族

const [ blockLevelFontFamilies ] = useSettings( 'typography.fontFamilies' ); if ( ! fontFamilies ) { fontFamilies = blockLevelFontFamilies; }

组件通过useSettings( 'typography.fontFamilies' )从块编辑上下文中读取设置。useSettings的实现见 packages/block-editor/src/components/use-settings/index.js:它会先基于当前块的clientId,在块实例层级链中向上查找设置;找不到时再回退到块编辑器的全局设置。其底层委托给 store 的私有选择器getBlockSettings(packages/block-editor/src/store/get-block-settings.js),后者会沿着块层级向上遍历,并收集所有声明了__experimentalSettings块支持的祖先块设置。这也意味着:主题或父级块在typography.fontFamilies中定义的预设会自动成为该下拉框的数据源

2. 空数据保护

if ( ! fontFamilies || fontFamilies.length === 0 ) { return null; }

当没有任何预设字体族时,组件直接渲染null——因此不会出现一个空的下拉框。

3. 组装选项列表

const options = [ { key: '', name: __( 'Default' ), }, ...fontFamilies.map( ( { fontFamily, name } ) => ( { key: fontFamily, name: name || fontFamily, style: { fontFamily }, } ) ), ];
  • 第一项固定为key: ''、显示名 “Default”,即“跟随默认/重置”选项;
  • 每个预设字体族映射为一个选项,key使用fontFamily的 CSS 值,name优先取name字段、缺省时回退为fontFamily
  • 每个选项还附带style: { fontFamily },因此下拉列表中的每一项会以自身字体渲染,让用户直观预览字体效果。

4. 渲染 CustomSelectControl

const selectedValue = options.find( ( option ) => option.key === value ) ?? ''; return ( <CustomSelectControl label={ __( 'Font' ) } value={ selectedValue } onChange={ ( { selectedItem } ) => onChange( selectedItem.key ) } options={ options } className={ clsx( 'block-editor-font-family-control', className ) } { ...props } /> );
  • 底层实际是@wordpress/componentsCustomSelectControl,默认 label 为 “Font”;
  • selectedValue根据传入的value在选项中查找对应项;若未找到(例如value不在预设中),回退为''
  • 选中项通过onChange( selectedItem.key )回传。特别地,当选中 “Default” 项时selectedItem.key'',即对应 README 中“无参数调用时表示重置”的语义约定(在实现层面表现为回调''空字符串);
  • 自定义className会与内置的block-editor-font-family-control合并。

在全局样式排版面板中的真实调用

FontFamilyControl并非孤立组件,它在编辑器内置的“排版(Typography)”全局样式面板中被实际使用,位置在 packages/block-editor/src/components/global-styles/typography-panel.jsx:

<FontFamilyControl fontFamilies={ fontFamilies } value={ fontFamily } onChange={ setFontFamily } />

调用上下文要点:

  • 只有当设置settings.typography.fontFamilies中存在至少一个字体族(useHasFontFamilyControl会逐项检查各字体的长度,见同文件第 112-115 行)时,该控件才会渲染;
  • 它被包裹在InheritanceToolsPanelItem中,支持“继承”语义与重置(onDeselect={ resetFontFamily });
  • 面板通过useMemosettings.typography.fontFamilies处理成fontFamilies数据(含fontFamilyname),直接喂给组件。

这为自定义块接入提供了范本:将组件嵌入你自己的InspectorControls或面板,并维护好value/onChange即可。

与 theme.json 预设的关联

typography.fontFamilies预设通常由主题的theme.json定义。在根目录的 lib/theme.json 中即可找到 Gutenberg 插件自身使用的字体预设配置。数据结构与组件期望的 schema 完全对应:

"typography": { "fontFamilies": [ { "fontFamily": "var(--wp--preset--font-family--system-font)", "name": "系统字体", "slug": "system-font" } ] }

这意味着:主题开发者只需在theme.jsonsettings.typography.fontFamilies中声明字体族(fontFamilynameslug,可选fontFace),FontFamilyControl便会自动把这些字体呈现为可选项,无需在组件层重复声明——这正是“预设优先、prop 覆盖”设计的意义所在。

总结与注意事项

  • 接入方式:以__experimentalFontFamilyControl命名从@wordpress/block-editor导出,作为受控组件使用,必填onChange,可选valuefontFamilies
  • 数据流:未传fontFamilies时自动读取typography.fontFamilies设置(块级覆盖全局,回退到编辑器设置),为空时渲染null
  • 选项语义:内置 “Default” 项(key 为''),选中它即代表“重置”,onChange回调'';其余选项 key 为字体族的 CSS 值,并以name(缺省回退fontFamily)为显示名,且每项按自身字体族渲染预览;
  • 透传机制:其余 props 直接透传给底层CustomSelectControl,可进一步定制 label、className 等;
  • 实验性风险:组件仍为实验性 API,未来版本可能调整 Props 或导出命名(例如当前实现已移除__next40pxDefaultSize迁移 prop,该 prop 自 WordPress 7.1 起已默认生效,代码中标记为 deprecated),升级依赖时请留意变更日志。

仓库内可供进一步研读的相关文件:

  • 组件实现
  • 组件 README
  • Storybook 示例
  • 包导出入口
  • 设置读取 Hook useSettings
  • 设置解析选择器 getBlockSettings
  • 全局样式排版面板中的调用
  • Gutenberg 插件自身的字体预设配置

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询