如何设计一个可扩展的WordPress主题框架:从父主题到子主题的最佳实践?

好的,让我们开始设计一个可扩展的WordPress主题框架,从父主题到子主题的最佳实践。

主题框架设计:父主题的构建

一个好的主题框架应该具备以下几个关键特性:

  1. 模块化: 将主题功能分解为独立、可重用的模块。
  2. 可扩展性: 允许通过子主题覆盖和增强父主题的功能。
  3. 可维护性: 代码结构清晰、易于理解和修改。
  4. 性能优化: 加载速度快、资源利用率高。

1. 目录结构

一个清晰的目录结构是模块化的基础。建议采用以下结构:

parent-theme/
├── assets/               # 存放静态资源 (CSS, JS, 图片)
│   ├── css/
│   │   ├── style.css      # 主样式表
│   │   ├── custom.css     # 自定义样式
│   │   └── ...
│   ├── js/
│   │   ├── script.js     # 主脚本
│   │   ├── custom.js     # 自定义脚本
│   │   └── ...
│   ├── images/
│   │   └── ...
│   └── fonts/
│       └── ...
├── inc/                 # 存放 PHP include 文件 (主题核心功能)
│   ├── functions-theme.php  # 主题核心功能函数
│   ├── functions-admin.php  # 后台管理相关函数
│   ├── functions-widgets.php # 自定义小工具相关函数
│   ├── functions-hooks.php   # 自定义钩子相关函数
│   ├── functions-filters.php # 自定义过滤器相关函数
│   ├── customizer/          # 自定义主题设置 (Theme Customizer)
│   │   ├── customizer.php    # 自定义主题设置主文件
│   │   ├── sections/         # 自定义设置面板
│   │   │   ├── section-header.php
│   │   │   ├── section-footer.php
│   │   │   └── ...
│   │   ├── controls/         # 自定义设置控件
│   │   │   ├── control-color.php
│   │   │   ├── control-image.php
│   │   │   └── ...
│   └── template-tags.php  # 模板标签
├── languages/           # 存放翻译文件 (.po, .mo)
│   └── ...
├── templates/           # 存放通用模板
│   ├── template-parts/   # 存放模板片段
│   │   ├── content.php    # 文章内容模板
│   │   ├── content-page.php  # 页面内容模板
│   │   ├── content-single.php # 单篇文章内容模板
│   │   ├── header.php     # 页眉模板
│   │   ├── footer.php     # 页脚模板
│   │   └── ...
│   ├── page-templates/    # 存放页面模板
│   │   ├── template-home.php
│   │   ├── template-contact.php
│   │   └── ...
│   ├── 404.php             # 404 页面模板
│   ├── archive.php         # 归档页面模板
│   ├── index.php           # 主页模板
│   ├── page.php            # 页面模板
│   ├── single.php          # 单篇文章模板
│   └── search.php          # 搜索结果页面模板
├── README.md            # 主题说明文档
├── style.css            # 主题样式表 (必须)
└── functions.php        # 主题核心文件 (必须)

2. 核心文件:functions.php

functions.php 是主题的核心文件,负责加载主题的其他模块,并定义主题的基本功能。

<?php

/**
 * 主题核心文件
 */

// 定义主题常量
define( 'THEME_VERSION', '1.0.0' );
define( 'THEME_DIR', get_template_directory() );
define( 'THEME_URI', get_template_directory_uri() );

// 加载主题文本域 (用于翻译)
load_theme_textdomain( 'parent-theme', THEME_DIR . '/languages' );

// 引入主题支持
require_once THEME_DIR . '/inc/functions-theme.php';

// 引入后台管理功能
require_once THEME_DIR . '/inc/functions-admin.php';

// 引入自定义小工具
require_once THEME_DIR . '/inc/functions-widgets.php';

// 引入自定义钩子
require_once THEME_DIR . '/inc/functions-hooks.php';

// 引入自定义过滤器
require_once THEME_DIR . '/inc/functions-filters.php';

// 引入自定义主题设置
require_once THEME_DIR . '/inc/customizer/customizer.php';

// 注册导航菜单
register_nav_menus(
    array(
        'primary' => __( '主导航菜单', 'parent-theme' ),
        'footer'  => __( '页脚导航菜单', 'parent-theme' ),
    )
);

// 添加主题支持
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
add_theme_support( 'automatic-feed-links' );
add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption' ) );
add_theme_support( 'customize-selective-refresh-widgets' );
add_theme_support( 'responsive-embeds' );

