分析 WordPress `body_class()` 函数的源码:如何通过 `body_class` 过滤器向 “ 标签添加 CSS 类。

各位观众老爷们,晚上好!今天咱们来聊聊 WordPress 里的一个“变脸大师”—— body_class() 函数。它能让你的 <body> 标签摇身一变,穿上各种不同的 CSS“衣服”,从而让你的网站页面更具针对性,更漂亮!

一、body_class() 是个啥?

简单来说,body_class() 函数的作用就是生成一系列 CSS 类,并将它们添加到 HTML 的 <body> 标签上。这些类可以根据不同的页面类型(比如首页、文章页、分类页等)、文章属性(比如文章 ID、分类 ID 等)以及其他条件动态生成。

想象一下,你有一个博客,首页想用一种风格,文章页想用另一种风格,分类页又想来点不一样的。如果没有 body_class(),你可能需要写一堆 JavaScript 代码来判断当前页面类型,然后手动添加 CSS 类。有了 body_class(),这些就都变得简单多了!

二、源码探秘:body_class() 的“变脸”原理

咱们来看看 body_class() 函数的源码,看看它到底是怎么变出这些 CSS 类的。不过别担心,咱们会一步步拆解,保证你能看得懂。

function body_class( $class = '' ) {
    // ...一些变量初始化...

    $classes = array();

    // 1. 添加一些默认的类
    $classes[] = $wp_query->is_rtl() ? 'rtl' : 'ltr';
    $classes[] = 'wp-embed-responsive';
    $classes[] = 'admin-bar'; //如果有管理栏显示
    if ( is_admin_bar_showing() ) {
       $classes[] = 'admin-bar-showing';
    }

    // 2. 根据页面类型添加类
    if ( is_front_page() ) {
        $classes[] = 'home';
    }
    if ( is_home() && ! is_front_page() ) {
        $classes[] = 'blog';
    }
    if ( is_archive() ) {
        $classes[] = 'archive';
    }
    if ( is_singular() ) {
        $classes[] = 'singular';
    }

    // ...更多页面类型判断...

    // 3. 根据文章属性添加类
    if ( is_single() ) {
        global $post;
        if ( isset( $post ) ) {
            $classes[] = 'postid-' . $post->ID;
            $classes[] = 'single-format-' . get_post_format( $post ); //例如 single-format-video
            $classes[] = 'single-' . $post->post_type; //例如 single-post
        }
    }

    // ...更多文章属性判断...

    // 4. 处理自定义的类
    if ( ! empty( $class ) ) {
        if ( ! is_array( $class ) ) {
            $class = preg_split( '#s+#', $class );
        }
        $classes = array_merge( $classes, $class );
    }

    // 5. 应用 'body_class' 过滤器
    $classes = apply_filters( 'body_class', $classes, $class );

    // 6. 去重和输出
    $classes = array_unique( $classes );
    $classes = array_map( 'esc_attr', $classes ); //转义
    $output = 'class="' . join( ' ', $classes ) . '"';
    echo $output;
}

代码有点长,但咱们可以把它分成几个部分来看:

  1. 初始化: 函数一开始会初始化一些变量,比如 $classes 数组,用来存储所有的 CSS 类。

  2. 添加默认类: 函数会添加一些默认的 CSS 类,比如 rtl(如果网站是 RTL 语言)、admin-bar(如果后台管理栏显示)等等。

  3. 根据页面类型添加类: 这是 body_class() 的核心部分。函数会根据不同的页面类型(比如首页、文章页、分类页等)添加相应的 CSS 类。比如,如果当前页面是首页,就会添加 home 类;如果当前页面是文章页,就会添加 single 类。

  4. 根据文章属性添加类: 对于文章页,函数还会根据文章的属性添加 CSS 类,比如文章 ID、分类 ID 等。比如,如果当前文章的 ID 是 123,就会添加 postid-123 类。

  5. 处理自定义类: body_class() 函数允许你传入自定义的 CSS 类。如果你传入了自定义类,函数会将它们添加到 $classes 数组中。

  6. 应用 ‘body_class’ 过滤器: 这个是重点!body_class() 函数会应用一个名为 'body_class' 的过滤器。通过这个过滤器,你可以修改 $classes 数组,添加、删除或修改 CSS 类。

  7. 去重和输出: 最后,函数会对 $classes 数组进行去重,然后将所有 CSS 类拼接成一个字符串,并输出到 <body> 标签的 class 属性中。

