标签: WordPress主题开发

  • WordPress主题使用Google PageSpeed Insights 提示:未使用被动式监听器来提高滚动性能的警告的解决办法

    WordPress主题使用Google PageSpeed Insights 提示:未使用被动式监听器来提高滚动性能的警告的解决办法

    在使用 PageSpeed Insights 测试我们的WordPress站点的使用,如果前端加载了jQuery库,我们往往会收到一条「未使用被动式监听器来提高滚动性能」的警告,谷歌建议我们将触摸和滚轮事件监听器标记为 `passive`,以提高页面的滚动性能。

    为什么出现未使用被动式监听器的警告

    在浏览器渲染网页的过程中,默认情况下,浏览器会主动监听绑定到触摸和滚动事件,根据该事件的运行结果和是否阻止浏览器的默认行为来判断是否执行默认操作。比如我们可以在 touchstart 事件调用 preventDefault ,这时,浏览器会禁用该事件的默认操作,不会滚动或缩放。

    而浏览器无法预先知道一个监听器会不会调用 preventDefault(),它需要等监听器执行完后,再去执行默认行为,而监听器执行是要耗时的,这样就会导致页面卡顿。更深入的解释参考:移动Web滚动性能优化: Passive event listeners

    让WordPress内置的jQuery使用被动式监听器的办法

    如果我们把监听器的监听方式改为被动的,就可以消除掉这个延时,提高网页的触摸和滚动性能。虽然这个警告不会直接影响PageSpeed Insights的评分,解决掉这个延时后,对提高网页的用户体验还是有一些帮助的。

    截止本文发布之日,WordPress内置的jQuery尚不支持这个操作。很幸运的是,我们可以通过一段简单的代码来为jQuery加上这个支持。

    add_action('wp_enqueue_scripts', function ()
    {
        wp_add_inline_script('jquery', '
        jQuery.event.special.touchstart = {
            setup: function( _, ns, handle ) {
                    this.addEventListener("touchstart", handle, { passive: !ns.includes("noPreventDefault") });
                }
            };
            jQuery.event.special.touchmove = {
                setup: function( _, ns, handle ) {
                    this.addEventListener("touchmove", handle, { passive: !ns.includes("noPreventDefault") });
                }
            };
            jQuery.event.special.wheel = {
                setup: function( _, ns, handle ){
                    this.addEventListener("wheel", handle, { passive: true });
                }
            };
            jQuery.event.special.mousewheel = {
                setup: function( _, ns, handle ){
                    this.addEventListener("mousewheel", handle, { passive: true });
                }
            };'
        );
    }, 999);

    如果您的网站中没有使用jQuery,依然出现了未使用被动式监听器来提高滚动性能的警告,可以参考以上代码中的this.addEventListener 部分修改您的代码,来实现被动式监听。

  • WordPress导航类主题 uziwp_nav

    WordPress导航类主题 uziwp_nav

    演示地址:https://gkxyz.com

    2022.09.02

    • 主题初始化,主题需要依赖安装`Advanced Custom Fields 专业版`
    • 后台可以自定义设置首页出现的类别
    • 单页中可以关联推荐的站点、文章内容
    • 基于Bootstrap,兼容电脑pc端、手机wap端
    • 保密模式,所有内页内容可以设置需要输入密码才能访问。
  • WordPress企业类主题 uziwp_twentytwentytwo

    WordPress企业类主题 uziwp_twentytwentytwo

    站点演示:https://uziwp.com

    本主题售价:¥899. !!!非诚勿扰!!!,购买地址:uziwp_twentytwentytwo 企业类主题 – 柚子科技 WordPress 主题、WordPress插件

    20221011

    • 新增右侧工具栏产品类内容(可以自定义设置显示分类ID)

    20220806

    • 增加幻灯片banner的文字填入功能,可以设置标题、副标题、正文等。
    • 细化文章列表中显示标签、分类功能.
    • 新增“栏目新闻”等模块。
    • 新增后台全局自定义文字颜色、链接颜色等。
    • 修改页脚栏目,移动到小工具的功能。
    • 兼容多端设备PC电脑端,手机,平板.
    • 新增访问密码设置,内容区域需要输入密码才能访问。
    • 新增模块自选功能,首页内容,可以自定义模块。
  • WordPress:获取当前页面菜单的current menu item,输出在菜单中的子菜单get sub menu

    WordPress:获取当前页面菜单的current menu item,输出在菜单中的子菜单get sub menu

    遇到一个问题,要显示当前页面的面包屑导航,只是这个面包屑路径反应的不是页面自身的层级关系,而是该页面在菜单导航中的位置。因此需要检测该页面所在菜单的current menu item,在stackexchange上找到了一个不错的方法,记录一下。

    使用wp_nav_menu_objects filter查找current menu item,在调用wp_nav_menu之前先过滤一下这个filter的值,找到current menu item,将需要的信息,例如menu ID,标题或url等,记录到一个全局变量里。等调用完wp_nav_menu后,就可以使用这个全局变量显示信息了。

    在当前菜单中做一下记号

    add_filter( 'wp_nav_menu_objects', 'uzi_wp_nav_menu_objects' );
    function uzi_wp_nav_menu_objects( $sorted_menu_items )
    {
        foreach ( $sorted_menu_items as $menu_item ) {
            if ( $menu_item->current ) {
                $_SESSION['uzi_current_menu'] = $menu_item;
                break;
            }
        }
        return $sorted_menu_items;
    }

    全局变量$_SESSION['uzi_current_menu']记录了当前菜单的current menu item的标题。

    一些比较有用的信息如下

    $menu_item->ID - Menu ID
    $menu_item->title - 该菜单项名称
    $menu_item->post_title - Post Title,不一定和菜单项名称相同
    $menu_item->url -  固定链接
    $menu_item->object_id - post ID
    $menu_item->post_parent - Post Parent(例如page的parent page)
    $menu_item->menu_item_parent - 指在该菜单中的层级关系

    输出main-nav菜单中,当前页面所在菜单的子菜单

    $locations = get_nav_menu_locations();
    $menu = wp_get_nav_menu_object($locations['main-nav']); // primary' is our nav menu's name
    $menu_items = wp_get_nav_menu_items($menu->term_id);
    // var_dump($menu,$_SESSION['uzi_current_menu']->ID,$menu_items);
    if (!empty($menu_items)) {
        echo '<ul>';
        foreach ($menu_items as $menu_item) {
            if($menu_item->menu_item_parent == $_SESSION['uzi_current_menu']->ID
               || $menu_item->menu_item_parent == $_SESSION['uzi_current_menu']->			if ($menu_item->menu_item_parent == $_SESSION['uzi_current_menu']->ID
    				|| ($menu_item->menu_item_parent == $_SESSION['uzi_current_menu']->menu_item_parent && 0 != $menu_item->menu_item_parent)
    			) {
    				//判断当前页面是该菜单项的子项
    				if (is_page($menu_item->object_id) || is_category($menu_item->object_id)) {
    					echo '<li class="current-menu-item">';
    				} else {
    					echo '<li>';
    				}
    				echo '<a href="' . $menu_item->url . '">' . $menu_item->title . '</a>';
    				echo '</li>';
    			}        
        }
        echo '</ul>';
    }
  • WordPress更改`在此输入标题`占位符提示文字 #title-prompt-text

    WordPress更改`在此输入标题`占位符提示文字 #title-prompt-text

    WordPress默认在撰写新文章时,在标题输入文本框内有一个“在此输入标题”占位符提示文字。

    <label class="" id="title-prompt-text" for="title">添加标题</label>

    2022腾讯云新春特惠购买直达链接:https://www.jiloc.com/go/qcloud-act

    当我们创建自定义的文章类型,想改变这个提示,但却没有默认参数来改变这个文字,可以通过下面的代码改变这个提示文字。

    function change_title_text($title)
    {
        $screen = get_current_screen();
        if ('movie' == $screen->post_type) {
            $title = __('输入影片名.Enter the movie name', 'jvsn');
        }
        return $title;
    }
    add_filter('enter_title_here', 'change_title_text');
    

    通过创建函数 change_title_text,检查是否存在一个特定的自定义类型,然后通过过滤器enter_title_here,更改默认的标题提示文字,修改其中的 movie 为自定义分类法名称。

  • WordPress主题插件开发save_post hook 钩子 修改文章发表状态 图文教程

    WordPress主题插件开发save_post hook 钩子 修改文章发表状态 图文教程

    老季最近在开发一个插件,需要在保存文章的hook钩子中修改文章的状态,这里记录一下具体的方法。

    这里要先移除保存文章的钩子然后再更新文章状态(不然会造成服务器500错误),然后再把钩子重新启用。官方说明文档如下:

    Avoiding infinite loops

    If you are calling a function such as wp_update_post that includes the save_post hook, your hooked function will create an infinite loop. To avoid this, unhook your function before calling the function you need, then re-hook it afterward.

    // this function makes all posts in the default category private
     
    function set_private_categories($post_id) {
        // If this is a revision, get real post ID
        if ( $parent_id = wp_is_post_revision( $post_id ) ) 
            $post_id = $parent_id;
     
        // Get default category ID from options
        $defaultcat = get_option( 'default_category' );
     
        // Check if this post is in default category
        if ( in_category( $defaultcat, $post_id ) ) {
            // unhook this function so it doesn't loop infinitely
            remove_action( 'save_post', 'set_private_categories' );
     
            // update the post, which calls save_post again
            wp_update_post( array( 'ID' => $post_id, 'post_status' => 'draft' ) );
     
            // re-hook this function
            add_action( 'save_post', 'set_private_categories' );
        }
    }
    add_action( 'save_post', 'set_private_categories' );

    WordPress官方手册:https://developer.wordpress.org/reference/hooks/save_post/

  • WordPress 自定义文章类型 固定链接 使用.html 后缀 图文教程

    WordPress 自定义文章类型 固定链接 使用.html 后缀 图文教程

    当我们创建了自定义类型文章之后,默认的`固定链接`即使设置成 /%postname%.html ,自定义文章的后缀也不带.html ,所以我们记录一下通过代码的方式来实现。

    比如我们这里使用案例的类型

    /jiloc-case/postname //默认url路径

    /jiloc-case/postname.html //修改之后的url路径

    /**
     * 设置多种自定义文章类型的固定链接结构为 post_name.html
     */
    $mytypes = array(//根据需要添加你的自定义文章类型
            'case' => 'jiloc-case',
    	'product' => 'jiloc-product',
    );
    add_filter('post_type_link', 'my_custom_post_type_link', 1, 3);
    function my_custom_post_type_link( $link, $post = 0 ){
        global $mytypes;
        if ( in_array( $post->post_type,array_keys($mytypes) ) ){
            return home_url( $mytypes[$post->post_type].'/' . $post->post_name .'.html' );
        } else {
            return $link; 
        }
    }
    add_action( 'init', 'my_custom_post_type_rewrites_init' );
    function my_custom_post_type_rewrites_init(){
        global $mytypes;
        foreach( $mytypes as $k => $v ) {
    		add_rewrite_rule($v.'/([^/]+)\.html$','index.php?post_type='.$k.'&name=$matches[1]','top');		
        }
    } 
  • WordPress 后台仪表盘 文章 页面 列表 显示对应的ID

    WordPress 后台仪表盘 文章 页面 列表 显示对应的ID

    在WordPress 中,每一篇文章及每一个页面都有一个独一无二的id 。在开发主题或者插件的时候可能有需要获取相对应的文章或者页面id,例如在展示特色文章幻灯片,你需要获取对应文章的id。现在教你一个方法快速在后台文章和页面列表显示对应的ID。

    将下面的代码添加到主题的functions.php 文件下:

    add_filter('manage_posts_columns', 'posts_columns_id', 5);
    add_action('manage_posts_custom_column', 'posts_custom_id_columns', 5, 2);
    add_filter('manage_pages_columns', 'posts_columns_id', 5);
    add_action('manage_pages_custom_column', 'posts_custom_id_columns', 5, 2);
    function posts_columns_id($defaults){
        $defaults['wps_post_id'] = __('ID');
        return $defaults;
    }
    function posts_custom_id_columns($column_name, $id){
            if('wps_post_id' === $column_name){
                    echo $id;
        }
    }

    保存后,在后台-文章-文章列表 那里你会看到显示的id。

  • WordPress Dashboard后台 非插件 纯代码 实现自定义字段过滤

    前面我们介绍了 WordPress 主题/插件开发 自定义文章分类 筛选功能 图文教程

    下面我们记录一下如何在后台实现过滤自定义字段,将以下代码放入 functions.php 文件中代码段如下:

    add_filter( 'parse_query', 'jadmin_posts_filter' );
    add_action( 'restrict_manage_posts', 'jadmin_posts_filter_restrict_manage_posts' );
     
    function jadmin_posts_filter( $query )
    {
        global $pagenow;
        if ( is_admin() && $pagenow=='edit.php' && isset($_GET['ADMIN_FILTER_FIELD_NAME']) && '' != $_GET['ADMIN_FILTER_FIELD_NAME']) {
            $query->query_vars['meta_key'] = sanitize_text_field($_GET['ADMIN_FILTER_FIELD_NAME']);
        if (isset($_GET['ADMIN_FILTER_FIELD_VALUE']) && '' != $_GET['ADMIN_FILTER_FIELD_VALUE'])
            $query->query_vars['meta_value'] = sanitize_text_field($_GET['ADMIN_FILTER_FIELD_VALUE']);
        }
    }
     
    function jadmin_posts_filter_restrict_manage_posts()
    {
        global $wpdb;
        $sql = 'SELECT DISTINCT meta_key FROM '.$wpdb->postmeta.' ORDER BY 1';
        $fields = $wpdb->get_results($sql, ARRAY_N);
    ?>
    <select name="ADMIN_FILTER_FIELD_NAME">
    <option value=""><?php _e('Filter By Custom Fields', 'jiloc'); ?></option>
    <?php
        $current = isset($_GET['ADMIN_FILTER_FIELD_NAME'])? $_GET['ADMIN_FILTER_FIELD_NAME']:'';
        $current_v = isset($_GET['ADMIN_FILTER_FIELD_VALUE'])? $_GET['ADMIN_FILTER_FIELD_VALUE']:'';
        foreach ($fields as $field) {
            if (substr($field[0],0,1) != "_"){
            printf
                (
                    '<option value="%s"%s>%s</option>',
                    $field[0],
                    $field[0] == $current? ' selected="selected"':'',
                    $field[0]
                );
            }
        }
    ?>
    </select> <?php _e('Value:', 'jiloc'); ?><input type="TEXT" name="ADMIN_FILTER_FIELD_VALUE" value="<?php echo $current_v; ?>" />
    <?php
    }
  • php代码实现 WordPress禁止使用前端主题访问 维护模式

    php代码实现 WordPress禁止使用前端主题访问 维护模式

    最近在给客户弄一个基于WordPress的OA系统,前台禁止访问。仅供后台使用。这边我们记录一下,如何禁止使用前端主题。开启维护模式。

    为什么要启用维护模式?

    • 可以避免访客在打开博客时,因为折腾出现一些不怎么美好的情况。
    • 它可以帮助您正常地在网站的后端调整网站设置,主题或插件,而不会让访问者看到您的网站在维护时的全部细节。

    开启维护模式也很简单,我们需要打开WordPress当前模板目录中的functions.php

    添加如下代码:

    function maintenance_mode() {       
        if ( !current_user_can( 'edit_themes' ) || !is_user_logged_in() ) {
            wp_die('站点维护中,请稍后再来.');
        } 
    }
    add_action('get_header', 'maintenance_mode');

    保存上传就开启了维护模式。

  • WordPress 使用 wp_count_posts() 函数快速获取文章数量

    WordPress 使用 wp_count_posts() 函数快速获取文章数量

    还记得老季之前想要获取 WordPress 站点的所有文章总数统计网上的教程,以及在某些地方的使用也都是直接使用 SQL 语句直接查询数据来做总数统计,现在相信还真的是费时费力,原因就是不知道 WordPress 还有 wp_count_posts()这样一个函数,具体是哪个版本出来就懒得去看了,反正随时都保持 WordPress 最新版。

    其实在很多的 WordPress 主题上都会有一个统计或者文章归档的页面,就需要统计一些 WordPress 站点上已经发布多少文章了,以此来展示自己的站点或者给自己一个统计,当然我们在开发某些特别的功能或者逻辑计算时也可能会用到,最近在开发一个插件的时候就多次用到了,不想再去写 SQL 来统计,费时费力并且 WordPress 本身就有的功能为什么就不好好利用呢,果断就想起了 wp_count_posts 函数。

    wp_count_posts 函数是在 WordPress 中用来统计文章数量的函数,可以统计的类型有文章(post)和页面(page)。并且能够直接统计出文章各个不同状态的数据,使用起来非常的便捷,两行代码即可搞定。

    //获取文章数量
    $postcount = wp_count_posts();
    //获取页面数量
    $pagecount = wp_count_posts('page');

    默认是获取的 post 文章类型的,当然如果是自定义类型应该也是可以支持的,这个目前没有测试,不过相信 WordPress 是绝对考虑到了兼容性的,值得注意的是,上面说过了是两行代码,所以上面的例子并不能直接输出,因为 wp_count_posts 函数返回的是一个对象数据,如下。

    // WordPress wp_count_posts 函数返回值
    stdClass Object
    (
        [publish] => 11 //已发布
        [future] => 0   //定时发布
        [draft] => 0    //草稿
        [pending] => 0  //待审
        [private] => 0  //私有
        [trash] => 0    //垃圾箱
        [auto-draft] => 34  //自动草稿
        [inherit] => 0  //修订版本
        [request-pending] => 0
        [request-confirmed] => 0
        [request-failed] => 0
        [request-completed] => 0
    )
    

    所以,获取已发布状态文章的完整统计代码如下:

    //WordPress 已发布文章数量
    $count_posts = wp_count_posts();  
    $publish_posts = $count_posts->publish;

    其它的就举一反三,相信也都能看得懂了,老季就不再过多的赘述。最后在补充一点,有时候我们可能喜欢代码的简单性,所以在写法上面就比较大胆,没有怎么考虑兼容性,一行代码就能搞定,所以在不考虑兼容性的情况下还有以下的一种写法:

    //WordPress 已发布文章数量,不兼容 PHP5.4 以前
    $publish_posts = wp_count_posts()->publish;

    比较喜欢用吧,不过使用这种写法请一定保证你的 PHP 版本在 5.4 以上即可正常运行。

  • wordpress自定义侧边栏小工具widget

    wordpress自定义侧边栏小工具widget

    wordpress提供了主题小工具支持(后台——外观——小工具),可以实现自由拖动功能模板到侧边栏,实现相关的调用显示。wordpress默认提供了若干个小工具,但大部分不能满足博主的建站需求,因此对小工具自定义扩展非常有必要。以下通过转载添加分类文章列表小工具的教程详细了解如何自定义侧边栏小工具。

    概念性的东西:wordpress提供了一个WP_Widget类,我们只需要扩展WP_Widget类,就可以制作自己的小工具(widget),此类文件位于 wp-includes\widgets.php

    下面老季给出一个完整的调用分类文章模块的widget工具完整代码:

    <?php
    /**
    * 功能:调用某分类下的文章列表
    * 调用:在主题functions.php文件里引入本文件
    **/
    /** 
     * Add function to widgets_init that'll load our widget. 
     * @since 0.1 
     */
    add_action('widgets_init', 'load_relation_widgets');
    /** 
     * Register our widget. 
     * 'Example_Widget' is the widget class used below. 
     * 
     * @since 0.1 
     */
    function load_relation_widgets()
    {
        register_widget('jtag_post_widget');
    }
    
    class jtag_post_widget extends WP_Widget
    {
        public function jtag_post_widget()
        {
            $widget_ops  = array(
                'classname'                   => 'widget_custom_html',
                'description'                 => __( '关联标签分类文章调用.' ),
                'customize_selective_refresh' => true,
                'show_instance_in_rest'       => true,
            );
            $this->__construct('jtag_post_widget', $name = '关联标签分类文章调用', $widget_ops);
        }
        //小工具的选项设置表单
        public function form($instance)
        {
            $instance = wp_parse_args((array)$instance, array('title' => '分类文章', 'showPosts' => 10, 'cat' => 0)); //默认值
            $title = htmlspecialchars($instance['title']);
            $showPosts = htmlspecialchars($instance['showPosts']);
            $cat = htmlspecialchars($instance['cat']);
            echo '<p style="text-align:left;"><label for="' . $this->get_field_name('title') . '">标题:<input style="width:200px;" id="' . $this->get_field_id('title') . '" name="' . $this->get_field_name('title') . '" type="text" value="' . $title . '" /></label></p>';
            echo '<p style="text-align:left;"><label for="' . $this->get_field_name('showPosts') . '">文章数量:<input style="width:200px;" id="' . $this->get_field_id('showPosts') . '" name="' . $this->get_field_name('showPosts') . '" type="text" value="' . $showPosts . '" /></label></p>';
            echo '<p style="text-align:left;"><label for="' . $this->get_field_name('cat') . '">分类ID(多个分类ID,可用逗号分割):<input style="width:200px" id="' . $this->get_field_id('cat') . '" name="' . $this->get_field_name('cat') . '" type="text" value="' . $cat . '" /></label></p>';
        }
        public function update($new_instance, $old_instance)
        {
            $instance = $old_instance;
            $instance['title'] = strip_tags(stripslashes($new_instance['title']));
            $instance['showPosts'] = strip_tags(stripslashes($new_instance['showPosts']));
            $instance['cat'] = strip_tags(stripslashes($new_instance['cat']));
            return $instance;
        }
        public function the_rand_posts($args = '')
        {
            $default = array('showPosts' => 10, 'cat' => '1');
            $r = wp_parse_args($args, $default);
            extract($r);
            $args = array(
                'cat'   =>  $cat,
                'showposts' =>  $showPosts,
                'orderby'   =>  'desc',
            );
            $the_query = new WP_Query($args);
            if ($the_query->have_posts()) {
                echo '<ul>';
                while ($the_query->have_posts()) {
                    $the_query->the_post();
                    echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
                }
                echo '</ul>';
            }
            // Restore original Post Data
            wp_reset_postdata();
        }
        //小工具在前台显示效果
        public function widget($args, $instance)
        {
            extract($args);
            $title = apply_filters('widget_title', empty($instance['title']) ? __('分类文章<i>Title</i>') : $instance['title']);
            $showPosts = empty($instance['showPosts']) ? 10 : $instance['showPosts'];
            $cat = empty($instance['cat']) ? 0 : $instance['cat'];
            echo $before_widget;
            if ($title) echo $before_title . $title . $after_title;
            $this->the_rand_posts("showPosts=$showPosts&cat='$cat'");
            echo $after_widget;
        }
    }
    
WeChat