// 设置内容宽度
if ( ! isset( $content_width ) ) {
    $content_width = 900;
}

// 注册和加载主题脚本和样式
function parent_theme_scripts() {
    // 注册样式
    wp_register_style( 'parent-theme-style', get_stylesheet_uri(), array(), THEME_VERSION );
    wp_register_style( 'parent-theme-custom', THEME_URI . '/assets/css/custom.css', array(), THEME_VERSION );

    // 注册脚本
    wp_register_script( 'parent-theme-script', THEME_URI . '/assets/js/script.js', array( 'jquery' ), THEME_VERSION, true );
    wp_register_script( 'parent-theme-custom', THEME_URI . '/assets/js/custom.js', array( 'jquery' ), THEME_VERSION, true );

    // 加载样式
    wp_enqueue_style( 'parent-theme-style' );
    wp_enqueue_style( 'parent-theme-custom' );

    // 加载脚本
    wp_enqueue_script( 'parent-theme-script' );
    wp_enqueue_script( 'parent-theme-custom' );

    // 传递 PHP 数据到 JavaScript
    wp_localize_script( 'parent-theme-script', 'theme_data', array(
        'ajax_url' => admin_url( 'admin-ajax.php' ),
        'nonce'    => wp_create_nonce( 'ajax_nonce' ),
    ) );
}
add_action( 'wp_enqueue_scripts', 'parent_theme_scripts' );

// 自定义 excerpt length
function parent_theme_excerpt_length( $length ) {
    return 40; // 返回自定义的 excerpt 长度
}
add_filter( 'excerpt_length', 'parent_theme_excerpt_length', 999 );

// 自定义 excerpt more
function parent_theme_excerpt_more( $more ) {
    return '...'; // 返回自定义的 excerpt more
}
add_filter( 'excerpt_more', 'parent_theme_excerpt_more' );

// 添加自定义 body class
function parent_theme_body_class( $classes ) {
    if ( is_front_page() ) {
        $classes[] = 'front-page';
    }

    if ( is_singular() ) {
        $classes[] = 'singular';
    }

    return $classes;
}
add_filter( 'body_class', 'parent_theme_body_class' );

3. 主题支持:inc/functions-theme.php

这个文件用于定义主题的基本支持功能,例如特色图像、HTML5 支持等。将其独立出来,方便管理和修改。

<?php

/**
 * 主题支持功能
 */

// 添加主题支持
function parent_theme_setup() {

    // 让主题支持特色图像
    add_theme_support( 'post-thumbnails' );

    // 添加自定义图像尺寸
    add_image_size( 'featured-image', 900, 600, true ); // 固定尺寸
    add_image_size( 'thumbnail-image', 150, 150, true );

    // 启用 HTML5 支持
    add_theme_support( 'html5', array(
        'search-form',
        'comment-form',
        'comment-list',
        'gallery',
        'caption',
    ) );

    // 启用自动 feed 链接
    add_theme_support( 'automatic-feed-links' );

    // 启用主题自定义 logo
    add_theme_support( 'custom-logo', array(
        'height'      => 100,
        'width'       => 400,
        'flex-height' => true,
        'flex-width'  => true,
        'header-text' => array( 'site-title', 'site-description' ),
    ) );

    // 启用主题自定义背景
    add_theme_support( 'custom-background', apply_filters( 'parent_theme_custom_background_args', array(
        'default-color' => 'ffffff',
        'default-image' => '',
    ) ) );

    // 启用主题自定义头部
    add_theme_support( 'custom-header', apply_filters( 'parent_theme_custom_header_args', array(
        'default-image'      => '',
        'default-text-color' => '000000',
        'header-text'        => true,
        'width'              => 1000,
        'height'             => 250,
        'flex-width'         => true,
        'flex-height'        => true,
    ) ) );

    // 启用主题选择性刷新小工具
    add_theme_support( 'customize-selective-refresh-widgets' );

    // 启用主题响应式嵌入
    add_theme_support( 'responsive-embeds' );
}
add_action( 'after_setup_theme', 'parent_theme_setup' );

4. 后台管理:inc/functions-admin.php

这个文件用于定义主题的后台管理功能,例如添加自定义菜单、设置页面等。

<?php

/**
 * 后台管理功能
 */

