ng-alain对sidebar-nav进行修改实现菜单布局切换

 一、背景

希望菜单项可以放在顶部

之前使用样式修改修改过第一版,后来发现问题较多,而且样式修改起来特别麻烦,因此通过对sidebar-nav的修改满足需求。

二、实现 

1、主要是通过修改sidebar-nav.component.js,实现新的nav组件

// =========LAYOUTS=========
@import './../../../styles/theme';
@import './../../../styles/index';

.ad-nav-head-div {
  float: left;
  margin-left: 20px;
  width: 100%;
  height: 60px;
}
.ad-nav-head {
  float: left;
  list-style-type: none;
  margin-top: -10px;
  border-right: 1px solid @content-heading-border;
  .ad-nav-li-head {
    float: left;
    list-style-type: none;
    border-left: 0 solid transparent;
    border-bottom: 0 solid transparent;
    transition: border-bottom-color 0.4s ease;
    .ad-nav-li-hend-ui {
      float: left;
      list-style-type: none;
      position: absolute;
      top: 48px;
      background-color: @aside-bg;
    }
  }
  .ad-nav__-head-selected {
    background-repeat: no-repeat;
    background-size: 100% 100%;
    height: 100%;
    background-position: center center;
    background-image: url('../../../assets/img/nav/nav-selected-bg.png');
  }
  .ad-nav__-head-selected > a {
    color: @blue-color2;
  }
}
.ad-nav-li-head-hidden {
  display: none !important;
}
import {
  Component,
  OnInit,
  HostListener,
  ChangeDetectorRef,
  ElementRef,
  Renderer2,
  Input,
  Output,
  EventEmitter,
  OnDestroy,
  AfterViewInit,
} from '@angular/core';
import { LayoutChangeService } from '@core/layout/layoutChange.service';
import { Router, NavigationEnd } from '@angular/router';
import { LocationStrategy } from '@angular/common';
import { MenuService, SettingsService, Menu } from '@delon/theme';
import { filter } from 'rxjs/operators';
import { Subscription } from 'rxjs/Subscription';
/** @type {?} */
const SHOWCLS = 'ad-nav__floating-show';
/** @type {?} */
const FLOATINGCLS = 'ad-nav__floating';
/*头部selected样式*/
const HEDNSELECTED = 'ad-nav__-head-selected';
/*左树选中样式*/
const LEFTSELECTED = 'ad-nav__selected';

@Component({
  selector: 'app-header-nav',
  template: `
    
  `,
  styleUrls: ['./header.nav.Component.less'],
})

//  extends SidebarNavComponent
export class HeaderNavComponent implements OnInit, OnDestroy, AfterViewInit {
  constructor(
    public menuSrv: MenuService,
    public settings: SettingsService,
    public router: Router,
    public locationStrategy: LocationStrategy,
    public render: Renderer2,
    public cd: ChangeDetectorRef,
    public el: ElementRef,
    public layoutService: LayoutChangeService,
  ) {
    this.subscription = layoutService.Status$.subscribe(message => {
      // 获取当前的布局状态
      this.loyout = message;
      this.initCollapsed();
      this.setRouterLinkActive();
      this.initSidebar('init');
    });
  }
  subscription: Subscription;
  public loyout = this.layoutService.getLayout;
  bodyEl: any;
  list = [];
  doc = document;
  @Input() autoCloseUnderPad = true;
  @Output('select') select = new EventEmitter();
  rootEl = this.el.nativeElement;
  private change$: any;
  floatingEl: HTMLDivElement;
  private routerLinkActive: any = this.initRouterLinkActive();
  private route$;
  private sidebar$;
  // 确定光标是否在下拉菜单上面
  private isOnUl = false;
  // 监听切换ipad按钮事件
  @HostListener('document:click', ['$event.target'])
  onClick() {
    this.hideAll();
  }
  // propDecorators = {
  //   autoCloseUnderPad: [{ type: Input }],
  //   select: [{ type: Output }],
  //   onClick: [{type: HostListener, args: ['document:click', ['$event.target']]}]
  // };
  /**
   * 对选中样式进行初始化
   */
  public initRouterLinkActive() {
    this.routerLinkActive = this.loyout ? HEDNSELECTED : LEFTSELECTED;
  }

