1、TbDropDown是啥
上张图一看就明白了:
这是bootstrap提供的组件之一,在Yii bootstrap的插件当中对应于TbDropDown这个类。
2、为什么会遇到这个问题?
找到官方文档,我们可能习惯性的把代码抄下来了,如下:
array(
'class' => 'bootstrap.widgets.TbMenu',
'htmlOptions' => array('class' => 'pull-right'),
'items' => array(
array('label' => Yii::app()->user->name, 'url' => '#',
'items' => array(
array('label' => 'Login', 'url' => 'javascript:void(0);', 'visible' => Yii::app()->user->isGuest),
array('label' => 'Register', 'url' => 'javascript:createUser();','visible' => Yii::app()->user->isGuest),
array('label' => 'Logout (' . Yii::app()->user->name . ')', 'url' => array('/site/logout'), 'visible' => !Yii::app()->user->isGuest),
)),
),
),
可以参考: http://www.cniska.net/yii-bootstrap/#tbMenu
没有看到DropDown?哈哈,因为它潜伏在TbMenu当中的,一个TbMenu其实就是上图当中的Guest这个item,而所谓的DropDown其实就是下面的Login和Register。不信看源码:(bootstrap/widget/TbMenuBase.php line 96)
if (isset($item['items']) && !empty($item['items']))
{
$this->controller->widget('bootstrap.widgets.TbDropdown', array(
'encodeLabel'=>$this->encodeLabel,
'htmlOptions'=>isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions,
'items'=>$item['items'],
));
}
好的,弄清楚是什么的时候,就该为什么了。我们看到在创建TbMenu的时候,里面的item的参数只有一个'url,而这个参数实际上对应于最终生成的<a href=""></a>里的href属性-----哇,万一我想要让这个标签执行一段js脚本怎么办?
有人说那你就让url="javascrip:js_method()"不就完了。我想虽然不是很推荐这种做法,但总比不能实现强。后来执行了一段代码,这段代码有返回值,最初在搜狗浏览器上面运行毫无压力,然后蛋疼的事情终于发生在了ie和Firefox身上:浏览器直接跳转了,并把返回值给显示出来。
逃避总不是办法,还是想想怎么样弄个onclick属性上去才是正招。
3、解决之道
翻文档的事儿就别指望了,因为没有。只能看源码了。
bootstrap/widget/TbDropdown.php line 57:
if (isset($item['url']))
return CHtml::link($item['label'], $item['url'], $item['linkOptions']);
else
return $item['label'];
传了个linkOptions进去?!
CHtml::link:
public static function link($text,$url='#',$htmlOptions=array())
{
if($url!=='')
$htmlOptions['href']=self::normalizeUrl($url);
self::clientChange('click',$htmlOptions);
return self::tag('a',$htmlOptions,$text);
}
咋变htmlOptions了?!
CHtml::tag
public static function tag($tag,$htmlOptions=array(),$content=false,$closeTag=true)
{
$html='<' . $tag . self::renderAttributes($htmlOptions);
if($content===false)
return $closeTag && self::$closeSingleTags ? $html.' />' : $html.'>';
else
return $closeTag ? $html.'>'.$content.'</'.$tag.'>' : $html.'>'.$content;
}
renderAttributes函数的核心代码:
foreach($htmlOptions as $name=>$value)
{
if(isset($specialAttributes[$name]))
{
if($value)
{
$html .= ' ' . $name;
if(self::$renderSpecialAttributesValue)
$html .= '="' . $name . '"';
}
}
elseif($value!==null)
$html .= ' ' . $name . '="' . ($raw ? $value : self::encode($value)) . '"';
}
到这里,我们发现其实htmlOptions里面的键值对被原封不动的写入了html的a标签。
所以如果你想要在最后生成的a标签里面添加相应的属性,那么就在最开始的代码当中添加 'linkOptions'=>array(.....)
array(
'class' => 'bootstrap.widgets.TbMenu',
'htmlOptions' => array('class' => 'pull-right'),
'items' => array(
array('label' => Yii::app()->user->name, 'url' => '#',
'items' => array(
array('label' => 'Login', 'url' => 'javascript:void(0);', 'linkOptions' => array('onclick' => 'createUser()'), 'visible' => Yii::app()->user->isGuest),
array('label' => 'Register', 'url' => 'javascript:createUser();','visible' => Yii::app()->user->isGuest),
array('label' => 'Logout (' . Yii::app()->user->name . ')', 'url' => array('/site/logout'), 'visible' => !Yii::app()->user->isGuest),
)),
),
),
4、总结
(1)yii bootstrap的插件当中,经常会用htmlOptions为标签设置html属性,但这次居然用了linkOPtions(中间有一次变身你们还记得不?)
(2)没事儿还是看看源码吧。。。