分析 `wp_add_inline_script()` 和 `wp_add_inline_style()` 的源码,它们如何将内联代码插入到页面中?

大家好,欢迎来到今天的 “WordPress 内联代码大冒险” 讲座!我是你们今天的导游,我们将一起深入 wp_add_inline_script()wp_add_inline_style() 的源码腹地,看看它们是如何神不知鬼不觉地把内联代码塞进页面的。

准备好了吗?Let’s roll!

开场白:为什么要搞内联代码?

在正式开始之前,我们先来聊聊为什么要使用内联代码。想象一下,你有一个非常小的 JavaScript 片段,或者一些只有特定页面才需要的 CSS 样式。如果把它放在单独的文件里,浏览器就要多发一次 HTTP 请求,这在速度上是不划算的。这时候,内联代码就派上用场了,它可以直接嵌入到 HTML 页面中,减少请求次数,提高页面加载速度。

当然,内联代码也不是万能的。如果代码量太大,会增加 HTML 页面的体积,反而影响加载速度。所以,要根据实际情况权衡利弊。

第一站:wp_add_inline_script() 的源码剖析

我们先来看看 wp_add_inline_script() 这个函数。它的作用是在已注册的 JavaScript 脚本之后添加内联 JavaScript 代码。

function wp_add_inline_script( $handle, $data, $position = 'after' ) {
    global $wp_scripts;

    if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) {
        return false;
    }

    if ( empty( $handle ) || empty( $data ) ) {
        return false;
    }

    $script = $wp_scripts->registered[ $handle ] ?? null;

    if ( ! $script ) {
        return false;
    }

    $inline_script = trim( $data );

    if ( empty( $inline_script ) ) {
        return false;
    }

    if ( 'before' === $position ) {
        $wp_scripts->add_data( $handle, 'before', "n" . $inline_script . "n" );
    } else {
        $wp_scripts->add_data( $handle, 'after', "n" . $inline_script . "n" );
    }

    return true;
}
  • 参数解释:

    • $handle: 要附加内联脚本的脚本的句柄(handle)。这个句柄必须是已经通过 wp_register_script()wp_enqueue_script() 注册过的。
    • $data: 要添加的内联 JavaScript 代码字符串。
    • $position: 内联代码的位置,可以是 'before''after',默认是 'after'
  • 源码解读:

    1. 全局变量检查: 首先,它检查全局变量 $wp_scripts 是否存在,并且是 WP_Scripts 类的实例。如果不是,说明 WordPress 的脚本管理器还没有初始化,函数直接返回 false
    2. 参数验证: 接着,它检查 $handle$data 是否为空。如果为空,也直接返回 false
    3. 脚本句柄验证: 然后,它检查 $handle 对应的脚本是否已经注册。如果未注册,也返回 false。这里使用了 null coalescing operator (??) 来简化代码。
    4. 内联脚本内容处理:$data 进行 trim() 操作,去掉首尾的空白字符。
    5. 添加内联代码: 最后,根据 $position 的值,使用 $wp_scripts->add_data() 方法将内联代码添加到脚本的 beforeafter 属性中。这里会在内联代码前后添加换行符 n,以保证代码的可读性。
  • $wp_scripts->add_data() 的作用:

    $wp_scripts->add_data() 方法是 WP_Scripts 类中的一个重要方法,用于向已注册的脚本添加数据。在这里,它用于添加内联 JavaScript 代码。

    public function add_data( $handle, $key, $value ) {
        if ( ! isset( $this->registered[ $handle ] ) ) {
            return false;
        }
    
        if ( is_object( $this->registered[ $handle ] ) ) {
            if ( empty( $this->registered[ $handle ]->extra_data ) || ! is_array( $this->registered[ $handle ]->extra_data ) ) {
                $this->registered[ $handle ]->extra_data = array();
            }
            $this->registered[ $handle ]->extra_data[ $key ] = $value;
        } else {
            if ( empty( $this->registered[ $handle ][ 'extra' ] ) || ! is_array( $this->registered[ $handle ][ 'extra' ] ) ) {
                $this->registered[ $handle ][ 'extra' ] = array();
            }
            $this->registered[ $handle ][ 'extra' ][ $key ] = $value;
        }
    
        return true;
    }

    这个方法会将 $key$value 添加到 $wp_scripts->registered[$handle] 对象的 extra_data 属性中(如果 $wp_scripts->registered[$handle] 是一个对象),或者添加到 $wp_scripts->registered[$handle] 数组的 extra 键下(如果 $wp_scripts->registered[$handle] 是一个数组)。

  • 如何输出内联代码?

    内联代码并没有直接输出到页面上,而是被存储在 $wp_scripts 对象中。直到 wp_print_scripts() 函数被调用时,才会将内联代码和脚本一起输出。

    wp_print_scripts() 会遍历所有已注册的脚本,如果某个脚本有 beforeafter 属性,就会将这些属性中的内联代码输出到页面上。

    // 简化后的 wp_print_scripts() 相关代码
    foreach ( $this->queue as $handle ) {
        $script = $this->registered[ $handle ];
    
        // 输出 'before' 内联脚本
        if ( ! empty( $script->extra_data['before'] ) ) {
            foreach ( $script->extra_data['before'] as $data ) {
                printf( "<script type='text/javascript'>n%sn</script>n", $data );
            }
        }
    
        // 输出脚本
        $this->print_html( $script->handle, $script->src, $script->ver, $script->args );
    
        // 输出 'after' 内联脚本
        if ( ! empty( $script->extra_data['after'] ) ) {
            foreach ( $script->extra_data['after'] as $data ) {
                printf( "<script type='text/javascript'>n%sn</script>n", $data );
            }
        }
    }

    可以看到,wp_print_scripts() 会将 beforeafter 属性中的内联代码分别用 <script> 标签包裹起来,然后输出到页面上。

