Backbone 实现 WordPress 目录内容展示

wpapi with backbone in wordpress

WordPress 提供以 Backbone 为基础的 Rest Api 客户端来访问和操作后台数据内容,本篇文章介绍如何使用这一框架实现文章目录内容的动态展示功能,同时详细介绍其中 MVC 的使用流程和方法。

Backbonejs 是一套使用 JavaScript 实现 MVC 程序模式的框架,为采用这一方式的 Web 应用开发提供基础架构。Backbone 非常灵活,扩展性很强,能够方便地应用到不同的项目中,而且 Bacnbone 可以通过 RESTful JSON 接口与现有应用集成。

WordPress 核心内置了 Backbone 客户端,同时实现了 Rest Api 连接后端服务器,本篇文章就通过文章目录内容动态展示这个例子介绍上述原理和使用方法。

一、定义目录内容 DOM 容器

在插件或主题中增加一个空的 DOM 容器用来动态展示文章目录内容,以插件为例。

function plugin_init() {
    //容器插入位置
    add_action( 'wp_footer', 'add_cat_posts_container' );
    //需要装载jquery和wp-api
    wp_enqueue_script( 'plugin-js', plugins_url( '/js/plugin.js', __FILE__ ), array( 'jquery', 'wp-api' ) );
}
//定义容器
function add_cat_posts_container() {
    echo '<div id="popup_cat_posts">';
    echo '<ul></ul>';
    echo '</div>';
}
add_action( 'plugins_loaded', 'plugin_init' );

二、新建 Posts Collection 实例

WordPress 核心提供 wp.api,基于Backbone 实现了 Rest Api 客户端接口,可以直接使用相应的 Posts Collection、Categories Collection、Post Model 等对象获取对应的数据。实例化这些对象之前需要先装载 API 的 Schema,这个过程是异步的。

var postsCollection;
wp.api.loadPromise.done( function() {
    postsCollection = new wp.api.collections.Posts();
});

三、扩展 Backbone View

View 对象实现与用户交互,响应 DOM 事件,响应 Collection、Model 事件,刷新用户界面等,主要完成以下几个任务:

1、响应用户接口事件(DOM)

这包括两种类型的事件,即容器 View 内部的事件外部的事件,需要通过不同的方式处理。内部事件通过定义事件和对应的响应函数声明即可:

events: {
    //这里事件声明可以使用容器View内元素的class、id名,比如"click .classname"、"keydown #idname",不使用就是容器View本身
    "mouseleave": "hide", //鼠标离开容器View时隐藏容器
    "click": "hide", //容器View内点击鼠标时隐藏容器
},
hide: function() {
    //$el是Backbone提供的容器View的jQuery对象引用
    this.$el.hide();
}

容器 View 不能直接响应外部的 DOM 事件,容器外部事件需要扩展 Backbone 事件对象,有两种方式,即事件对象扩展事件调度总线

(1)Backbone 事件对象扩展

Backbone 提供了用户自定义事件并把对象和事件关联和触发的机制:

var object = {}; //用户对象
_.extend(object, Backbone.Events); //把该用户对象关联到Backbone事件对象上
//监听事件,这里事件名可以自定义
object.on("myevent", function(msg) {
    alert("Triggered " + msg);
});
//触发事件myevent
$(document).hover(function(){
    object.trigger("myevent", "an event");
});

(2)Backbone 事件调度总线

本例采用这一处理方式,首先新建一个 Backbone 事件调度器,然后把用户事件和响应函数(render)关联到事件调度器上,当用户触发 DOM 事件后 trigger 容器 View 中定义的用户事件并调用关联函数刷新容器界面。

Event.Dispatcher = _.clone(Backbone.Events);
var Cat_Posts_View = Backbone.View.extend({
    //容器对象初始化时关联外部事件响应函数,事件名称自定义catItemMousemove
    initialize: function() {
        this.listenTo(Event.Dispatcher, 'catItemMousemove', this.render);
    },
    render: function(event, cid) {
        let models = this.collection.where({cat_id: cid});
        this.$el.children().html('');
        models.forEach((mod) => {
            this.$el.children().append(
                '<li><a href="' + mod.get("link") + '"><img src="'
                + mod.get("_embedded")["wp:featuredmedia"][0].source_url
                + '"></a><div>'
                + '<a href="' + mod.get("link") + '">'
                + mod.get("title").rendered
                + '</a></div></li>'
            );
        });
        //计算容器View的位置并显示
        let left = ...;
        let top = ...;
        this.$el.css({'left': left, 'top': top}).show();
    }
)};
2、响应 Collection 和 Model 事件

当 Posts Collection 对象从后台获取数据后会触发相关的事件(add、update、sync、change等),容器 View 可以根据需求监听这些事件并作出处理,这就需要关联事件到响应函数上。

var Cat_Posts_View = Backbone.View.extend({
    //关联Collection事件
    initialize: function() {
        //监听Collection事件
        this.listenTo(this.collection, "add", this.add);
        this.listenTo(this.collection, "change", this.change);
    },
    add: function(mod, colle, opt) {
        //该函数调用会触发collection的“change”事件
        mod.set("cat_id", opt.cid);
        return this;
    }
    change: function(mod) {
        ...
    },
...
四、关联 Backbone View 与 DOM 容器

首先是需要实例化上面定义好的 View 对象,并同实例化好的 Posts Collection 对象关联,再关联 View 对象到 DOM 容器上。View 对象实例化和关联 Posts Collection 放在 wp.aip Schema 装载后,关联 View 对象到 DOM 容器上放在 DOM 文档准备后。

wp.api.loadPromise.done( function() {
    //实例化Posts Collection对象,实例化View对象并关联Collection对象
    cpv = new Cat_Posts_View({collection: new wp.api.collections.Posts()});
    (function ($) {
        $(document).ready( function() {
            //View对象关联DOM容器
            cpv.setElement("#popup_cat_posts");
            //DOM事件触发View中关联的事件
            $("#content").click(function (e) {
                Event.Dispatcher.trigger("contentClick");
            });
            //调用Collection fecth方法获取目录相关的文章,做了文章预取
            $( "li.cat-item" ).each( (i, em) => {
                let class_name = $(em).attr("class");
                let cat_id = class_name.match(/item-(\d+)/)[1];
                cpv.collection.fetch( { data: { categories: cat_id,  _embed: 1 }, remove: false, cid: cat_id } );
                $(em).mousemove(
        	    function (event) {
                    Event.Dispatcher.trigger("catItemMousemove", event, cat_id);
                    }
                );
            });
        });
    })(jQuery)
});

上面的代码没有给出相关的 CSS 样式、特殊情况处理以及 Backbone Router 部分内容,可以根据需求补充完善。总结 Backbone MVC 的使用方法主要就是扩展Model、Collection、View,定义并关联事件处理,刷新用户界面。另外,Backbone 集成了Underscore.js,可以方便地处理 Model、Collection 中的数据。

发表评论

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