  /**
   * 切换时交替设置选中的样式
   */
  private setRouterLinkActive() {
    this.initRouterLinkActive();
    let oldSelectDom;
    let delClassName;
    let addClassName;
    if (this.loyout) {
      addClassName = HEDNSELECTED;
      delClassName = LEFTSELECTED;
      oldSelectDom = this.rootEl.querySelector('.' + LEFTSELECTED);
    } else {
      addClassName = LEFTSELECTED;
      delClassName = HEDNSELECTED;
      oldSelectDom = this.rootEl.querySelector('.' + HEDNSELECTED);
    }
    this.render.addClass(oldSelectDom, addClassName);
    this.render.removeClass(oldSelectDom, delClassName);
  }
  ngOnInit() {
    const me = this;
    this.bodyEl = this.doc.querySelector('body');
    this.menuSrv.openedByUrl(this.router.url);
    this.genFloatingContainer();
    this.change$ = /** @type {?} */ (this.menuSrv.change.subscribe(function(
      res,
    ) {
      me.list = res;
      me.cd.detectChanges();
    }));
    this.installUnderPad();
    this.initRouterLinkActive();
  }

  ngAfterViewInit() {
    this.initCollapsed();
    this.sidebar$ = this.bodyEl.querySelector('app-sidebar');
    this.initSidebar('init');
  }

  /**
   * 处理当ipad场景是 menu在上面需要把ipad按钮隐藏
   */
  initCollapsed() {
    if (this.settings.layout.collapsed && this.loyout) {
      this.settings.setLayout('collapsed', !this.settings.layout.collapsed);
    }
  }
  /**
   * 处理在顶部的高度 避免遮挡tip
   * @param type init show hide
   */
  initSidebar(type) {
    const me = this;
    const dom = me.sidebar$ || this.bodyEl.querySelector('app-sidebar');
    if (me.loyout) {
      switch (type) {
        case 'show':
          if (dom.style.height !== '') {
            dom.style.height = '';
          }
          break;
        case 'hide':
          if (dom.style.height === '') {
            dom.style.height = '60px';
          }
          break;
        default:
          if (dom.style.height === '') {
            dom.style.height = '60px';
          }
      }
    } else {
      if (dom.style.height !== '') {
        dom.style.height = '';
      }
    }
  }

  /**
   * 设置app-sidebar高度 将app-sidebar显示出来
   */
  showSidebar() {
    this.initSidebar('show');
  }
  /**
   * 设置app-sidebar高度 将app-sidebar隐藏
   */
  hideSidebar() {
    this.initSidebar('hide');
  }
  floatingAreaClickHandle(e) {
    e.stopPropagation();
    /** @type {?} */
    const linkNode = /** @type {?} */ (e.target);
    if (linkNode.nodeName !== 'A') {
      return false;
    }
    /** @type {?} */
    let url = linkNode.getAttribute('href');
    if (url && url.startsWith('#')) {
      url = url.slice(1);
    }
    if (linkNode.dataset['type'] === 'external') {
      return true;
    }
    /** @type {?} */
    const baseHerf = this.locationStrategy.getBaseHref();
    if (baseHerf) {
      url = url.slice(baseHerf.length);
    }
    this.router.navigateByUrl(url);
    this.onSelect(this.menuSrv.getPathByUrl(url).pop());
    this.hideAll();
    e.preventDefault();
    return false;
  }