// 添加自定义管理菜单
function parent_theme_admin_menu() {
    add_menu_page(
        __( '主题设置', 'parent-theme' ),
        __( '主题设置', 'parent-theme' ),
        'manage_options',
        'parent-theme-settings',
        'parent_theme_settings_page',
        'dashicons-admin-generic',
        20
    );
}
add_action( 'admin_menu', 'parent_theme_admin_menu' );

// 创建设置页面
function parent_theme_settings_page() {
    ?>
    <div class="wrap">
        <h1><?php esc_html_e( '主题设置', 'parent-theme' ); ?></h1>
        <form method="post" action="options.php">
            <?php
                settings_fields( 'parent_theme_options' );
                do_settings_sections( 'parent-theme-settings' );
                submit_button();
            ?>
        </form>
    </div>
    <?php
}

// 注册设置
function parent_theme_register_settings() {
    register_setting(
        'parent_theme_options',
        'parent_theme_options',
        'parent_theme_sanitize_options'
    );

    add_settings_section(
        'parent_theme_general_section',
        __( '常规设置', 'parent-theme' ),
        'parent_theme_general_section_callback',
        'parent-theme-settings'
    );

    add_settings_field(
        'parent_theme_option_example',
        __( '示例选项', 'parent-theme' ),
        'parent_theme_option_example_callback',
        'parent-theme-settings',
        'parent_theme_general_section'
    );
}
add_action( 'admin_init', 'parent_theme_register_settings' );

// 常规设置回调
function parent_theme_general_section_callback() {
    echo '<p>' . esc_html__( '在这里设置常规选项', 'parent-theme' ) . '</p>';
}

// 示例选项回调
function parent_theme_option_example_callback() {
    $options = get_option( 'parent_theme_options' );
    $example = isset( $options['example'] ) ? esc_attr( $options['example'] ) : '';
    ?>
    <input type="text" name="parent_theme_options[example]" value="<?php echo $example; ?>" />
    <?php
}

// 清理设置
function parent_theme_sanitize_options( $input ) {
    $sanitized = array();
    if ( isset( $input['example'] ) ) {
        $sanitized['example'] = sanitize_text_field( $input['example'] );
    }
    return $sanitized;
}

5. 自定义小工具:inc/functions-widgets.php

这个文件用于注册和定义自定义小工具。

<?php

/**
 * 自定义小工具
 */

// 定义自定义小工具类
class Parent_Theme_Widget extends WP_Widget {

    /**
     * 构造函数
     */
    function __construct() {
        parent::__construct(
            'parent_theme_widget', // Base ID
            __( 'Parent Theme Widget', 'parent-theme' ), // Name
            array( 'description' => __( 'A Parent Theme Widget', 'parent-theme' ), ) // Args
        );
    }

    /**
     * 小工具前端显示
     *
     * @param array $args     显示小工具的参数
     * @param array $instance 保存设置的值
     */
    public function widget( $args, $instance ) {
        $title = apply_filters( 'widget_title', $instance['title'] );

        echo $args['before_widget'];
        if ( ! empty( $title ) ) {
            echo $args['before_title'] . $title . $args['after_title'];
        }
        echo __( 'Hello, World!', 'parent-theme' );
        echo $args['after_widget'];
    }

    /**
     * 小工具设置表单
     *
     * @param array $instance 先前保存设置的值
     */
    public function form( $instance ) {
        $title = isset( $instance['title'] ) ? $instance['title'] : __( 'New title', 'parent-theme' );
        ?>
        <p>
            <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
        </p>
        <?php
    }

    /**
     * 更新小工具设置
     *
     * @param array $new_instance 新设置的值
     * @param array $old_instance 先前设置的值
     *
     * @return array 更新后的设置值
     */
    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
        return $instance;
    }

} // class Parent_Theme_Widget

// 注册小工具
function parent_theme_register_widgets() {
    register_widget( 'Parent_Theme_Widget' );
}
add_action( 'widgets_init', 'parent_theme_register_widgets' );

6. 自定义钩子和过滤器:inc/functions-hooks.phpinc/functions-filters.php

这两个文件用于定义自定义的 WordPress 钩子和过滤器,允许子主题在不修改父主题代码的情况下,修改主题的行为和输出。

inc/functions-hooks.php:

<?php

/**
 * 自定义钩子
 */

// 定义一个自定义动作钩子
function parent_theme_custom_action() {
    // 执行一些操作
}
add_action( 'parent_theme_custom_hook', 'parent_theme_custom_action' );

// 使用自定义钩子
function parent_theme_example_function() {
    // 在这里触发自定义钩子
    do_action( 'parent_theme_custom_hook' );
}
add_action( 'wp_footer', 'parent_theme_example_function' );