三、body_class 过滤器:CSS“变脸术”的精髓

body_class() 函数之所以强大,很大程度上要归功于 'body_class' 过滤器。通过这个过滤器,你可以轻松地向 <body> 标签添加 CSS 类,而无需修改 body_class() 函数的源码。

1. 如何使用 'body_class' 过滤器?

使用 'body_class' 过滤器非常简单,只需要在你的主题的 functions.php 文件中添加一个函数,并将该函数挂载到 'body_class' 过滤器上即可。

add_filter( 'body_class', 'my_custom_body_class' );

function my_custom_body_class( $classes ) {
    // 在这里添加、删除或修改 CSS 类

    // 比如,添加一个名为 'my-custom-class' 的 CSS 类
    $classes[] = 'my-custom-class';

    return $classes;
}

这段代码的作用是:每当 body_class() 函数被调用时,都会执行 my_custom_body_class() 函数。my_custom_body_class() 函数接收一个 $classes 数组作为参数,你可以在这个数组中添加、删除或修改 CSS 类,然后将修改后的 $classes 数组返回。

2. 'body_class' 过滤器的参数

'body_class' 过滤器接收两个参数:

  • $classes:一个数组,包含了 body_class() 函数已经生成的 CSS 类。
  • $class:传递给 body_class() 函数的自定义类(字符串或数组)。通常情况下,这个参数可以忽略。

3. 'body_class' 过滤器的用法示例

下面是一些使用 'body_class' 过滤器的示例:

  • 根据文章分类添加 CSS 类:
add_filter( 'body_class', 'add_category_body_class' );

function add_category_body_class( $classes ) {
    if ( is_single() ) {
        global $post;
        $categories = get_the_category( $post->ID );
        foreach ( $categories as $category ) {
            $classes[] = 'category-' . $category->slug;
        }
    }
    return $classes;
}

这段代码的作用是:如果当前页面是文章页,就获取该文章的所有分类,并将每个分类的 slug(别名)作为 CSS 类添加到 <body> 标签上。例如,如果一篇文章属于“新闻”和“科技”两个分类,那么 <body> 标签上就会添加 category-newscategory-technology 两个 CSS 类。

  • 根据用户角色添加 CSS 类:
add_filter( 'body_class', 'add_user_role_body_class' );

function add_user_role_body_class( $classes ) {
    global $current_user;
    wp_get_current_user();

    if ( is_user_logged_in() ) {
        $user_roles = $current_user->roles;
        foreach ( $user_roles as $role ) {
            $classes[] = 'user-role-' . $role;
        }
    }

    return $classes;
}

这段代码的作用是:如果用户已登录,就获取该用户的角色,并将每个角色作为 CSS 类添加到 <body> 标签上。例如,如果一个用户是管理员,那么 <body> 标签上就会添加 user-role-administrator 类。

  • 根据自定义字段添加 CSS 类:
add_filter( 'body_class', 'add_custom_field_body_class' );

function add_custom_field_body_class( $classes ) {
    if ( is_single() ) {
        $custom_field_value = get_post_meta( get_the_ID(), 'custom_field_name', true );
        if ( ! empty( $custom_field_value ) ) {
            $classes[] = 'custom-field-' . sanitize_title( $custom_field_value );
        }
    }
    return $classes;
}

这段代码的作用是:如果当前页面是文章页,就获取名为 custom_field_name 的自定义字段的值,并将该值作为 CSS 类添加到 <body> 标签上。注意要使用 sanitize_title() 函数对自定义字段的值进行处理,以确保生成的 CSS 类是有效的。

