Yii2 —— 實(shí)現(xiàn)自己的iCheck資源包
1.1.1 基本封裝
iCheck是配合bootstrap包使用的前端控件,用來美化radio和checkbox的顯示樣式的,根據(jù)前面的“資源管理”的說明,以及官網(wǎng)的文檔,可以很方便的把iCheck組件用資源包封裝起來,順便熟悉一下Yii 2中資源包的使用方法:
1、創(chuàng)建iCheck資源包ICheckAssets.php;
<?php namespace backend\assets; use yii\web\AssetBundle; class ICheckAsset extends AssetBundle { } |
2、設(shè)置資源路徑,這里省事,直接將icheck包放到%yii-app%\backend\web\front-lib目錄下:
<?php namespace backend\assets; use yii\web\AssetBundle; class ICheckAsset extends AssetBundle { public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'front-lib/icheck/skins/all.css', ]; public $js = [ 'front-lib/icheck/icheck.min.js', ]; } |
注:iCheck支持skin,這里暫時(shí)先把所有skin全部引入。
3、設(shè)置依賴包,iCheck依賴于bootstrap,同時(shí)初始化代碼依賴于jQuery,所以要將這兩個(gè)配置上:
<?php namespace backend\assets; use yii\web\AssetBundle; class ICheckAsset extends AssetBundle { public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'front-lib/icheck/skins/all.css', ]; public $js = [ 'front-lib/icheck/icheck.min.js', ]; public $depends = [ 'yii\web\JqueryAsset', 'yii\bootstrap\BootstrapAsset', ]; } |
4、iCheck組件不是直接引入CSS就可以了,而是在頁面需要執(zhí)行一段JS代碼才能把顯示樣式修改過來,因此需要注冊iCheck初始化代碼:
<?php namespace backend\assets; use yii\web\AssetBundle; class ICheckAsset extends AssetBundle { public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'front-lib/icheck/skins/all.css', ]; public $js = [ 'front-lib/icheck/icheck.min.js', ]; public $depends = [ 'yii\web\JqueryAsset', 'yii\bootstrap\BootstrapAsset', ]; public function registerAssetFiles($view) { parent::registerAssetFiles($view); $view->registerJs( '$("input").iCheck({ checkboxClass: "icheckbox_minimal-blue", radioClass: "iradio_minimal-blue", increaseArea: "20%" // optional });' ); } } |
注:這里固定配置為使用minimal/blue這個(gè)樣式。
5、使用資源包,在AppAssets中增加配置(注意路徑):
public $depends = [ 'backend\assets\ICheckAsset', 'yii\web\YiiAsset', 'yii\bootstrap\BootstrapAsset', ]; |
6、顯示效果如下:
至此,就初步完成了將iCheck封裝到資源包的過程,但是現(xiàn)在還有幾個(gè)遺留問題:
1、從上圖可以看出,明顯checkbox控件位置偏右了;
2、iCheck支持很多個(gè)樣式,可是上面代碼卻固定成minimal/blue,影響適用性;
3、引入的是all.css,沒有按需引入,這樣會導(dǎo)致CSS文件比較大;
下面把上述問題逐一解決。
1.1.2 控件位置
1.1.2.1原因
在使用iCheck之前,checkbox和文字是這樣的:
input控件在label控件內(nèi),label控件為了給checkbox控件空出位置,設(shè)置了一個(gè)padding-left:20px屬性,使得文字向右偏移20個(gè)字節(jié)。
在使用了iCheck之后,checkbox和文字是這樣的:
iCheck初始化后,將原來的input控件外面又包了一層div,導(dǎo)致input控件和文字被label視作一個(gè)整體,使得“padding-left:20px”屬性也作用到div上,使得checkbox和文字都被右移20px。
1.1.2.2解決辦法
檢查label控件的屬性,發(fā)現(xiàn)這個(gè)“padding-left:20px”屬性是forms.less中定義的,這個(gè)less文件是bootstrap的,所以直接修改這個(gè)文件不是個(gè)好主意。
最終確定在資源包內(nèi)修改如下:
public function registerAssetFiles($view) { parent::registerAssetFiles($view); $view->registerJs( '$("input").iCheck({ checkboxClass: "icheckbox_minimal-blue", radioClass: "iradio_minimal-blue", increaseArea: "20%" // optional }); $(".icheckbox_minimal-blue").css("margin-left", "-20px"); $(".iradio_minimal-blue").css("margin-left", "-20px");' ); } |
1.1.3 支持多樣式
支持iCheck的多個(gè)樣式,也是在資源包里實(shí)現(xiàn):
1、首先定義樣式名稱:
<?php namespace backend\assets; use yii\web\AssetBundle; class ICheckAsset extends AssetBundle { const SKIN_ALL = 'all'; const SKIN_FLAT = 'flat/_all'; const SKIN_FLAT_AERO = 'flat/aero'; const SKIN_FLAT_BLUE = 'flat/blue'; const SKIN_FLAT_FLAT = 'flat/flat'; const SKIN_FLAT_GREEN = 'flat/green'; const SKIN_FLAT_GREY = 'flat/grey'; const SKIN_FLAT_ORANGE = 'flat/orange'; const SKIN_FLAT_PINK = 'flat/pink'; const SKIN_FLAT_PURPLE = 'flat/purple'; const SKIN_FLAT_RED = 'flat/red'; const SKIN_FLAT_YELLOW = 'flat/yellow'; const SKIN_FUTURICO = 'futurico/futurico'; const SKIN_LINE = 'line/_all'; const SKIN_LINE_AERO = 'line/aero'; const SKIN_LINE_BLUE = 'line/blue'; const SKIN_LINE_GREEN = 'line/green'; const SKIN_LINE_GREY = 'line/grey'; const SKIN_LINE_LINE = 'line/line'; const SKIN_LINE_ORANGE = 'line/orange'; const SKIN_LINE_PINK = 'line/pink'; const SKIN_LINE_PURPLE = 'line/purple'; const SKIN_LINE_RED = 'line/red'; const SKIN_LINE_YELLOW = 'line/yellow'; const SKIN_MINIMAL = 'minimal/_all'; const SKIN_MINIMAL_AERO = 'minimal/aero'; const SKIN_MINIMAL_BLUE = 'minimal/blue'; const SKIN_MINIMAL_GREEN = 'minimal/green'; const SKIN_MINIMAL_GREY = 'minimal/grey'; const SKIN_MINIMAL_LINE = 'minimal/minimal'; const SKIN_MINIMAL_ORANGE = 'minimal/orange'; const SKIN_MINIMAL_PINK = 'minimal/pink'; const SKIN_MINIMAL_PURPLE = 'minimal/purple'; const SKIN_MINIMAL_RED = 'minimal/red'; const SKIN_MINIMAL_YELLOW = 'minimal/yellow'; const SKIN_POLARIS = 'polaris/polaris'; const SKIN_SQUARE = 'square/_all'; const SKIN_SQUARE_AERO = 'square/aero'; const SKIN_SQUARE_BLUE = 'square/blue'; const SKIN_SQUARE_GREEN = 'square/green'; const SKIN_SQUARE_GREY = 'square/grey'; const SKIN_SQUARE_LINE = 'square/square'; const SKIN_SQUARE_ORANGE = 'square/orange'; const SKIN_SQUARE_PINK = 'square/pink'; const SKIN_SQUARE_PURPLE = 'square/purple'; const SKIN_SQUARE_RED = 'square/red'; const SKIN_SQUARE_YELLOW = 'square/yellow'; public static $skin = 'all'; public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'front-lib/icheck/skins/all.css', ]; public $js = [ 'front-lib/icheck/icheck.min.js', ]; public $depends = [ 'yii\web\JqueryAsset', 'yii\bootstrap\BootstrapAsset', ]; public function registerAssetFiles($view) { parent::registerAssetFiles($view); $view->registerJs( '$("input").iCheck({ checkboxClass: "icheckbox_minimal-blue", radioClass: "iradio_minimal-blue", increaseArea: "20%" // optional }); $(".icheckbox_minimal-blue").css("margin-left", "-20px"); $(".iradio_minimal-blue").css("margin-left", "-20px");' ); } } |
2、初始化時(shí)載入指定的CSS文件:
<?php namespace backend\assets; use yii\web\AssetBundle; class ICheckAsset extends AssetBundle { public static $skin = self::SKIN_MINIMAL_BLUE; public $basePath = '@webroot'; public $baseUrl = '@web/front-lib/icheck'; public $depends = [ 'yii\web\JqueryAsset', 'yii\bootstrap\BootstrapAsset', ]; /** * @inheritdoc */ public function init() { parent::init(); $this->css = [ 'skins/' . self::$skin . '.css', ]; // detect is debug mode and select uncompressed js file $jsFile = YII_DEBUG ? 'icheck.js' : 'icheck.min.js'; $this->js = [ $jsFile, ]; } }
|
3、根據(jù)設(shè)置的樣式名稱初始化checkbox控件:
public function registerAssetFiles($view) { parent::registerAssetFiles($view); $cssClassSuffix = str_replace('/', '-', self::$skin); $view->registerJs( '$("input").iCheck({ checkboxClass: "icheckbox_' . $cssClassSuffix . '", radioClass: "iradio_' . $cssClassSuffix . '", increaseArea: "20%" // optional }); $(".icheckbox_' . $cssClassSuffix . '").css("margin-left", "-20px"); $(".iradio_' . $cssClassSuffix . '").css("margin-left", "-20px");' ); } |
這樣,就封裝好了,想要什么樣式,就配置這個(gè)包里的$skin參數(shù)即可。
1.1.4 按需載入
實(shí)現(xiàn)上一節(jié)的支持多樣式,其實(shí)同時(shí)也實(shí)現(xiàn)了按需載入的功能,參見下圖:
1.1.5 可復(fù)用
iCheck是個(gè)很常用的前端庫,前面是只將其放到了backend端,其實(shí)frontend端也很有可能會用到,因此再進(jìn)一步,可以把iCheck放到框架層,使其可以更好的被復(fù)用:
1、在vendor下建立frontlib子目錄,然后將icheck包拷貝進(jìn)去,目錄結(jié)構(gòu)如下:
2、將前面實(shí)現(xiàn)的ICheckAsset.php也轉(zhuǎn)到這個(gè)目錄下(如上圖);
3、打開ICheckAsset.php,修改代碼:
/*public $basePath = '@webroot'; public $baseUrl = '@web/frontlib/icheck';*/ public $sourcePath = '@vendor/frontlib/icheck'; |
即注釋掉$basePath和$baseUrl的賦值,改為對$sourcePath初始化,根據(jù)Yii文檔,$basePath和$baseUrl參數(shù)是不能跟$sourcePath共存。Yii在運(yùn)行時(shí),會根據(jù)$sourcePath所指定的路徑,將資源文件拷貝到assets目錄下。
4、在使用iCheck資源的地方,修改代碼如下:
class AppAsset extends AssetBundle { public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'css/site.css', 'css/common.css', 'css/login.css', ]; public $js = [ ]; public $depends = [ 'vendor\frontlib\icheck\ICheckAsset', 'yii\web\YiiAsset', 'yii\bootstrap\BootstrapAsset', ]; } |