我有一个用于创建模板的HTML类。 我的班级是这样的:
<?php
$page = \TEST\HTML::dispense(':html');
$page->mainWrapper(':div') //creates a child object by using __call() and sets the "div" model
->id('mainWrapper') //sets id
->style('background','red') //adds a style
->text('blah') //adds a text
->addClass('someClass'); //adds a class
->someSpan(':span')
->addClass('spanClass')->addClass('someClass')
->style('font-size','12pt')
->style('border-bottom','1pt dashed black')
->style('background','red');
?>
这使我能够快速开发html标记,而不必担心丢失的字符或错误引用的属性。一切都被缓存,我没有性能问题。
现在我想更进一步。在生产模式下,一切正常,但对于最终输出,我想删除所有内联“样式”属性并最小化它们并将它们缓存在css文件中。 现在,我有一个循环遍历所有HTML对象的函数,并根据标记,id和类聚合数据。 我的问题是:一旦我以这种形式获得了整齐的css数组:
$style['tag']['.class']['#id']['styleKey'] = styleValue
如何修剪冗余值,以便留下相关的css文件?缩小和gzipping可以在稍后阶段进行。我现在想要的是比较值并在转储之前优化数组,以便将具有相同标记/ id /类的所有元素共同的所有'styleKeys'组合在一起。
所以在上面的例子中,例如,由于两个元素(div和span)共享样式“background:red”和类“someClass”,我将有一个“someClass”CSS规则“background:红色的“
如果有任何兴趣,这是我的“提取方式”功能:
<?php
public static function extractStyles($element, array &$styles=array()){
if($element instanceof \TEST\HTML){$element = $element->htmlData();}
$tag = isset($element['#acronym']) ? $element['#acronym'] : NULL;
$id = isset($element['#id']) ? '#'.$element['#id'] : NULL;
$classes = isset($element['#class']) ? $element['#class'] : NULL;
if(isset($element['#style']) && ($tag || $id || $class)){
$ref = &$styles;
if($id){if(!isset($ref[$id])){$ref[$id] = array();};$ref = &$ref[$id];}
if($classes){
if(\is_array($classes)){$classes = '.'.implode('.',$classes);}
if(!isset($ref[$classes])){$ref[$classes] = array();};$ref = &$ref[$classes];
}
if($tag){if(!isset($ref[$tag])){$ref[$tag] = array();};$ref = &$ref[$tag];}
foreach($element[self::ATTRIBUTES]['#style'] as $style=>$value){
$ref[$style] = $value;
}
}
if(isset($element[self::CHILDREN]) && count($element[self::CHILDREN])){
foreach($element[self::CHILDREN] as $child){
self::extractStyles($child, $styles);
}
}
return $styles;
}
?>
任何指针都会受到欢迎......我真的迷路了。我甚至不知道我所寻找的是否可行。
如上所述,性能暂时不是问题。如果它有效,我会找到一种优化它的方法。 此外,请不要链接到xCSS和其他框架,因为它们处理字符串,我的CSS创建为数组。 提前感谢你们给我的任何帮助!
答案 0 :(得分:2)
第一顺序优化是构建层次结构树。此树中的父对子关系是子对象是父对象的超集。此树的根节点是空样式(您不会显示它)。
因此,如果你有
.parent {
background: red;
}
.childA {
background: red;
border: 1px solid black;
}
.childB {
background: red;
font-weight: 800;
}
父级被设置为树中的最小公分母。然后可以将其压缩为3个类,文本更少。子元素将包含路径中的所有类。如果您最初拥有<span class="childA">
,那么您将获得<span class="parent childA">
压缩类看起来像:
.parent {
background: red;
}
.childA {
border: 1px solid black;
}
.childB {
font-weight: 800;
}
关于ID的说明,ID始终是最合适的类的子级。因此,如果你有
#menu {
background: red;
border: 1px solid black;
margin: 15px 40px;
color: white;
}
它将成为ChildA的孩子,其css将缩减为
#menu {
margin: 15px 40px;
color: white;
}
显示为<ul id="menu" class="parent childA">
要创建树,您将需要一个对象来存储相同子对象的数组(递归)和一个函数,当给定两个对象时,可以确定它们的css是否是子集,相等或超集,差异,或者没有共性。
如果你不熟悉二元搜索树,那么现在是讨论这个问题的好时机,尽管这会比这更复杂,但它将是朝着正确方向迈出的良好开端。
二阶优化是确定子元素的嵌套是否可以进一步减少类的需要。例如,如果<li>
内的所有<ul id="#menu">
内容都设置得相似,那么您可以为#menu li
为此,您需要转到每个节点并分析其子节点。如果同一节点类型的所有子节点共享一个公共样式元素(使用上面的set comparer),则将公共集元素提取为父节点。差异成了孩子们。
让我们说你有这个例子(注意事项已经通过第1遍):
<ul id="menu" class="parent childA">
<li class="top menuli">Item</li>
<li class="menuli">Item</li>
<li class="menuli">Item</li>
<li class="menuli">Item</li>
<li class="bottom menuli">Item</li>
</ul>
我们注意到所有<li>
都有一个共同的元素.menuli,这意味着我们可以删除在第1遍中创建的这个类,并用平坦的#menu li
规则替换它。我们通过从每个子li中删除menuli类,并用.menuli
规则替换#menu li
规则来实现此目的。
我们的css改变如下:
#menu {
margin: 15px 40px;
color: white;
}
.menuli {
font-size: 30px;
font-weight: 800;
margin: 8px 0;
}
到
#menu {
margin: 15px 40px;
color: white;
}
#menu li {
font-size: 30px;
font-weight: 800;
margin: 8px 0;
}
html失去了课程menuli
<ul id="menu" class="parent childA">
<li class="top">Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li class="bottom">Item</li>
</ul>
在搜索节点树而不是深度优先搜索时,请记住使用广度优先搜索。如果你是积极的,你可以在许多路径上继续检查类似标签的第二级别,常见的二级搜索可能会显示#menu li a
或#container div p
等类似的类。如果你允许,这将成为NP难题无限深度搜索。
希望这会有所帮助。如果这是你想要的方向,我很乐意帮助提供更多关于集合比较器和树搜索器的代码,尽管这样做要复杂得多。