因为近期给朋友公司做个门户网站,把荒置了6、7年的PHP又重新拾起,发现PHP这些年兴旺多了,很多新的东西看的不明不白,研究了几个框架ZendFramework、thinkphp、Symfony、yii2,也曾经考虑直接用网上现有的开源cms,要么因为商用授权太贵,要么后台太复杂,要么覆盖行业太多导致业务复杂,看了一通代码,头晕得很,最终选择yii2自己开发个轻量的cms+shop系统,慢慢的做,应该能做出后台简单、有自己特色的网站系统来!一下是我的一些开发过程和经验,因为没有考虑太多的技术和通用,所以有局限。网友可参考使用(请注明出处即可,我也使用了别人的成果)
在yii2中把一些js的动态组件封装成可参数化的Widget对象能够简化功能逻辑,代码复用可大大提高。
一般组件由样式、js脚本、html标签构成,在yii2中被放到AssetBundle和Widget中处理。Asset Bundle这个英文的解释是把有用的东西捆扎在一块,对的!它就是把一些公共的css和js捆扎成自定义的包,Widget用来放置客户化的样式、js脚本、html标签输出到浏览器。
一下是对SuperSlide2中的“焦点图 / 幻灯片”(来源http://www.SuperSlide2.com/)的Widget封装。
首先从AssetBundle继承出自己的SuperSlideAsset(文件名为SuperSlideAsset.php),把jquery.superslide.2.1.1.js和它使用样式捆扎,代码如下:
<?php
namespace yii\widgets;
use yii\web\AssetBundle;
use yii\web\View;
class SuperSlideAsset extends AssetBundle
{
public $sourcePath = '@yii/assets/superslide';
public $js = [
'jquery.superslide.2.1.1.js',
];
public $css = [
'themes/default/default.css',
];
public $depends = [
'yii\web\YiiAsset',
];
}
文件jquery.superslide.2.1.1.js和它使用样式放到这个路径:
然后从Widget继承编写自己的SuperSlideWidget,主要东西有init()初始化参数、注册js和css文件、输出html动态标签。代码如下:
<?php
namespace yii\widgets;
use Yii;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\web\JsExpression;
use yii\base\Arrayable;
use yii\i18n\Formatter;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\base\Widget;
use yii\helpers\ArrayHelper;
class SuperSlideWidget extends Widget
{
const PLUGIN_NAME = 'SuperSlide';
/**
* SuperSlide Options
* @var array
*/
public $rows;
public $name;
public $width;
public $height;
public $themeType;//default
public $autoPlay;//true,false
//[v1.0] fade:渐显; || top:上滚动;|| left:左滚动;|| topLoop:上循环滚动;|| leftLoop:左循环滚动;|| topMarquee:上无缝循环滚动;|| leftMarquee:左无缝循环滚动;
//[v2.0] fold:淡入淡出;[v2.1] slideDown:下拉效果
public $effect;//动画效果
public $trigger;//"mouseover" titCell触发方式 || mouseover:鼠标移过触发;|| click:鼠标点击触发;
public $easing;//"swing" 缓动效果;[v2.1]更改默认效果为“swing”,使效果更流畅
public $delayTime;//毫秒;切换效果持续时间(一次切换效果执行所用的时间长度)。
public $mouseOverStop;//true 鼠标移到容器层(无缝滚动是mainCell)是否停止播放
public $pnLoop; //true 前/后按钮是否继续循环,若为false则当翻动到最前/后页时,前/后按钮点击无效,同时增加prevStop/nextStop类名控制样色
/**
* Initializes the widget. init()初始化参数、
* If you override this method, make sure you call the parent implementation first.
*/
public function init()
{
if ($this->name === null) {
throw new InvalidConfigException("'name' properties must be specified.");
}
if ($this->rows === null) {
throw new InvalidConfigException("'rows' properties must be specified.");
}
if ($this->width === null) {
$this->width="1024px";
}
if ($this->height === null) {
$this->height="400px";
}
if ($this->autoPlay === null) {
$this->autoPlay="true";
}
if ($this->effect === null) {
$this->effect="fade";
}
if ($this->trigger === null) {
$this->trigger="mouseover";
}
if ($this->easing === null) {
$this->easing="swing";
}
if ($this->delayTime === null) {
$this->delayTime="500";
}
if ($this->mouseOverStop === null) {
$this->mouseOverStop="true";
}
if ($this->pnLoop === null) {
$this->pnLoop="true";
}
if ($this->themeType === null) {
$this->themeType="default";
}
parent::init();
}
/**
* @inheritdoc,
titCell ".hd li" 导航元素对象(鼠标的触发元素对象) 图解
mainCell ".bd" 切换元素的包裹层对象
*/
public function run()
{
$this->registerClientScript();//注册js和css文件
//输出html动态标签
$out= "<div id='".$this->name."' class='slideBox' width='".$this->width."' height='".$this->height."' >\n";
$out=$out. "<div class='hd'>\n";
$iRow=1;
$hdul=" <ul style='overflow:hidden; zoom:1; float:left;margin:0; padding:0; list-style-type:none;'>\n";
while ($iRow<count($this->rows)+1 )
{
$hdul=$hdul."<li>".$iRow."</li>";
$iRow=$iRow+1;
}
$hdul=$hdul."</ul>\n";
$out=$out. $hdul;
$out=$out. "</div>\n";
$out=$out. "<div class='bd'>\n";
$out=$out. "<ul style='margin:0; padding:0;list-style-type:none;' >\n";
foreach ($this->rows as $k => $ad ) {
$out=$out."<li><a href='".$ad['link_url']."' target='".$ad['target']."'>";
$out=$out." <img src='".$ad['image_url']."' width='100%' height='".$this->height."' /></a></li>\n";
}
$out=$out. " </ul>\n";
$out=$out. "</div>\n";
$out=$out. "<!-- 下面是前/后按钮代码,如果不需要删除即可 -->\n";
$out=$out. "<a class='prev' href='javascript:void(0)'></a>\n";
$out=$out. "<a class='next' href='javascript:void(0)'></a>\n";
$out=$out. "</div>\n";
echo $out;
}
/**
* register client scripts(css, javascript)
*/
public function registerClientScript()
{
$view = $this->getView();
$asset = SuperSlideAsset::register($view); //这里使用SuperSlideAsset
if ($this->themeType != 'default') {
$view->registerCssFile($asset->baseUrl . "/themes/{$this->themeType}/{$this->themeType}.css", ['depends' => 'yii\widgets\SuperSlideAsset']);
}
$options = [];
$options['mainCell'] = '.bd ul';
$options['autoPlay'] = $this->autoPlay;
$options['effect'] = $this->effect;
$options['trigger'] = $this->trigger;
$options['easing'] = $this->easing;
$options['delayTime'] = $this->delayTime;
$options['mouseOverStop'] = $this->mouseOverStop;
$options['pnLoop'] = $this->pnLoop;
$js=" jQuery('.slideBox').slide(".Json::encode($options)."); \n";
$view->registerJs($js,3);//View::POS_END
}
}
使用SuperSlideWidget的例子:
$rows=Yii::$app->db->createCommand($sql)->query();//需要包含link_url,image_url,target字段
echo SuperSlideWidget::widget([
'name' => 'slide_windows',
'width' => '1024px',
'rows'=> $rows,
'height' => '350px',
'themeType' => 'default',
])
至此,大功告成!
参考样式文件:
.slideBox{ background:#fff;overflow:hidden; position:relative; border:1px solid #ddd;}
.slideBox .hd{ height:15px; overflow:hidden; position:absolute; right:5px; bottom:5px; z-index:1; }
.slideBox .hd ul{ overflow:hidden; zoom:1; float:left; }
.slideBox .hd ul li{ float:left; margin-right:2px; width:15px; height:15px; line-height:14px; text-align:center; background:#fff; cursor:pointer; }
.slideBox .hd ul li.on{ background:#f00; color:#fff; }
.slideBox .bd{ position:relative; height:100%; z-index:0; }
.slideBox .bd li{ zoom:1; vertical-align:middle; }
.slideBox .bd img{ display:block;border:0; }
.slideBox .a{ text-decoration:none; color:#333; font:normal 12px/22px 宋体; }
/* 下面是前/后按钮代码,如果不需要删除即可 */
.slideBox .prev{ position:absolute; right:0px; top:48%; margin-top:0px; display:block; width:32px; height:40px; background:url(../images/l.png) no-repeat; filter:alpha(opacity=50);opacity:0.5; }
.slideBox .next{ position:absolute; left:auto; top:48%; margin-top:0px; display:block; width:32px; height:40px; background:url(../images/r.png) no-repeat; filter:alpha(opacity=50);opacity:0.5; }
.slideBox .prev:hover,
.slideBox .next:hover{ filter:alpha(opacity=100);opacity:1; }
.slideBox .prevStop{ display:none; }
.slideBox .nextStop{ display:none; }