ダイナミックなスライダーで角のNavbarを作成する方法


つは、角度devs幸せを想像しなければなりません


前に角で新しいプロジェクトを始めました.
私はすぐに角度の学習曲線は反応よりもはるかに急であることに気づいた.そして、もしあなたが少しのFe経験にゼロで絶対的な初心者であるならば、これは多分本当です.

-物事を行う方法


たとえば、反応を使用してビルドを開始するには、アプリケーションを起動するには、CRA(Create Reaction App)NPMパッケージを使用できます.その後、アプリを開くことができます.JSファイルは、あなたのHTML(JSX)、JavaScript、さらにはCSSコードを書き始めます.スタイルのコンポーネントのようなJSツールのCSSを使用することで.だから、すべての懸念は、単一のファイルに入る!
また、コンポーネント、状態、および小道具のようないくつかの基本的な概念を理解する必要があります.プラスいくつかの非常に基本的なFPのもの.そして、それは多かれ少なかれ.
もちろん、物事の複雑さは、アプリケーションの複雑さが大きくなる傾向がある.そして、より多くの概念、デザインパターン、ライブラリ、およびツールを学ぶ必要があります最終的にマスター(反応ルータ、グローバル州管理、redux、r - thunk、R -佐賀、レンダリング最適化のテクニックなど).
しかし、このすべてはオプションです(反応コアライブラリの一部ではありません).余分なもののほとんどは、サードパーティのライブラリの形式で来る.

-物事を行う角度


角度は全く新しいレベルに物事を取ります.あなたが有名なto doリストを構築する場合は、“Hello World”は、1つのページのアプリケーションの世界で相当する場合は、角のアプリをブートストラップすることはできませんし、単一のファイルにJavaScriptコードを書き始める.
まず、角度、特定の抽象化といくつかの新しいデザインパターン、コンポーネント、ディレクティブ、テンプレート、OOPの基礎、依存性の注入、および多くを学ぶ必要があります.
あなたは、私が反応のために同じことを言ったと主張することができます.両方のケースでは、ライブラリ固有の基本的なものを何かを構築する前に学ぶ必要があります.これは本当です.しかし、私の意見では、角度は反応に比べてその基本的なものの多くを持っています.
また、角のアプリを書くために入力スクリプトを知る必要があります.それは必須ではありませんが、受け入れられた業界標準です.
また、HTML、CSS、およびTSコードは別のファイルに分離されます.これは、懸念の明確な分離とWebアプリケーションを構築する古典的な方法に似ています.これは利点があります-しかし、私は私がどのように反応するかを好むと思います.
したら、基本をマスターし、最終的に物事のハングアップしていると思うように起動すると、ダニングKruger曲線上の最初の丘を通過し、絶望の谷に“マウント愚か”のピークから落ちる.

物事はすぐに複雑になる


あなたは、角度が反応(ルータ、アニメーション、RXJS)よりその芯に焼かれて、それが完全な温泉開発ツールボックスであるということを最終的に理解します.これが人々がフレームワークと呼ぶ理由です.を返します.
...
私の角度学習旅行の現在のポイントは、おそらくD - Kカーブの底のどこかにあります.そして、私はちょうど啓蒙の丘の上に巨大な玉石をロールバックし始めたように感じます.汝の明るい面は、ゆっくりと近づいて、頂上に近づいていくことだ.

良いもの-スライダーでNavbarを構築する方法。。


...そして、そのプロセス中にあなたの健全性を維持する.
先週、私は現在(私の会社のクライアント)に取り組んでいるプロジェクトのコンポーネント/機能の下にダイナミックなスライダを持つNavbarを実装しました.
それで、このブログのポストの目的のために、私は孤立してこの構成要素を再作成しました.途中でおもしろい問題に出くわした.その問題を解決するいくつかの創造的思考が必要です.
完成したコンポーネントがどのように見えるかは、ここにあります.

