跳转到主要内容
qingkong 提交于 26 June 2015

6.12 在主题中应用smacss(3)——Apply SMACSS in Drupal theme(3)

之前我们讨论了如何控制区块中的选择器,现在让我们来学习如何用类似的技巧控制字段的选择器。

我们知道,字段是Drupal7建设网站的基石。字段包含着内容,内容为王!在我们学习控制字段的选择器之前,我们应该先搞清楚drupal是如何把字段渲染出来的。关于这个知识点,请看第二章第三节

上次,我们从drupal核心复制了区块的模版文件blcok.tpl.php到自己的主题文件夹中,并进行了覆写,以达到掌控区块的主题层。对于字段来说,我们还是要使用类似的方法。字段在默认情况下是由主题函数theme_field()渲染的,所以为了改动这个函数,我们需要将它拷贝到自己主题文件夹中的template.php函数中进行覆写,将名字改为mytheme_field,这里的mytheme是自己的主题名称。

覆写后的新函数如下:

/**

 * Overrides theme_field()

 */

 

function mytheme_field($variables) {

  $output = '';

 

  // Render the label, if it's not hidden.

  if (!$variables['label_hidden']) {

    $output .= '<div ' . $variables['title_attributes'] . '>' . $variables['label'] . ':&nbsp;</div>';

  }

 

  // Render the items.

  $output .= '<div ' . $variables['content_attributes'] . '>';

  foreach ($variables['items'] as $delta => $item) {

    $output .= '<div ' . $variables['item_attributes'][$delta] . '>' . drupal_render($item) . '</div>';

  }

  $output .= '</div>';

 

  // Render the top-level DIV.

  $output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';

 

  return $output;

}

你会发现这段代码和核心中的theme_field很类似,只改动了其中两处。我们在这里将包裹字段标签和字段内容的div的硬编码的class选择器给移除了。

然后,我们可以在template.php中为字段加上预处理函数:

/**
 * Implements hook_preprocess_field()
 */
 
function mytheme_preprocess_field(&$vars) {
  /* 先创建几个变量,这样可以少打几个字 */
  $name = $vars['element']['#field_name'];
  $bundle = $vars['element']['#bundle'];
  $mode = $vars['element']['#view_mode'];
  $classes = &$vars['classes_array'];
  $title_classes = &$vars['title_attributes_array']['class'];
  $content_classes = &$vars['content_attributes_array']['class'];
  $item_classes = array();

$base_class = drupal_clean_css_identifier($field); 

  /* 字段的类选择器 */
  $classes[] = 'field-wrapper';
  $title_classes[] = 'field-label';
  $content_classes[] = 'field-items';
  $item_classes[] = 'field-item';
 
  /* Uncomment the lines below to see variables you can use to target a field */
  // print '<strong>Name:</strong> ' . $name . '<br/>';
  // print '<strong>Bundle:</strong> ' . $bundle  . '<br/>';
  // print '<strong>Mode:</strong> ' . $mode .'<br/>';
 
  /* 例子,为指定的字段加上特定的类选择器 */
  switch ($mode) {
    /* 所有的 teaser模式字段 */
    case 'teaser':
      switch ($name) {
        /* Teaser read more links */
        case 'node_link':
          $item_classes[] = 'more-link';
          break;
        /* Teaser descriptions */
        case 'body':
        case 'field_description':
          $item_classes[] = 'description';
          break;
      }
      break;
  }
  /* 根据名称 */
  switch ($name) {
    case 'field_authors':
      $title_classes[] = 'inline';
      $content_classes[] = 'authors';
      $item_classes[] = 'author';
      break;
  }
 
 /* 添加奇偶类 */
  foreach ($vars['items'] as $delta => $item) {
    $vars['item_attributes_array'][$delta]['class'] = $item_classes;
    $vars['item_attributes_array'][$delta]['class'][] = $delta % 2 ? 'even' : 'odd';
  }
}

 

说了这么多,肯定还是会有很多人觉得很难控制Drupal输出的各种css选择器,是的,关于这一点,几乎每个themer都抱怨过:It sucks!

如果你发现有某个选择器你实在不知道如何控制,你还可以用一个比较迂回的办法,不过这需要你会用CSS预处理机制:比如sass中的@extend,这样你可以为自己需要的某个选择器写好样式,然后让drupal为你提供的选择器来extend这些样式。

ok,到此,虽然我们并没有完整的讲述在Drupal中各种改写选择器并实施SMACSS架构的方法,但是,至少证明这在一定程度上是可行的。

我们知道,开发者在开发Drupal7的时候,SMACSS之类的模块化CSS思想还没有出现。因此,正如前面所说的,Drupal7的CSS在构架方面存在着诸多弱点——虽然以当初的观点来看,大家都认为已经算是很不错的解决方案了。然而随着各方面经验的积累、大型实战项目的挑战及新兴观念和技术的普及,人们逐渐认识到这些问题,并尝试在自己的项目中,甚至新的Drupal8开发中加以改善。D8的整个前端构架都应用了SMACSS的思想,而我们在这几节中的讨论,则是试图改善D7中的问题。

Drupal 版本