inc/functions-filters.php:

<?php

/**
 * 自定义过滤器
 */

// 定义一个自定义过滤器
function parent_theme_custom_filter( $text ) {
    return 'Modified: ' . $text;
}
add_filter( 'parent_theme_custom_text', 'parent_theme_custom_filter' );

// 使用自定义过滤器
function parent_theme_example_function() {
    $original_text = 'Original Text';
    $modified_text = apply_filters( 'parent_theme_custom_text', $original_text );
    echo $modified_text;
}
add_action( 'wp_footer', 'parent_theme_example_function' );

7. 自定义主题设置:inc/customizer/

这个目录包含自定义主题设置相关的 PHP 文件,允许用户通过 WordPress 主题自定义工具修改主题的外观和行为。

inc/customizer/customizer.php:

<?php
/**
 * Theme Customizer functionality
 *
 * @package WordPress
 * @subpackage Parent Theme
 * @since Parent Theme 1.0
 */

/**
 * Sets up the WordPress core customizer and enqueues customizer styles.
 *
 * Note that this function is hooked into the after_setup_theme hook, which
 * runs before the init hook. Because of this, any styles enqueued inside
 * determined conditional logic must use late_static_binding (via static::).
 */
function parent_theme_customize_register( $wp_customize ) {

    // Add postMessage support for site title and description.
    $wp_customize->get_setting( 'blogname' )->transport         = 'postMessage';
    $wp_customize->get_setting( 'blogdescription' )->transport  = 'postMessage';
    $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage';

    if ( isset( $wp_customize->selective_refresh ) ) {
        $wp_customize->selective_refresh->add_partial( 'blogname', array(
            'selector'        => '.site-title a',
            'render_callback' => 'parent_theme_customize_partial_blogname',
        ) );
        $wp_customize->selective_refresh->add_partial( 'blogdescription', array(
            'selector'        => '.site-description',
            'render_callback' => 'parent_theme_customize_partial_blogdescription',
        ) );
    }

    // Include custom controls.
    require_once trailingslashit( get_template_directory() ) . '/inc/customizer/controls/control-color.php'; // Example
    // Include custom sections.
    require_once trailingslashit( get_template_directory() ) . '/inc/customizer/sections/section-header.php'; // Example

    // Register custom sections.
    Parent_Theme_Customize_Header_Section::register( $wp_customize ); // Example

    // Register custom controls.
    $wp_customize->register_control_type( 'Parent_Theme_Customize_Color_Control' ); // Example

    // Add Header Settings section.
    $wp_customize->add_section( 'header_settings', array(
        'title'    => __( 'Header Settings', 'parent-theme' ),
        'priority' => 30,
    ) );

    // Add Header Background Color setting and control.
    $wp_customize->add_setting( 'header_background_color', array(
        'default'           => '#ffffff',
        'sanitize_callback' => 'sanitize_hex_color',
        'transport'         => 'postMessage',
    ) );

    $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'header_background_color', array(
        'label'    => __( 'Header Background Color', 'parent-theme' ),
        'section'  => 'header_settings',
        'settings' => 'header_background_color',
    ) ) );

    // Example usage of custom control
    $wp_customize->add_setting(
        'custom_color_setting',
        array(
            'default'           => '#000000',
            'sanitize_callback' => 'sanitize_hex_color',
        )
    );

    $wp_customize->add_control(
        new Parent_Theme_Customize_Color_Control(
            $wp_customize,
            'custom_color_setting',
            array(
                'label'      => __( 'Custom Color', 'parent-theme' ),
                'section'    => 'header_settings',
                'settings'   => 'custom_color_setting',
            )
        )
    );
}
add_action( 'customize_register', 'parent_theme_customize_register' );

/**
 * Render the site title for the selective refresh partial.
 *
 * @return void
 */
function parent_theme_customize_partial_blogname() {
    bloginfo( 'name' );
}

/**
 * Render the site tagline for the selective refresh partial.
 *
 * @return void
 */
function parent_theme_customize_partial_blogdescription() {
    bloginfo( 'description' );
}

/**
 * Bind JS handlers to make Theme Customizer preview reload changes asynchronously.
 */
function parent_theme_customize_preview_js() {
    wp_enqueue_script( 'parent-theme-customizer', get_theme_file_uri( '/assets/js/customizer.js' ), array( 'customize-preview' ), THEME_VERSION, true );
}
add_action( 'customize_preview_init', 'parent_theme_customize_preview_js' );

