6

在 Yii 中,有许多不同的方法可以让 CSS 进入你的页面。

问题是,一旦你开始使用扩展、小部件、主题等,它们都有自己的样式表(很公平),并且 CSS 被处理和插入 HTML 的顺序会根据它们是否设置在控制器、视图或布局,或者正在使用 Yii 资产管理器或 Yii 包管理器。

最近,我们的 Yii 项目被修改为使用注册在config/main.php中的包,方式如下:

'clientScript'=>array(
        'packages'=> array(
            'theme'=>array(
                'basePath'=>'yii.themes.default',
                'css'=>array('css/reset.css','css/main.css','css/form.css'),
                'js'=>array('js/lib.js'),
                'depends'=>array('jquery'),
            ),
...

这导致 CSS 文件中断,因为它旨在覆盖网格视图样式,并且现在包含在 CGridView 样式表之前。

解决方案是在底部添加这些行layouts/main.php

$path = Yii::getPathOfAlias('yii.themes.default').'/css/style.css';
$cssFile = Yii::app()->getAssetManager()->publish($path);
Yii::app()->getClientScript()->registerCssFile($cssFile);

对我来说,这感觉不是一个完美的解决方案,我希望将来我们可能会在忘记我们所做的事情时遇到问题,或者我们必须做一个不同主题的类似事情,或者完全不同的项目。

当 CSS 可以从这么多不同的来源提供时,是否有更好的方法来有效地管理 CSS?

编辑:

我正在考虑扩展 CClientScript 以提供“覆盖”类型的选项,您可以在其中指定一个 CSS 文件数组,您正在注册的文件应该包含在这些文件之后。不过感觉可能有点飘了。。。

4

2 回答 2

5

我提出了以下解决方案,使用类似于 z-index 工作方式的方法。尽管无论如何它都不是完美的。

默认情况下,样式表的优先级设置为 0,您可以使用registerCssandregisterCssFile将其设置为正整数或负整数。负整数会将文件插入到 CSS 的其余部分之前,正整数会将其发送到末尾。

config/main.php中,将 clientScript 设置为使用新类:

    'clientScript'=>array(
        'class' => 'components\ClientScript',
        ...

components/ClientScript.php

我正在玩弄指定注册文件之间的依赖关系而不是基于整数的优先级的想法,但没有遵循它。我暂时把这段代码留在这里,以防有人想接受它。

class ClientScript extends CClientScript
{

    protected $dependencies = array();
    protected $priority = array();

    public function renderHead(&$output)
    {
        $cssFilesOrdered = array();
        $currentCssFiles = $this->cssFiles;

        if (!empty($this->priority)){
            # assign 0 to anything without a specific priority
            # can't do this in the register method because not every CSS file that ends up here used it
            $cssFilesWithPrioritySet = array_keys($this->priority);
            foreach ($currentCssFiles as $path => $v){
                if (!in_array($path, $cssFilesWithPrioritySet)){
                    $this->priority[$path] = 0;
                }
            }

            asort($this->priority);
            foreach ($this->priority as $path => $id){
                $cssFilesOrdered[$path] = $currentCssFiles[$path];
                unset($currentCssFiles[$path]);
            }
            # add any remaining CSS files that didn't have an order specified
            $cssFilesOrdered += $currentCssFiles;
        }

        if (!empty($cssFilesOrdered)){
            $this->cssFiles = $cssFilesOrdered;
        }

        parent::renderHead($output);
    }

    public function registerCssFile($url, $media = '', $order = null)
    {
        $this->setOrder($url, $order);
        return parent::registerCssFile($url, $media);
    }

    public function registerCss($id, $css, $media = '', $order = null)
    {
        $this->setOrder($id, $order);
        return parent::registerCss($id, $css, $media);
    }

    private function setOrder($identifier, $order)
    {
        if (!is_null($order)){
            if (is_array($order)){
                $this->dependencies[$identifier] = $order;
            } elseif (is_numeric($order)){
                $this->priority[$identifier] = $order;
            }
        }
    }

}
于 2012-07-26T09:33:30.203 回答
0

我认为增强@bcmcfc 功能的更好方法是保持默认排序,同时确保优先排序。

我在这里修改了 renderHead() 函数。

public function renderHead(&$output)
{
    $cssFilesOrdered = array();
    $currentCssFiles = $this->cssFiles;
    //print_r($currentCssFiles);
    if (!empty($this->priority))
    {
        // sort priority array according to value (priority number)
        asort($this->priority);
        $tmp = array_values($this->priority);
        $startPriority = $tmp[0];
        # assign 0 to anything without a specific priority
        # can't do this in the register method because not every CSS file that ends up here used it
        $cssFilesWithPrioritySet = array_keys($this->priority);
        $startCounter = $startPriority-count($currentCssFiles);
        foreach ($currentCssFiles as $path => $v)
        {
            if (!in_array($path, $cssFilesWithPrioritySet))
            {
                $this->priority[$path] = $startCounter++;
            }
        }

        asort($this->priority);
        foreach ($this->priority as $path => $id)
        {
            $cssFilesOrdered[$path] = $currentCssFiles[$path];
            unset($currentCssFiles[$path]);
        }
    }

    if (!empty($cssFilesOrdered)){
        $this->cssFiles = $cssFilesOrdered;
    }
    # add any remaining CSS files that didn't have an order specified
    $cssFilesOrdered += $currentCssFiles;
    parent::renderHead($output);
}
于 2015-12-10T15:53:27.303 回答