  clearFloatingContainer() {
    if (!this.floatingEl) {
      return;
    }

    this.floatingEl.removeEventListener(
      'click',
      this.floatingAreaClickHandle.bind(this),
    );
    // fix ie: https://github.com/cipchk/delon/issues/52
    if (this.floatingEl.hasOwnProperty('remove')) {
      this.floatingEl.remove();
    } else if (this.floatingEl.parentNode) {
      this.floatingEl.parentNode.removeChild(this.floatingEl);
    }
  }
  genFloatingContainer() {
    this.clearFloatingContainer();
    this.floatingEl = this.render.createElement('div');
    this.floatingEl.classList.add(FLOATINGCLS + '-container');
    this.floatingEl.addEventListener(
      'click',
      this.floatingAreaClickHandle.bind(this),
      false,
    );
    this.bodyEl.appendChild(this.floatingEl);
  }
  genSubNode(linkNode, item) {
    /** @type {?} */
    const id = '_sidebar-nav-' + item['__id'];
    /** @type {?} */
    const node = /** @type {?} */ (linkNode.nextElementSibling.cloneNode(true));
    node.id = id;
    node.classList.add(FLOATINGCLS);
    node.addEventListener(
      'mouseleave',
      function() {
        node.classList.remove(SHOWCLS);
      },
      false,
    );
    this.floatingEl.appendChild(node);
    return node;
  }
  hideAll() {
    /** @type {?} */
    const allNode = this.floatingEl.querySelectorAll('.' + FLOATINGCLS);
    for (let i = 0; i < allNode.length; i++) {
      allNode[i].classList.remove(SHOWCLS);
    }
  }
  calPos(linkNode, node) {
    /** @type {?} */
    const rect = linkNode.getBoundingClientRect();
    /** @type {?} */
    const scrollTop = Math.max(
      this.doc.documentElement.scrollTop,
      this.bodyEl.scrollTop,
    );
    /** @type {?} */
    const docHeight = Math.max(
      this.doc.documentElement.clientHeight,
      this.bodyEl.clientHeight,
    );
    /** @type {?} */
    let offsetHeight = 0;
    if (docHeight < rect.top + node.clientHeight) {
      offsetHeight = rect.top + node.clientHeight - docHeight;
    }
    node.style.top = rect.top + scrollTop - offsetHeight + 'px';
    node.style.left = rect.right + 5 + 'px';
  }

  /**
   * ipad 产品下 鼠标放在图标上显示菜单
   * @param e
   * @param item
   * @param type
   */
  showSubMenu(e, item, type) {
    if (this.loyout) {
      this.toggleOpen(item, type);
      return;
    }
    if (this.settings.layout.collapsed !== true) {
      return;
    }
    e.preventDefault();
    /** @type {?} */
    const linkNode = /** @type {?} */ (e.target);
    this.genFloatingContainer();
    /** @type {?} */
    const subNode = this.genSubNode(/** @type {?} */ (linkNode), item);
    this.hideAll();
    subNode.classList.add(SHOWCLS);
    this.calPos(/** @type {?} */ (linkNode), subNode);
  }

  /**
   * 对外接口
   * @param item
   */
  onSelect(item) {
    this.select.emit(item);
  }

  /**
   * 判断是否在下来菜单上
   */
  checkPosition(item, type) {
    if (this.loyout) {
      this.isOnUl = type;
      if (!type) {
        this.toggleOpen(item, type);
      }
    }
  }
  toggleOpen(item, type) {
    if (this.loyout) {
      // 鼠标在menu上 将menu显示出来
      setTimeout(() => {
        if (this.isOnUl) {
          return;
        }
        this.toggleOpenHead(item, type);
      }, 300);
    }
  }

  /**
   * 处理头部显示隐藏
   * @param item
   * @param type
   */
  toggleOpenHead(item, type) {
    if (type) {
      this.showSidebar();
    } else {
      this.hideSidebar();
    }
    this.menuSrv.visit(function(i, p) {
      if (i !== item) {
        i['_open'] = false;
      }
    });
    /** @type {?} */
    let pItem = item['__parent'];
    while (pItem) {
      pItem._open = true;
      pItem = pItem.__parent;
    }
    item._open = type;
    this.cd.markForCheck();
  }

  /**
   *
   * @param item
   */
  toggleOpenFun(item) {
    if (this.loyout) {
      return;
    }
    this.menuSrv.visit(function(i, p) {
      if (i !== item) {
        i['_open'] = false;
      }
    });
    /** @type {?} */
    let pItem = item['__parent'];
    while (pItem) {
      pItem._open = true;
      pItem = pItem.__parent;
    }
    item._open = !item._open;
    this.cd.markForCheck();
  }

  ngOnDestroy() {
    this.change$.unsubscribe();
    this.subscription.unsubscribe();
    if (this.route$) {
      this.route$.unsubscribe();
    }
    this.clearFloatingContainer();
  }

  installUnderPad() {
    const me = this;
    if (!this.autoCloseUnderPad) return;
    this.route$ = /** @type {?} */ (this.router.events
      .pipe(
        filter(function(e) {
          return e instanceof NavigationEnd;
        }),
      )
      .subscribe(function(s) {
        return me.underPad();
      }));
    this.underPad();
  }
  underPad() {
    const me = this;
    if (window.innerWidth < 992 && !this.settings.layout.collapsed) {
      setTimeout(function() {
        return me.settings.setLayout('collapsed', true);
      });
    }
  }
}

 

你可能感兴趣的:(angular,ng-alain)