/**
 * Enqueue customizer styles.
 */
function parent_theme_customize_css() {
    wp_enqueue_style( 'parent-theme-customizer', get_theme_file_uri( '/assets/css/customizer.css' ), array(), THEME_VERSION );
}
add_action( 'customize_controls_print_styles', 'parent_theme_customize_css' );

inc/customizer/sections/section-header.php:

<?php
/**
 * Customizer Header Section
 *
 * @package WordPress
 * @subpackage Parent Theme
 * @since Parent Theme 1.0
 */

if ( class_exists( 'WP_Customize_Section' ) ) {

    /**
     * Header Section
     */
    class Parent_Theme_Customize_Header_Section extends WP_Customize_Section {

        /**
         * The type of customize section being rendered.
         *
         * @since  1.0.0
         * @access public
         * @var    string
         */
        public $type = 'header';

        /**
         * Custom section json.
         *
         * @since  1.0.0
         * @access public
         * @return void
         */
        public function json() {
            $json = parent::json();
            $json['options'] = array( 'hide_title' => $this->hide_title );
            return $json;
        }

        /**
         * Init the section.
         *
         * @param WP_Customize_Manager $manager The WordPress Customize Manager.
         * @param string               $id      A Specific ID of the section.
         * @param array                $args    Section arguments.
         * @see WP_Customize_Section::__construct()
         */
        public function __construct( $manager, $id, $args = array() ) {
            parent::__construct( $manager, $id, $args );
        }

        /**
         * An Underscore (JS) template for rendering this section.
         *
         * Class variables for this section class are available in the `data`
         * object; export custom variables by overriding
         * {@see WP_Customize_Section::json()}.
         *
         * @see WP_Customize_Section::print_template()
         *
         * @access protected
         * @since 4.3.0
         */
        protected function render_template() {
            ?>
            <li id="accordion-section-{{ data.id }}" class="accordion-section control-section control-section-{{ data.type }}">
                <h3 class="accordion-section-title" tabindex="0">
                    {{ data.title }}
                    <# if ( data.description ) { #>
                        <button class="button-secondary section-description-button" type="button" aria-describedby="{{ data.id }}-description">{{ data.title }}</button>
                    <# } #>
                </h3>
                <# if ( data.description ) { #>
                    <div class="accordion-section-content description" id="{{ data.id }}-description">
                        {{{ data.description }}}
                    </div>
                <# } #>
                <ul class="accordion-section-content control-section-content">
                    <# data.controls.forEach( function( control ) { #>
                        <li>{{{ control }}}</li>
                    <# } ) #>
                </ul>
            </li>
            <?php
        }

        /**
         * Register custom section.
         *
         * @param WP_Customize_Manager $wp_customize Customize manager instance.
         * @since  1.0.0
         * @access public
         * @static
         */
        public static function register( $wp_customize ) {
            $wp_customize->register_section_type( 'Parent_Theme_Customize_Header_Section' );
        }
    }
}

inc/customizer/controls/control-color.php:

<?php
/**
 * Customizer Color Control
 *
 * @package WordPress
 * @subpackage Parent Theme
 * @since Parent Theme 1.0
 */

if ( class_exists( 'WP_Customize_Control' ) ) {

    /**
     * Custom Color Control Class
     */
    class Parent_Theme_Customize_Color_Control extends WP_Customize_Control {

        /**
         * The type of customize control being rendered.
         *
         * @since  1.0.0
         * @access public
         * @var    string
         */
        public $type = 'parent_theme_color';

        /**
         * Enqueue control related scripts/styles.
         *
         * @access public
         * @since 1.0.0
         * @return void
         */
        public function enqueue() {
            wp_enqueue_script( 'parent-theme-custom-controls-js', get_template_directory_uri() . '/assets/js/custom-controls.js', array( 'jquery', 'customize-controls', 'iris', 'underscore', 'wp-color-picker' ), THEME_VERSION, true );
            wp_enqueue_style( 'parent-theme-custom-controls-css', get_template_directory_uri() . '/assets/css/custom-controls.css', array( 'customize-controls', 'wp-color-picker' ), THEME_VERSION );
        }

        /**
         * Refresh the parameters passed to the JavaScript via JSON.
         *
         * @access public
         * @since 1.0.0
         * @uses WP_Customize_Control::json()
         * @return void
         */
        public function json() {
            $json = parent::json();

            return $json;
        }

        /**
         * An Underscore (JS) template for rendering this control in the customizer.
         *
         * Class variables for this control class are available in the `data`
         * object; export custom variables by overriding
         * {@see WP_Customize_Control::json()}.
         *
         * @see WP_Customize_Control::print_template()
         *
         * @access protected
         * @since 4.3.0
         */
        protected function render_template() {
            ?>
            <label>
                <# if ( data.label ) { #>
                    <span class="customize-control-title">{{{ data.label }}}</span>
                <# } #>
                <# if ( data.description ) { #>
                    <span class="description customize-control-description">{{{ data.description }}}</span>
                <# } #>
                <input class="color-picker-hex" type="text" data-palette="{{ data.palette }}" data-default-color="{{ data.default }}" value="{{ data.value }}" data-alpha="{{ data.alpha }}" />
            </label>
            <?php
        }
    }
}

