为什么我的 ajax 功能没有按预期工作?

why is my ajax function not working as expected?

所以我的 class 看起来像这样:

class Myclass{

    private $nonce;

    public function __construct(){
        if( get_current_screen()->id == 'nav-menus' ){
            $this->nonce = 'my-plugin-nonce';
        }
        add_action( 'wp_ajax_run_action', array( $this, 'run' ) );

        wp_localize_script(
            'my-script',
            'my_script',
            array( 'nonce' => wp_create_nonce( $this->nonce ), 
                 'ajaxurl' => admin_url('admin-ajax.php'),
            )
        );
    }

    public function run(){
        if( ! wp_verify_nonce( $_POST['nonce'], $this->nonce ) )
            return false;

        wp_send_json_success();
    }

}
new Myclass;

这里是 javascript 代码:

$.ajax({
    type: 'POST',
    dataType: 'json',
    url: my_script.ajaxurl,
    data: {
         'action': 'run_action',
         'nonce' : my_script.nonce,
    },
    complete: function( object ) {
        console.log( object.responseJSON )
    }
});

问题是,当我尝试从我的 javascript ajax 函数中调用 run_action 操作时,它没有 return 正确。

请注意,我已正确本地化我的脚本,对象中包含的所有数据都已正确呈现。

为什么会这样?

抄本注释:

wp_localize_script() MUST be called after the script has been registered using wp_register_script() or wp_enqueue_script().

所以你的工作流程应该如下:

  1. 注册脚本
  2. 本地化
  3. 排队您的本地化脚本。
  4. 将其与适当的操作联系起来:wp_enqueue_scriptsadmin_enqueue_scripts

例如:

向您的 __construct 方法添加操作:

add_action('wp_enqueue_scripts', array($this, 'registerAjaxScript'));

然后创建一个方法来注册和本地化您的脚本:

function registerAjaxScript() {
  wp_register_script('my-script', 
         string $src, 
         array $deps, 
         string or bool $ver, 
         bool $in_footer
  );
  wp_localize_script('my-script',
        'my_script',
        array( 'nonce' => wp_create_nonce( $this->nonce ), 
             'ajaxurl' => admin_url('admin-ajax.php'),
        )
  );
}

脚本的本地化必须在您包含脚本的页面上完成(即在这种情况下在 nav-menus.php 管理页面上)- 您不包含实际排队的代码javascript,但你所做的代码 post 向我暗示你实际上是在尝试在 ajax 调用本身中本地化脚本 - 这是行不通的。

我在下面重新整理了您的代码并添加了注释来解释每项更改:

class Myclass {
    /**
     * No reason not to assign this already (and I've renamed it to explicitly,
     * let people reading the code know that it is not the nonce itself, but the
     * name of the nonce action - fooled me for a minute or two :p
     */
    private $nonce_action_name = 'my-plugin-nonce';

    /**
     * The __construct function is great for hooking everything you need to
     * hook, and for setting initial variables. Pretty much anything else
     * should NOT be in this function though!
     */
    public function __construct(){
        // Register your ajax action.
        add_action( 'wp_ajax_run_action', array( $this, 'run' ) );

        // Hook into the appropriate action for admin scripts
        add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
    }

    public function scripts() {
        /**
         * I've negated your if-statement here - basically we don't want to do
         * anything at all if we are not on the correct page - which is clearer
         * this way - also you had it in the __construct function, which will
         * actually produce a fatal error, since get_current_screen is not
         * usually defined yet at that point(!)
         */
        if( get_current_screen()->id !== 'nav-menus' ){
            return;
        }

        //Now enqueue (or register) the script
        wp_enqueue_script('my-script', plugins_url('/my-script.js', __FILE__));

        //Then localize it
        wp_localize_script(
            'my-script',
            'my_script',
            array(
                'nonce' => wp_create_nonce( $this->nonce_action_name ),
                'ajaxurl' => admin_url('admin-ajax.php'),
            )
        );
    }
    /**
     * Actual ajax handler
     */
    public function run(){
        if( ! wp_verify_nonce( $_POST['nonce'], $this->nonce_action_name ) ) {
            //This is a guess, but I think you'll want to wp_send_json_error
            //here to match up with your success below
            wp_send_json_error();
        } else {
            wp_send_json_success();
        }
        /**
         * Always recommended to explicitly die() after handling ajax - though
         * the wp_send_json_* family probably does it for you.
         */
        die();
    }
}
new Myclass;

最后要注意的是 ajaxurl 实际上总是在管理员中定义,因此您实际上不需要将其添加到您的本地化中(尽管添加一些额外的字节只会造成伤害)。