第二站:wp_add_inline_style() 的源码剖析

接下来,我们来看看 wp_add_inline_style() 这个函数。它的作用是在已注册的 CSS 样式之后添加内联 CSS 代码。

function wp_add_inline_style( $handle, $data ) {
    global $wp_styles;

    if ( ! is_a( $wp_styles, 'WP_Styles' ) ) {
        return false;
    }

    if ( empty( $handle ) || empty( $data ) ) {
        return false;
    }

    $style = $wp_styles->registered[ $handle ] ?? null;

    if ( ! $style ) {
        return false;
    }

    $inline_style = trim( $data );

    if ( empty( $inline_style ) ) {
        return false;
    }

    $wp_styles->add_data( $handle, 'after', "n" . $inline_style . "n" );

    return true;
}
  • 参数解释:

    • $handle: 要附加内联样式的样式的句柄(handle)。这个句柄必须是已经通过 wp_register_style()wp_enqueue_style() 注册过的。
    • $data: 要添加的内联 CSS 代码字符串。
  • 源码解读:

    wp_add_inline_style() 的源码结构和 wp_add_inline_script() 非常相似,只是把 $wp_scripts 换成了 $wp_stylesWP_Scripts 换成了 WP_Styles

    1. 全局变量检查: 检查全局变量 $wp_styles 是否存在,并且是 WP_Styles 类的实例。
    2. 参数验证: 检查 $handle$data 是否为空。
    3. 样式句柄验证: 检查 $handle 对应的样式是否已经注册。
    4. 内联样式内容处理:$data 进行 trim() 操作。
    5. 添加内联代码: 使用 $wp_styles->add_data() 方法将内联代码添加到样式的 after 属性中。注意,wp_add_inline_style() 只能在样式之后添加内联代码,没有 before 选项。
  • $wp_styles->add_data() 的作用:

    $wp_styles->add_data() 方法和 $wp_scripts->add_data() 的作用类似,都是用于向已注册的样式添加数据。

  • 如何输出内联代码?

    内联样式的输出方式和内联脚本类似,也是在 wp_print_styles() 函数被调用时输出。

    // 简化后的 wp_print_styles() 相关代码
    foreach ( $this->queue as $handle ) {
        $style = $this->registered[ $handle ];
    
        // 输出样式
        $this->print_html( $style->handle, $style->src, $style->ver, $style->args, $style->media );
    
        // 输出 'after' 内联样式
        if ( ! empty( $style->extra_data['after'] ) ) {
            foreach ( $style->extra_data['after'] as $data ) {
                printf( "<style type='text/css'>n%sn</style>n", $data );
            }
        }
    }

    wp_print_styles() 会将 after 属性中的内联样式用 <style> 标签包裹起来,然后输出到页面上。

第三站:实战演练:代码示例