8. 模板文件:templates/

这个目录包含主题的模板文件,例如 index.phpsingle.phppage.php 等。使用 get_template_part() 函数加载模板片段,提高代码的可维护性。

index.php:

<?php
/**
 * 主页模板
 */

get_header();
?>

<div id="primary" class="content-area">
    <main id="main" class="site-main">

        <?php
        if ( have_posts() ) :
            // 加载文章循环模板
            while ( have_posts() ) : the_post();
                get_template_part( 'templates/template-parts/content', get_post_format() );
            endwhile;

            // 分页
            the_posts_navigation();

        else :
            // 加载没有文章时的模板
            get_template_part( 'templates/template-parts/content', 'none' );

        endif;
        ?>

    </main><!-- #main -->
</div><!-- #primary -->

<?php
get_sidebar();
get_footer();
?>

templates/template-parts/content.php:

<?php
/**
 * 文章内容模板
 */
?>

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <header class="entry-header">
        <?php
        if ( is_singular() ) :
            the_title( '<h1 class="entry-title">', '</h1>' );
        else :
            the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
        endif;

        if ( 'post' === get_post_type() ) : ?>
        <div class="entry-meta">
            <?php parent_theme_posted_on(); ?>
        </div><!-- .entry-meta -->
        <?php
        endif; ?>
    </header><!-- .entry-header -->

    <div class="entry-content">
        <?php
            the_content( sprintf(
                __( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'parent-theme' ),
                get_the_title()
            ) );

            wp_link_pages( array(
                'before' => '<div class="page-links">' . __( 'Pages:', 'parent-theme' ),
                'after'  => '</div>',
            ) );
        ?>
    </div><!-- .entry-content -->

    <footer class="entry-footer">
        <?php parent_theme_entry_footer(); ?>
    </footer><!-- .entry-footer -->
</article><!-- #post-<?php the_ID(); ?> -->

9. 样式表:style.css

style.css 是主题的样式表,用于定义主题的样式。在父主题中,应该定义主题的基本样式,例如排版、颜色、布局等。

/*
Theme Name:   Parent Theme
Theme URI:    https://example.com/parent-theme/
Description:  Parent Theme Description
Author:       Author Name
Author URI:   https://example.com/
Template:
Version:      1.0.0
License:      GNU General Public License v2 or later
License URI:  http://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  parent-theme
*/

/* ------------------------------------------------------------
   主题基本样式
------------------------------------------------------------ */

body {
    font-family: sans-serif;
    line-height: 1.6;
    color: #333;
}

h1, h2, h3, h4, h5, h6 {
    font-weight: bold;
    margin-bottom: 1rem;
}

a {
    color: #007bff;
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

主题框架设计:子主题的构建

子主题允许在不修改父主题代码的情况下,修改主题的外观和行为。

1. 创建子主题

创建一个新的目录,作为子主题的根目录。例如,child-theme/

2. 创建 style.css 文件

在子主题的根目录下,创建一个 style.css 文件,并添加以下内容:


/*
Theme Name:   Child Theme
Theme URI:    https://example.com/child-theme/
Description:  Child Theme Description
Author:       Author Name
Author URI:   https://example.com/
Template:     parent-theme
Version:      1.0.0
License:      GNU General Public License v2 or later
License URI:  http://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  child-theme
*/

/* ------------------------------------------------------------
   子主题样式
------------------------------------------------------------ */

/* 覆盖父主题的样式 */
body {
    font-family: serif;
    color: #666;
}

/* 添加新的样式 */
.custom-class {
    color: red;

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注