Navbarコンポーネントには、4ナビゲーション項目があります.項目のいずれかをクリックすると、ユーザーは定義済みルートにリダイレクトされる
主な目標は現在アクティブな経路を示すことでした、そして、その結果、ユーザー(したがって、スライダー)に現在アクティブなNavbarアイテム.
もう1つの要件は、スライダがスムーズに1つのアイテムから他のものに移行する必要があった.
スライダは追加のリスト要素として実装され、いくつかの基本的なスタイルを付けます.
  <!-- navbar.component.html -->

  <ul class="header-menu">
    <li #navElements *ngFor="let item of navItemsList">
      <a 
        routerLink="/{{item.route}}" 
        (click)="calcNewIndicatorDOMStyles()"
      >
        {{ item.name }}
      </a>
    </li>
    <li 
      class="slider" 
      [style.width.px]="activeItemWidth" 
      [style.left.px]="activeItemLeftMargin">
    </li>
  </ul>
  // navbar.component.css

  .slider {
    position: absolute;
    bottom: -5px;
    margin-left: 2.2em;
    border-bottom: 2px solid white;
    transition: 0.3s;
    width: 50px;
  }
あなたは実行中のアプリhereを見つけることができます
追加の要件は、スライダの幅が動的に変更し、その上のNAVの項目の幅に一致する必要があります.
NAV項目幅の変更は2つのシナリオで起こります.

  • 画面のサイズ変更.ユーザーは自分のデバイスをピボットできます.

  • テキスト翻訳の変更.コンポーネントの下にある/enボタンでシミュレート.
  • 以下のテンプレートファイルコードを見ると、インラインスタイルを使用してスライダの左マージンと幅を動的に設定できます.
      <!-- navbar.component.html -->
    
      <li 
        class="slider" 
        [style.width.px]="activeItemWidth"    <======
        [style.left.px]="activeItemLeftMargin">    <======
      </li>
    
    このメソッドでActiveSiteWidthとActiveItemleftマージンが計算されます.
      // navbar.component.ts
    
        calcNewIndicatorDOMStyles() {
          this.activeItemWidth = this.router.isActive(routes.name, 
          false)
            ? this.navItemDOMProps?.[0].width
            : this.router.isActive(routes.posts, false)
            ? this.navItemDOMProps?.[1].width
            : this.router.isActive(routes.random, false)
            ? this.navItemDOMProps?.[2].width
            : this.router.isActive(routes.speed, false)
            ? this.navItemDOMProps?.[3].width
            : 0;
    
          this.activeItemLeftMargin = 
          this.router.isActive(routes.name, false)
            ? 0
            : this.router.isActive(routes.posts, false)
            ? this.navItemDOMProps?.[0].width + 30
            : this.router.isActive(routes.random, false)
            ? this.navItemDOMProps?.[0].width + 
              this.navItemDOMProps?.[1].width + 60
            : this.router.isActive(routes.speed, false)
            ? this.navItemDOMProps?.[0].width + 
              this.navItemDOMProps?.[1].width + 
              this.navItemDOMProps?.[2].width + 90
            : 0;
        }
    
    このメソッドは、NAV項目がクリックされたときにユーザーによってトリガされます.次に、新しいスライダの位置(マージン左)と幅を再計算する必要がありますので、スライダを新しいアクティブなアイテムの下に移行することができます.
    それで、トリッキーな部分は、「再利用されて、新しいプロパティが計算されるテンプレートの後に)、「最も新鮮な」DOMスタイルを得る方法を考え出していました.より具体的には、最新のNAV要素offsetWidth値(最後のRender)を必要とし、CalcHewinDicatorModStyles ()メソッドで使用してスライダ幅と左マージンを計算できます.
    最初のステップは、ビューのDOMからターゲットリスト要素を取得しました.ViewChildrenデコレータを使用しました.
      // navbar.component.ts
    
        @ViewChildren('navElements') navElements: 
         QueryList<ElementRef>;
    
    このメソッドは新しいoffsetWidthを抽出します:
      // navbar.component.ts
    
      private getNewNavItemDOMWidths(navElementsList: any) {
        this.navItemDOMProps = navElementsList.map(item => ({
          width: item.nativeElement.offsetWidth
        }));
      }
    
    最後に、私は見出しに「健全さ」という言葉を使った理由に到達しました.
    これは、把握する最も難しい部分でした.
    私はどのLifeCycleメソッドを使用することができます私は、最新の、計算されたDOMスタイルのプロパティを取得するために使用できますか?
    最も有望な候補はngafterviewinit ()とngafterviewchecked ()であった.他のすべてのメソッドはあまりにも早くcompライフサイクルで発火しました.
    しかし、驚いたことに、それらの2つのメソッドのどちらかからgetNewNaviteModWidgets ()メソッドを呼び出すことはうまくいきませんでした.私はまだ古い値を取得していました.
    したがって、
      ngAfterViewInit() { 
        this.getNewNavItemDOMWidths(this.navElements.toArray());
        this.calcNewIndicatorDOMStyles();
      }
    
    または、
      ngAfterViewChecked() { 
        this.getNewNavItemDOMWidths(this.navElements.toArray());
        this.calcNewIndicatorDOMStyles();
      }
    
    それ自体ではうまくいかなかった.
    例.
    現在の選択された言語がenであると言いましょう、そして、4 navアイテムは幅10、20、30、40(私は、イラストの目的のためにここで乱数を使用しています)を持ちました.
    それから、私が言語をDEに変えるならば、これは実際のDOM幅が50、60、70、80に変わる原因になります-テキスト長が異なるので.
    これをngafterviewinit ()とngafterviewchecked () lifecyleメソッドでログをコンソールしようとすると、10 , 20 , 30 , 40 (前のレンダリングの値)を取得します
    どうやってこの問題を解決できたか.
    次のような質問をしました.
    テンプレートビューの再レンダリング後、新しいDOMスタイルプロパティが計算された後、NgReadViewCheckedのライフサイクルメソッドが再び呼び出されますか?
    そうでなければ、なぜ?どうしたらそれを実行することができますか?
    私の調査では、新しいDOMスタイルのプロパティが計算され、利用可能であるときに、角度がこのメソッドをデフォルトで実行しないという結論に達しました.それはどうにか、新しいスタイルが利用可能になるとき、このメソッドを再実行するのを意識するか、強制される必要があります.
    そこで、次のように解決しました.
      ngAfterViewChecked() { 
        this.getNewNavItemDOMWidths(this.navElements.toArray());
        this.calcNewIndicatorDOMStyles();
    
        setTimeout(() => {}, 0);
      }
    
    SetTimeoutブラウザAPIへの呼び出しは、このメソッドの中で角度を強制します.settimeoutの中のコールバックfnは、既にチェックされた後にビューに影響を与える可能性があるコードを含むことができます!
    そして、おそらくあなたはおそらく、これは2番目の場所に気づいた.CalcHewinDicatorDortyStyle ()をコールしますが、既に述べたLifeCycleメソッドの内部にあります.
    この解決法について興味深いのは、「ウィンドウ」がリサイズされた場合もカバーすることです.ビューポートを変更すると、このライフサイクルメソッドがトリガーされ、新しいDOMスタイルが取得され、スライダーの更新に使用されます.
    そして、それは多かれ少なかれ.
    全体のソースコードhereを見つけることができます

    -この旅の終わり


    最後まで読んでくれてありがとう.
    私はあなたが角度について何か新しいことを学んだことを願っています.または、私が提供するコードは、将来のプロジェクトに役立つでしょう.
    これを話すと、私はこの全体のポストを読んで角の専門家の質問があります.
    私の実装についてどう思いますか?それは素晴らしいですか、それは明白な反パターンですか?何かもっと良いことがありますか?THX