[组件库] Navbar

51 阅读3分钟

实现

  1. toggle 的随着页面缩放,显示或隐藏。主要取决于 .xx-navbar-expand--#{size}

    • 默认 ul.navbar-nav 为竖直排版 flex-direction: column
    • 在大屏(PC)>=992px 的时候,使用 .xx-navbar-expand-lg,则水平排版
      // @stage 0
      .xx-navbar-expand--lg {
        @(min-width: 992px) {
          flex-flow: row nowrap; // 替换 space-between
          justify-content: flex-start;
      
          .navbar-toggler {
            display: none;
          }
      
          .navbar-nav {
            flex-direction: row;
          }
        } // end media query
      } // end .xx-navbar-expand--lg
      
      // @stage 1
      $xxid-breakpoints: (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px) !default;
      .xx-navbar-expand {
      
        @each $breakpoint, $size in $xxid-breakpoints {
          &--#{$breakpoint} {
            @media (min-width: $size) {
              flex-flow: row nowrap;
              justify-content: flex-start;
      
              .navbar-toggler {
                display: none;
              }
              .navbar-nav {
                flex-direction: row;
              }
            } // end media query
          }// end &--#{$breakpoint}
        } // end @each
      } // end xx-navbar-expand
      
      
      // @stage 2
      $xxid-breakpoints: (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px) !default;
      .xx-navbar-expand {
        @each $breakpoint in map-keys($xxid-breakpoints) {
          &--#{$breakpoint} {
      
            /* 其中:@media (min-width: 0) 是没有意义的,也就是:
            xx-navbar-expand-xs {
              // 没有这个: @media (min-width: 0) {xx style code}
              xx style code
            }
            */
      
            @include media-breakpoint-up($breakpoint) {
              // direction:  row
              // 是否换行: 不换行
              flex-flow: row nowrap; // 替换 space-between
              justify-content: flex-start;
              .navbar-toggler {
                display: none;
              }
              .navbar-nav {
                flex-direction: row;
              }
            }
          }
        }
      }
      
      // @stage2 mixin
      @function breakpoint-min($breakpoint, $breakpoints: $xxid-breakpoints) {
        // map-get(Object, key) like Object[key] in JavaScript
        $min: map-get($breakpoints, $breakpoint);
        // return $min || null
        @return if($min !=0, $min, null);
      }
      
      @mixin media-breakpoint-up($name, $breakpoints: $xxid-breakpoints) {
        // let $min = breakpoint-min($name, $breakpoints)
        $min: breakpoint-min($name, $breakpoints); //  >= 576px
        @if $min {
          @media (min-width: $min) {
            @content;
          }
        }
        @else {
          @content;
        }
      }
      
      // 题外话:sass、less 类预编译工具的语法真是恶心,为啥不能写的像 JavaScript 呢? 完全就是在学习一门新语言!
      
  2. navbar 在大屏状态下的 background-color 以及 在小屏 && 展开菜单状态的 background-color 如何定义?

    • 想想就像夸自己,使用一个比较完美的方案解决
    • 大屏幕(PC):navbar-toggler 隐藏、.navbar-nav 中的元素变为水平显示。
    在 <xx-navbar></xx-navbar> 直接添加背景色、作为整个导航条的背景色,给 slot="routes" 设置背景色,作为菜单展开时候的背景色
    但是这边会存在一个致命的问题:无论导航条怎么伸缩,通过 .navbar-nav 添加的背景色,将会作用在 除了 brand 之外的所有导航区域。
    这样就导致了 导航条的背景色和 链接区的背景色冲突。画个图示意一下
    而我们给 .navbar-nav 元素添加背景色最初本意是:解决页面缩小的时候,展开菜单的背景色是透明色,无法看清上面的文字。
    
    1. 在当前情况下,导航条整体背景是白色的
    2. 开始 缩小浏览器 viewport
    3. 可以看到,导航区域的菜单,由水平导航变成
    了竖直导航。但是竖直导航的背景色是透明的,
    和下面的文字内容重叠,根本无法正常使用。所以
    我们需要给「展开、收起」的部分加上背景色,比如:
    红色
    4. 可以看到现在菜单部分背景色变成了红色,这样
    菜单部分便非常清晰了,不会收到下面内容的影响
    5. 让我们来拉伸浏览器窗口,让其回到大屏模式,也
    就是PC 浏览模式
    6. 开始拉伸
    7. 好了,我们可以看到拉伸的效果。brand 右边的
    菜单部分的背景色也变成了红色,这个可不是我们想要
    的,我们想要的是,在浏览器viewport 缩小的时候
    背景变成红色,展开的时候(navbar-togger)隐藏时候,
    背景色仍然和整体导航条一个颜色,这时候该怎么办呢?
    - 传入变量,伸展时候的菜单颜色和收缩时候的菜单颜色??
    目测不行,因为我们传入的是一个JS变量,也就是 vue的
    prop,这个如何和 media-query相互结合呢?总不能用
    window.resize 函数来兼听viewport 宽度吧
    
    - 最终的问题就出现在:我们需要在
    .xx-navbar-expand-lg(media and (min-width:992px))
    的时候,隐藏.navbar-nav 的背景色。隐藏背景色手段就是:
    设置
    .xx-navbar-expand-lg(media and (min-width:992px)) {
      .navbar-nav {
        background-color: transparent;
      }
    }
    
    8. ok 问题解决!
    
    组件本身实现:在 .xx-navbar-expand-lg { } 的时候,设置 .navbar-nav 的背景色为 transparent
    

关键点

  1. css

    1. last-of-type
    2. nth-last-of-type(2)
  2. v-directive v-clickoutside v-responsive