短代码系统
短代码系统允许在 CMS 内容和主题模板中嵌入 React 组件,类似 WordPress 的 shortcode 功能。插件和主题都可以注册和使用短代码。
架构
PHP 后端 前端 React
┌─────────────┐ ┌──────────────────┐
│ 短代码注册 │ │ 组件注册表 │
│ Shortcode │──HTML────▶│ mountReactComp. │
│ API │ 标记 │ useReactComp. │
└─────────────┘ └──────────────────┘内置短代码
系统默认提供以下短代码:
[Anon_Plugin_Editor] - Markdown 编辑器
属性:
placeholder- 占位符文本(默认:"开始写作...")height- 编辑器高度(默认:"400px")preview- 是否显示预览标签页:true/false(默认:true)
示例:
[Anon_Plugin_Editor placeholder="输入内容..." height="300px"][Anon_Plugin_Gallery] - 图片画廊
属性:
images- 图片 URL 列表,逗号分隔(必需)columns- 列数:1-4(默认:3)gap- 间距(默认:16)
示例:
[Anon_Plugin_Gallery images="url1,url2,url3" columns="2" gap="12"][Anon_Plugin_Alert] - 警告框
属性:
type- 类型:info/success/warning/error(默认:info)title- 标题(可选)closable- 是否可关闭:true/false(默认:true)
示例:
[Anon_Plugin_Alert type="success" title="操作成功" closable="true"]使用方式
在文章内容中使用
直接在文章内容的 Markdown 或 HTML 中写入短代码:
markdown
这是一段普通文本。
[Anon_Editor placeholder="输入内容..." height="400px"]
[Anon_Gallery images="url1,url2,url3" columns="3"]
这是另一段文本。在主题模板中使用
在主题的 PHP 模板文件中调用:
php
<?php
// 解析内容中的短代码
$content = get_post_content();
$content = Anon_System_Shortcode::do_shortcode($content);
echo $content;
?>扩展短代码
插件和主题都可以通过钩子注册自定义短代码:
PHP 端注册
php
<?php
// 监听短代码注册钩子
Anon_System_Hook::add_action('anon_register_shortcodes', function() {
// 注册自定义短代码
Anon_System_Shortcode::add_shortcode('Anon_Code', function($attrs) {
return Anon_System_Shortcode::render_react_component('CodeEditor', [
'language' => $attrs['language'] ?? 'javascript',
'height' => $attrs['height'] ?? '300px',
]);
});
});前端注册组件
在 dev_cms_admin/src/components/ReactComponents/index.ts 中注册对应的 React 组件:
typescript
import { registerReactComponent } from '@/hooks/useReactComponents'
import { CodeEditor } from './CodeEditor'
export function registerAllComponents() {
registerReactComponent('MarkdownEditor', MarkdownEditor)
registerReactComponent('ImageGallery', ImageGallery)
registerReactComponent('AlertBox', AlertBox)
// 注册自定义组件
registerReactComponent('CodeEditor', CodeEditor)
}创建 React 组件
创建组件文件 dev_cms_admin/src/components/ReactComponents/CodeEditor.tsx:
tsx
interface CodeEditorProps {
language?: string
height?: string
}
export function CodeEditor({
language = 'javascript',
height = '300px'
}: CodeEditorProps) {
return (
<div className="code-editor" style={{ height }}>
{/* 编辑器实现 */}
</div>
)
}API 参考
PHP API
Anon_System_Shortcode::add_shortcode(string $tag, callable $callback)
注册一个短代码。
参数:
$tag- 短代码标签名称$callback- 回调函数,接收属性数组,返回 HTML 字符串
示例:
php
Anon_System_Shortcode::add_shortcode('MyTag', function($attrs) {
return '<div>Custom content</div>';
});Anon_System_Shortcode::do_shortcode(string $content): string
解析内容中的短代码。
参数:
$content- 包含短代码的内容
返回:
- 解析后的 HTML 内容
示例:
php
$content = Anon_System_Shortcode::do_shortcode($post_content);
echo $content;Anon_System_Shortcode::render_react_component(string $component_name, array $props = []): string
生成 React 组件挂载点 HTML。
参数:
$component_name- React 组件名称$props- 传递给组件的属性
返回:
- HTML 标记字符串
示例:
php
$html = Anon_System_Shortcode::render_react_component('MyComponent', [
'title' => 'Hello',
'count' => 42
]);React API
registerReactComponent(name: string, component: React.ComponentType)
注册一个 React 组件供短代码使用。
示例:
typescript
import { registerReactComponent } from '@/hooks/useReactComponents'
import { MyComponent } from './MyComponent'
registerReactComponent('MyComponent', MyComponent)useReactComponentMounter(dependencies?: any[])
Hook,自动扫描并挂载页面上的 React 组件。
示例:
typescript
import { useReactComponentMounter } from '@/hooks'
function MyPage({ content }) {
const { remount } = useReactComponentMounter([content])
useEffect(() => {
remount()
}, [content])
return <div dangerouslySetInnerHTML={{ __html: content }} />
}mountReactComponents()
手动触发组件挂载。
示例:
typescript
import { mountReactComponents } from '@/hooks/useReactComponents'
fetchContent().then(content => {
setContent(content)
setTimeout(() => mountReactComponents(), 0)
})最佳实践
属性验证
在 PHP 端验证和清理属性:
php
Anon_System_Shortcode::add_shortcode('SafeComponent', function($attrs) {
if (empty($attrs['required_field'])) {
return '<div class="error">缺少必需属性</div>';
}
$count = max(1, min(100, intval($attrs['count'] ?? 10)));
$title = htmlspecialchars($attrs['title'] ?? '', ENT_QUOTES, 'UTF-8');
return Anon_System_Shortcode::render_react_component('SafeComponent', [
'title' => $title,
'count' => $count,
]);
});错误处理
在 React 组件中添加错误边界:
tsx
import { useState, useEffect } from 'react'
export function RobustComponent(props: any) {
const [error, setError] = useState<string | null>(null)
useEffect(() => {
try {
if (!props.requiredProp) {
throw new Error('缺少必需属性')
}
} catch (e) {
setError(e instanceof Error ? e.message : '未知错误')
}
}, [props])
if (error) {
return <div className="error">组件错误: {error}</div>
}
return <div>正常内容</div>
}相关文件
- 核心类:
core/Modules/System/Shortcode.php - React Hook:
dev_cms_admin/src/hooks/useReactComponents.tsx - 组件目录:
dev_cms_admin/src/components/ReactComponents/