光说不练假把式,我们来看几个实际的例子。

  • 示例 1:添加内联 JavaScript

    function my_enqueue_scripts() {
        wp_register_script( 'my-script', get_template_directory_uri() . '/js/my-script.js', array( 'jquery' ), '1.0', true );
        wp_enqueue_script( 'my-script' );
    
        $translation_array = array(
            'some_string' => __( 'Some string to translate', 'my-theme' ),
            'a_value'     => '10'
        );
        wp_localize_script( 'my-script', 'my_script_vars', $translation_array ); // 传递变量到js,实际上还是内联脚本
        wp_add_inline_script( 'my-script', 'console.log(my_script_vars);', 'before' ); // before
        wp_add_inline_script( 'my-script', 'console.log("Hello from inline script!");' ); // after
    }
    add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' );

    在这个例子中,我们首先注册并加载了一个名为 my-script 的 JavaScript 文件。然后,我们使用 wp_add_inline_script() 函数添加了两段内联 JavaScript 代码。其中一段代码会被添加到 my-script 之前,另一段代码会被添加到 my-script 之后。

    注意: wp_localize_script() 本质上也是通过 wp_add_inline_script() 实现的。它会将 PHP 变量转换成 JavaScript 对象,然后通过内联脚本的方式传递给 JavaScript 代码。

  • 示例 2:添加内联 CSS

    function my_enqueue_styles() {
        wp_register_style( 'my-style', get_template_directory_uri() . '/css/my-style.css', array(), '1.0' );
        wp_enqueue_style( 'my-style' );
    
        $custom_css = "
            .my-element {
                color: red;
                font-weight: bold;
            }
        ";
        wp_add_inline_style( 'my-style', $custom_css );
    }
    add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );

    在这个例子中,我们首先注册并加载了一个名为 my-style 的 CSS 文件。然后,我们使用 wp_add_inline_style() 函数添加了一段内联 CSS 代码,用于修改 .my-element 的样式。

第四站:注意事项和最佳实践

在使用 wp_add_inline_script()wp_add_inline_style() 时,有一些注意事项和最佳实践需要牢记:

  • 代码量: 内联代码应该尽量小,避免影响页面加载速度。如果代码量太大,建议放在单独的文件中。
  • 依赖关系: 内联代码可能会依赖于其他脚本或样式。确保这些依赖关系已经满足,否则可能会导致错误。
  • 代码组织: 尽量将内联代码组织好,使其易于阅读和维护。可以使用注释、缩进等技巧。
  • 性能优化: 考虑使用代码压缩工具来减小内联代码的体积。
  • 代码位置: 使用 wp_add_inline_script 时,beforeafter 的位置选择取决于你的代码逻辑。一般情况下,如果内联代码需要访问脚本文件中定义的变量或函数,应该放在 after 位置。
  • 句柄依赖: 确保你添加内联代码的句柄已经正确注册和加载。否则,内联代码不会被输出。

第五站:总结与展望

今天,我们一起探索了 wp_add_inline_script()wp_add_inline_style() 的源码,了解了它们是如何将内联代码插入到页面中的。

函数名 作用 参数
wp_add_inline_script() 在已注册的 JavaScript 脚本之后添加内联 JavaScript 代码 $handle (脚本句柄), $data (内联脚本代码), $position (位置,'before''after',默认为 'after')
wp_add_inline_style() 在已注册的 CSS 样式之后添加内联 CSS 代码 $handle (样式句柄), $data (内联 CSS 代码)
WP_Scripts->add_data() 向已注册的脚本添加数据(例如内联脚本) $handle (脚本句柄), $key (数据键,例如 'before''after'), $value (数据值,例如内联脚本代码)
WP_Styles->add_data() 向已注册的样式添加数据(例如内联样式) $handle (样式句柄), $key (数据键,例如 'after'), $value (数据值,例如内联样式代码)
wp_print_scripts() 输出所有已注册的 JavaScript 脚本和内联脚本
wp_print_styles() 输出所有已注册的 CSS 样式和内联样式

希望通过今天的讲座,大家对这两个函数有了更深入的理解,能够在实际开发中灵活运用。

当然,WordPress 的世界是不断变化的。未来,我们可能会有更多更好的方法来管理和优化内联代码。让我们一起期待吧!

感谢大家的参与,下次再见!

发表回复

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