如何灵活使用 AssetBundle 管理 CSS 样式及 JS 脚本 [ 2.0 版本 ]
2.0的变化相信大家都看到了,其中对一个资源包概念做出了很完美的实现,那就是AssetBundle,但是很多初学者朋友可能不太能够正确的领会其中的含义
我画了一张图,大家可以将就看一下:
其中,控制器动作的视图(view)渲染顺序是优先于我们的模板页(layout)的,那么一旦我们在某个视图中使用了新的JS库,或新的CSS样式文件,那么我们如何去处理呢?
以下方式是错误的,请避免使用:
有的人会直接在视图里添加对css或者js的link引用,这样引入的文件是在视图区域,而yii的默认JS加载会放在模板页的最后,这样可能导致依赖关系混乱。
比如你视图中引用的js文件里调用了jquery包,但是执行时jquery的加载代码在HTML页面的末尾,这样导致页面脚本错误。
还有人会图省事,直接把项目中所有的js或css文件都书写layout模板页里,这样产生大量的无效样式或js,影响了加载效率及页面错位风险。
所以正确的方式应该是通过AssetBundle去解决这个问题,先发一个简单的类给大家看一下:
namespace app\assets;
use yii\web\AssetBundle;
class AppAsset extends AssetBundle {
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'public/skin/default_skin/css/theme.css',
];
public $js = [
'public/vendor/jquery/jquery-1.11.1.min.js',
'public/vendor/jquery/jquery_ui/jquery-ui.min.js',
'public/js/bootstrap/bootstrap.min.js',
];
//依赖包
public $depends = [
//这里写你的依赖包即可,没有就别写
];
//导入当前页的功能js文件,注意加载顺序,这个应该最后调用
public static function addPageScript($view, $jsfile) {
$view->registerJsFile($jsfile, [AppAsset::className(), 'depends' => 'app\assets\AppAsset']);
}
//导入编辑器
public static function addCkeditor($view) {
$view->registerJsFile('/public/js/utility/ckeditor/ckeditor.js', [AppAsset::className(), 'depends' => 'app\assets\AppAsset']);
}
}
可以看到上面我创建的类中已经预定义了两个静态方法addPageScript和addCkeditor,其中addCkeditor是一个第三方的js组件,是个编辑器,具体的开发环境中你们可以写别的方法名及加载别的组件。
那么上的这个东西写好后应该如何去使用呢?
我们在模板页开头部分加上这句话:
//自动加载资源
AppAsset::register($this);
这样会在模板页加载基础的项目资源文件,比如css和js什么的。
现在我们有一个视图叫create-mail,需要使用ckeditor编辑器,那么我们应该在create-mail视图的开头加上这句话:
//导入ckeditor包资源
\app\assets\AppAsset::addCkeditor($this);
最后解释一下,addCkeditor()方法是我们预先定义好的,这样我们可以把一些常见的包都拆包并预处理好,如果你觉得麻烦可以直接使用如下的方式:
//导入ckeditor包资源
\app\assets\AppAsset::addPageScript($this,'js文件相对路径或url');
以上的例子只是使用了js文件作为一个简单的介绍,css样式的加载也是一样的道理。
这样做的好处是,即使在视图里加载css或js也会因为依赖关系而出现在视图外面的常规加载区域中,规范了很多。
同时也因为依赖关系,你在视图里加载的文件肯定会排在你的基础样式或脚本的后面,不会出错。
lxepoo 江苏南京
最后登录:2020-10-23
在线时长:33小时42分
- 粉丝27
- 金钱1487
- 威望125
- 积分3067
共 21 条评论
感谢感谢。紫薯布丁。
赞赞赞赞,再补5个字
I love you
REALLY???????????
不错,谢谢分享。一定要十个字吗,呵呵
不错,谢谢分享。一定要十个字吗,呵呵
嗯,我试过一个页面模板的思路就是这样做的。
@布老虎........................
不错,谢谢分享。一定要十个字吗,呵呵
楼主,你的JS文件放在的是web下面public/vendor/jquery里面的么。那我想要调用自身的/vendor/jquery/dist里面的怎么弄啊。或者能不能调用的到啊,因为vendor和web同级的,而URL的配置是直接指向basic/web/下面了。我是新手,求指教
$basePath 设置一下,他就会自动帮你索引你的文件,然后发布到web/asset下了。然后引用链接会自动改变。不谢,YII就是这么流弊。
能否判断浏览器版本,并输出相应内容?
或者应该如何输出带判断的语句,比如
<!--[if lt IE 9]> <script src="test.js"></script> <![endif]-->
可以,请仔细查看官方文档中关于资源包的处理方式,写的很明白可以支持IF方式。
@lxepoo 哦,看文档去,E文不好。 是期望知道的直接给出个使用方法。谢了,啃文档去。
解决了 js依赖问题,非常好
其实我主要是想看看依赖的,有哪些默认的AssetBundle,比如 'yii\web\YiiAsset','yii\bootstrap\BootstrapAsset'等。不过学到了渲染顺序也不错,那个编辑器插件也是第一次接触。总之谢谢!!!
新手报到,给我解决了一个大难题呀,感谢仁兄。
楼主,问一下,全局js配置,注册js文件能到header里面吗?怎样配置
文档里有写,JS可以出现在header里的。
http://www.yiichina.com/doc/api/2.0/yii-web-view#registerJsFile()-detail
POS_HEAD: in the head section
@lxepoo 谢谢,我会了,我是在AppAsset.php 配置全局js ,增加了一个就可以了
public $jsOptions = [
'position' => \yii\web\View::POS_HEAD ];
到底什么是依赖关系??
Cannot redeclare class frontend\assets\AppAsset
都前后端分离了,除了view,其他都扔cdn上去吧。。。。
谢谢分享
非常棒的分享,学习了啊,谢谢
你好 使用了layout之后 子视图里写JS代码 在引入的JQUERY之前 用不了$怎么解决
怎么保证在视图层写的JS代码在引入JS文件之后