Php 从Yii中的registerScript方法强制执行脚本顺序
我创建了一个小部件,它可以注册自己的脚本,如下所示Php 从Yii中的registerScript方法强制执行脚本顺序,php,yii,Php,Yii,我创建了一个小部件,它可以注册自己的脚本,如下所示 class MyWidget extends CWidget { public function run(){ Yii::app()->clientScript->registerScript(__CLASS__, <<<JAVASCRIPT var a = "Hello World!"; JAVASCRIPT , CClientScript::POS_END); }
class MyWidget extends CWidget {
public function run(){
Yii::app()->clientScript->registerScript(__CLASS__, <<<JAVASCRIPT
var a = "Hello World!";
JAVASCRIPT
, CClientScript::POS_END);
}
}
正如我们所看到的,上面的代码不起作用,所以我需要把第二行放在第一行之上
你知道怎么强制下订单吗?我可以扩展CClientScript
(并创建一个新的registerScript
方法),只要所有脚本都呈现在结束位置,并且我不必将上面的内联Javascript代码拉到新的包或文件中。尝试注册到头部
Yii::app()->clientScript->registerScript(__CLASS__, <<<JAVASCRIPT
var a = "Hello World!";
JAVASCRIPT
, CClientScript::POS_HEAD);
Yii::app()->clientScript->registerScript(\uuuu CLASS\uuuu,),所以我终于找到了一个解决方法。我扩展了一个新的clientScript
类,并修改了registerScript
方法,这样它将接受另一个参数$level
public function registerScript($id, $script, $position = self::POS_END, $level = 1);
考虑$level
就像CSS中的z-index
一样,除了$level
的数量越多,脚本的位置就越低
比如说
Yii::app()->clientScript->registerScript('script1', '/** SCRIPT #1 **/', CClientScript::POS_END, 1);
Yii::app()->clientScript->registerScript('script2', '/** SCRIPT #2 **/', CClientScript::POS_END, 2);
Yii::app()->clientScript->registerScript('script3', '/** SCRIPT #3 **/', CClientScript::POS_END, 1);
尽管script3
在script2
之后声明,但在呈现的脚本中,它将显示在script2
上方,因为script2
的$level
值大于script3
这是我的解决方案代码。它的工作原理与我想要的一样,尽管我不确定安排方法是否足够优化
/**
* ClientScript manages Javascript and CSS.
*/
class ClientScript extends CClientScript {
public $scriptLevels = array();
/**
* Registers a piece of javascript code.
* @param string $id ID that uniquely identifies this piece of JavaScript code
* @param string $script the javascript code
* @param integer $position the position of the JavaScript code.
* @param integer $level the rendering priority of the JavaScript code in a position.
* @return CClientScript the CClientScript object itself (to support method chaining, available since version 1.1.5).
*/
public function registerScript($id, $script, $position = self::POS_END, $level = 1) {
$this->scriptLevels[$id] = $level;
return parent::registerScript($id, $script, $position);
}
/**
* Renders the registered scripts.
* Overriding from CClientScript.
* @param string $output the existing output that needs to be inserted with script tags
*/
public function render(&$output) {
if (!$this->hasScripts)
return;
$this->renderCoreScripts();
if (!empty($this->scriptMap))
$this->remapScripts();
$this->unifyScripts();
//===================================
//Arranging the priority
$this->rearrangeLevels();
//===================================
$this->renderHead($output);
if ($this->enableJavaScript) {
$this->renderBodyBegin($output);
$this->renderBodyEnd($output);
}
}
/**
* Rearrange the script levels.
*/
public function rearrangeLevels() {
$scriptLevels = $this->scriptLevels;
foreach ($this->scripts as $position => &$scripts) {
$newscripts = array();
$tempscript = array();
foreach ($scripts as $id => $script) {
$level = isset($scriptLevels[$id]) ? $scriptLevels[$id] : 1;
$tempscript[$level][$id] = $script;
}
foreach ($tempscript as $s) {
foreach ($s as $id => $script) {
$newscripts[$id] = $script;
}
}
$scripts = $newscripts;
}
}
}
因此,我只需要将该类作为clientScript组件放入配置中
'components' => array(
'clientScript' => array(
'class' => 'ClientScript'
)
)
我已经为Yii提供了一个补丁,以允许排序(前置、追加、编号)
你可以在这里找到它
如果它没有进入您的位置,那么您可以将CClientScript扩展到您自己的类以应用我的更改
但一般来说,正确编写的JS应该独立于顺序工作
例如,您不需要定义一些全局范围变量,而是可以将它们作为属性分配给窗口(访问不存在的属性不会在js中引发错误)无需扩展CClienScript。解决此问题的简单方法是在控制器中的控制器中创建$script数组,并将视图脚本添加到该变量中。在布局文件中,在注册了要在其之前呈现的脚本后,您将注册存储在$scripts数组中的脚本。e、 g:
在控制器中
public $scripts = [];
在您的布局中:
$baseURL = Yii::app()->request->baseUrl;
$clientScript = Yii::app()->clientScript;
$clientScript->registerScriptFile( $baseURL . '/js/jquery.min.js', CClientScript::POS_END );
$clientScript->registerScriptFile( $baseURL . '/js/bootstrap.min.js', CClientScript::POS_END);
在您看来
<?php array_push($this->scripts,"/js/summernote.min.js");?>
重写CClientScript类,正如@Petra所说,这是我在使用@Petra code之后使用的代码,但它对我来说并不适用
class ClientScript extends CClientScript {
public $scriptLevels;
public function registerScript($id, $script, $position = null, $level = 1, array $htmlOptions = array()) {
$this->scriptLevels[$id] = $level;
return parent::registerScript($id, $script, $position, $htmlOptions);
}
public function render(&$output) {
foreach ($this->scripts as $key => $value) {
$this->scripts[$key] = $this->reorderScripts($value);
}
parent::render($output);
}
public function reorderScripts($element) {
$tempScripts = array();
$buffer = array();
foreach ($element as $key => $value) {
if (isset($this->scriptLevels[$key])) {
$tempScripts[$this->scriptLevels[$key]][$key] = $value;
}
}
ksort($tempScripts);
foreach ($tempScripts as $value) {
foreach ($value as $k => $v) {
$buffer[$k] = $v;
}
}
return $buffer;
}
}
然后,转到配置文件,在组件部分编辑以下内容:
'components' => array(
.
.
'clientScript' => array(
'class' => 'ClientScript'
),
)
我的意图是在最后呈现所有脚本。问题是小部件中的脚本取决于jQuery,我通过设置coreScriptPosition
字段()作为POS_END.Well,您有一个坏主意,或者您必须将var声明拆分为HEAD,widgets脚本的body ot END,或者您必须将END更改为READY:Yii::app()->clientScript->registerScript('script'),
<?php array_push($this->scripts,"/js/summernote.min.js");?>
class ClientScript extends CClientScript {
public $scriptLevels;
public function registerScript($id, $script, $position = null, $level = 1, array $htmlOptions = array()) {
$this->scriptLevels[$id] = $level;
return parent::registerScript($id, $script, $position, $htmlOptions);
}
public function render(&$output) {
foreach ($this->scripts as $key => $value) {
$this->scripts[$key] = $this->reorderScripts($value);
}
parent::render($output);
}
public function reorderScripts($element) {
$tempScripts = array();
$buffer = array();
foreach ($element as $key => $value) {
if (isset($this->scriptLevels[$key])) {
$tempScripts[$this->scriptLevels[$key]][$key] = $value;
}
}
ksort($tempScripts);
foreach ($tempScripts as $value) {
foreach ($value as $k => $v) {
$buffer[$k] = $v;
}
}
return $buffer;
}
}
'components' => array(
.
.
'clientScript' => array(
'class' => 'ClientScript'
),
)