四、body_class() 函数的使用技巧

  • 不要滥用 CSS 类: 虽然 body_class() 函数很强大,但也不要滥用 CSS 类。添加过多的 CSS 类会使 HTML 代码变得臃肿,影响网站的性能。只添加那些真正需要的 CSS 类。

  • 使用有意义的 CSS 类名: CSS 类名应该具有描述性,能够清晰地表达其含义。比如,不要使用 class="style1" 这样的类名,而应该使用 class="home-page" 这样的类名。

  • 结合 CSS 选择器使用: body_class() 函数生成的 CSS 类可以与 CSS 选择器结合使用,以实现更精确的样式控制。比如,你可以使用 .home .entry-title 来设置首页文章标题的样式。

  • 避免与现有的 CSS 类冲突: 在添加自定义 CSS 类时,要避免与现有的 CSS 类冲突。如果你的主题或插件已经使用了某个 CSS 类名,那么你就不要再使用相同的类名。

五、body_class() 函数的常见应用场景

  • 根据页面类型设置不同的背景颜色:
.home {
    background-color: #f0f0f0; /* 首页背景颜色 */
}

.single {
    background-color: #ffffff; /* 文章页背景颜色 */
}

.archive {
    background-color: #e0e0e0; /* 归档页背景颜色 */
}
  • 根据文章分类显示不同的侧边栏:
add_filter( 'body_class', 'add_category_body_class' );

function add_category_body_class( $classes ) {
    if ( is_single() ) {
        global $post;
        $categories = get_the_category( $post->ID );
        foreach ( $categories as $category ) {
            $classes[] = 'category-' . $category->slug;
        }
    }
    return $classes;
}
<body <?php body_class(); ?>>
    <!-- ...页面内容... -->
    <?php if ( in_array( 'category-news', get_body_class() ) ) : ?>
        <!-- 新闻分类的侧边栏 -->
        <aside>
            <h3>新闻资讯</h3>
            <!-- ... -->
        </aside>
    <?php elseif ( in_array( 'category-technology', get_body_class() ) ) : ?>
        <!-- 科技分类的侧边栏 -->
        <aside>
            <h3>科技前沿</h3>
            <!-- ... -->
        </aside>
    <?php else : ?>
        <!-- 默认侧边栏 -->
        <aside>
            <h3>热门文章</h3>
            <!-- ... -->
        </aside>
    <?php endif; ?>
</body>
  • 根据用户角色显示不同的管理菜单:
add_filter( 'body_class', 'add_user_role_body_class' );

function add_user_role_body_class( $classes ) {
    global $current_user;
    wp_get_current_user();

    if ( is_user_logged_in() ) {
        $user_roles = $current_user->roles;
        foreach ( $user_roles as $role ) {
            $classes[] = 'user-role-' . $role;
        }
    }

    return $classes;
}
<body <?php body_class(); ?>>
    <!-- ...页面内容... -->
    <nav>
        <ul>
            <li><a href="#">首页</a></li>
            <li><a href="#">文章</a></li>
            <li><a href="#">关于</a></li>
            <?php if ( in_array( 'user-role-administrator', get_body_class() ) ) : ?>
                <!-- 管理员菜单 -->
                <li><a href="#">管理面板</a></li>
                <li><a href="#">用户管理</a></li>
            <?php endif; ?>
        </ul>
    </nav>
</body>

六、总结

body_class() 函数是 WordPress 中一个非常实用的函数,它可以让你轻松地向 <body> 标签添加 CSS 类,从而实现更灵活、更个性化的页面样式控制。通过 'body_class' 过滤器,你可以根据各种条件动态地添加 CSS 类,而无需修改 body_class() 函数的源码。掌握 body_class() 函数的使用方法,可以让你更好地控制 WordPress 网站的样式,提升用户体验。

咱们今天就先聊到这里。希望通过今天的讲解,你对 body_class() 函数有了更深入的了解。下次再见!

发表回复

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