跳转到主要内容
qingkong 提交于 7 August 2015

7.2.4 drupal_add_library

另外,你还可以使用drupal_add_library添加js库。格式如下:

drupal_add_library($module, $library);

这里,库指的是一个js+css的集合,库中还可以包含其它依赖的库。例如,Drupal7中所包含jQuery UI,就是一个库,并且,这个库存在于核心的 system模块中,如果你想引入整个jQuery UI,你可以这样:

<?php

drupal_add_library('system', ‘ui');

?>

 

当它其中的子库ui.autocomplete被页面某个元素调用的时候,为了使其正常工作,还需要同时在页面上引入ui.core和ui.position。如果你使用drupal_add_js的话需要引入三次,这还不包括对应的css。但是,drupal_add_library可以一次性为我们搞定这些事情。你只需要使用以下代码引入ui.autocomplete,就可以引入相关的CSS/JS/依赖的子库:

<?php

drupal_add_library('system', 'ui.autocomplete');

?>

这一个语句就引入了 jquery.ui.autocomplete.js, jquery.ui.autocomplete.css, 以及所依赖的 jquery.ui.position.js, jquery.ui.widget.js, jquery.ui.core.js, jquery.ui.core.css, 和 jquery.ui.theme.css.

7.3.1 drupal中的JS 的写法

ok,经过上面的学习,你已经学会如何引入js语句了,那么在Drupal中js的写法有什么特殊之处呢?

假设,我们的jQuery文件内容如下——它看上去和平常的jQuery代码没有什么区别:

$(document).ready(function(){
	$(‘h1’).addClass('my-class');
});

如果我们直接引入这个文件,在Drupal中就会出现本章第一节中第7点所提到的错误,解决方案如下:

1  用jQuery代替美元符号$:

jQuery(document).ready(function(){

    $(‘h1’).addClass('my-class');

});

2 用下面红色代码包围原始文件:

(function($){

    $(document).ready(function(){

        $(‘h1’).addClass('my-class');

    });

})(jQuery);

另外,由于在jQuery中        //https://api.jquery.com/ready/

$( document ).ready(function() {

  // Handler for .ready() called.

});

$(function() {

  // Handler for .ready() called.

});

是等效的,所以你也可以把上面的代码写为:

(function($){

    $(function() {

        $(‘h1’).addClass('my-class');

    });

})(jQuery);

 

3 用drupal7自己的 behaviors

 

(function($){

    Drupal.behaviors.behaviorName = {

          attach: function (context, settings) {

            $(‘h1’).addClass('my-class');

        }

    };

})(jQuery);

我们还可以将context变量作为jQuery选择器的第二个参数,这样效率更高。所以代码还可以写成这样:

(function($){

    Drupal.behaviors.behaviorName = {

          attach: function (context, settings) {

            $(‘h1’, context).addClass('my-class');

        }

    };

})(jQuery);

 

7.3.2 Drupal.behaviorsv和 jQuery $.once()

 

在上面提到的方法2中的    

$(document).ready(function(){

        $(‘h1’).addClass('my-class');

    });

只会在页面完全加载后执行一次,这种方式对于大多数的情况都没有问题,但是对于AJAX事件就会力不从心了。因为AJAX事件会在页面加载之后改变DOM,而事件发生之后,由于页面并没有重新加载,因此js语句不会再次执行。

为了解决这个问题,jQuery给出了live()方法,以确保AJAX事件发生之后JS语句的有效性。

与此同时,Drupal也给出了自己的方法Drupal.behaviors,也就是上节中的方法3。

Drupal.behaviors的特点在于,每当DOM被完全载入,或者每当DOM发生改变,它所包含的js语句都会被执行一次。因此,当你使用Drupal.behaviors的时候,你不再需要使用$(document).ready来帮你判断你的DOM是否已经做好准备了。并且,当DOM发生改变的时候,你也不再需要使用jQuery的live()。

使用Drupal.behaviors不是必须的,但是是推荐的最佳实践。如下:

Drupal.behaviors.behaviorName = {

  attach: function (context, settings) {

    // Do something.

  },

  detach: function (context, settings, trigger) {

    // Undo something.

  }

};

Drupal.behaviors往往会在页面上被调用多次。这样,发生Ajax事件以后,就可以确保对DOM中新的元素执行Drupal.behaviors中的命令。但是,这样会使得DOM中原有的元素被重复执行Drupal.behaviors中的命令——虽然,很多时候,肉眼看不出变化。这样,效率会比较低,有些时候,可能还会导致一些意想不到的错误。因此我们使用  jQuery.once()来保证JS语句只运行一遍,而且它被加入了Drupal的核心中。 jQuery.once()会对已经被执行过对应JS语句的元素添加一个简单的class作为标记,并在下一次Drupal.behaviors执行的时候,找到这些标记,并跳过相应的元素。

例子如下

(function ($) {

Drupal.behaviors.mybehavior = {

  attach: function (context, settings) {

    $('#some_element', context).once('mybehavior', function () {

      // Code here will only be applied to $('#some_element')

      // a single time.

    });

  }

};

})(jQuery);

更多详情请参考: https://www.drupal.org/node/756722

https://www.lullabot.com/articles/understanding-javascript-behaviors-in-drupal

 

最后仅以下图纪念在社区中那些快乐的片段:

drupal.behaviorsliao_tian_ji_lu_.png

 

子曰:“学而时习之,不亦悦乎?有朋自远方来,不亦乐乎?人不知而不愠,不亦君子乎?”—— 《论语·学而》

Drupal 版本