先端八股文のVue


1.Vueの応答式原理
データ駆動ビュー、UI=render(state)、state状態が変化し、vueはテンプレートコンパイル、仮想DOM、patchプロセスを経てビューを更新します.vue2.xはobjectを使用します.definePropertyはdataのすべての属性で再確認し、ページが対応する属性を使用する場合、まずデータ収集を行い、属性の変化であれば関連する依存性に更新操作を通知します.vue3.x objectをproxyに置き換える.Proxyはオブジェクトと配列の変化を直接傍受できるため、defineproperty.
1.Vueの双方向バインド
双方向バインディングは、パブリケーション-サブスクライバモードとデータハイジャックを組み合わせて実現され、getは収集依存であり、setはデータ変化更新操作を行い、リスナーobserverを実現し、すべての属性をハイジャックして傍受するために使用され、変動があればサブスクライバに通知し、サブスクライバwatcherを実現し、属性の変化を受信して応答を実行する関数を実現し、ビューを更新することができる.各ノードを解析する関連命令をスキャンし、初期化テンプレートデータに基づいて応答のサブスクライバを初期化できる解析器compileを実現する
1.VueのneextTick原理
次のDOM更新サイクル後に遅延コールバックを実行し、nextTickは主にマクロタスクとマイクロタスクを使用し、実行環境に応じてpromise、mutationObserver、setImmediateを使用して非同期メソッドを定義しようとします.nextTickを複数回呼び出すと、メソッドがタスクキューに格納され、非同期メソッドで現在のキューが空になります.
4.Vueコンポーネントのライフサイクル
コンポーネントの作成、データの初期化、マウント、更新、レンダリング、更新、破棄のプロセスをライフサイクルと呼びます.
1.作成前後:
  • beforeCreate:Vueインスタンスのdataおよびマウント要素elは定義されておらず、初期化されていません.
  • createdフェーズ:Vueインスタンスのデータオブジェクトdataがあり、elはundefinedであり、インスタンスの作成が完了し、マウントが完了していない
  • 2.ロード前後:
  • beforeMount:Vueインスタンスのelとdataが初期化され、まだマウントされていません.このときDOMは仮想DOMです.必要なテンプレート構造をページに置き換えます.
  • mounted:Vueインスタンスのマウントが完了し、ビューのレンダリングに成功し、ページのレンダリングが完了しました.

  • 3.廃棄前後:
  • beforeDestory:コンポーネントが破棄されます.まだ破棄されていません.
  • destoryed:Vueインスタンスが破棄すると呼び出され、コンポーネントが使用できなくなり、イベントリスニングおよびDOMのバインド
  • が解除されました.
    4.更新前後:
  • beforeUpdate:dataが変化すると、データが更新されると呼び出され、再レンダリングされたテンプレート構造をページに配置します.
  • updated:ページ更新完了、データ更新新データ
  • Vue親子コンポーネントのライフサイクル呼び出し順序
    コンポーネントの呼び出し順序はすべて親の子で、レンダリングが完了したときに子の子と親の子が破棄されたときに親の子が破棄され、破棄が完了したのは子の子の子の子です.
  • 読み込みレンダリング完了:親createCreate–親created–親breateMount–子beforeCreate–子created–子breateMount–子mounted-親mounted
  • サブコンポーネント更新プロセス:親breateUpdate-サブbeforeUpdate-サブupdated-親updated
  • 親コンポーネント更新プロセス:親beforeUpdate-親updated
  • 破棄プロセス:親beforeDestory-子beforeDestory-子destoryed-親destoryed
  • computedとwatchの違い
  • computedはキャッシュ機能を有し、依存するデータが変化してこそcomputed
  • をトリガする.
  • watcherはキャッシュ機能がなく、データを傍受してコールバックを実行することができ、深く傍受するとオブジェクトの属性を開くことができ、deep-trueオプションを開くことができ、watcherは非同期をサポートし、2つのパラメータ、newData、oldData、=、2つの属性、deep:オブジェクトを1層も遍歴していないことを深く観察し、immediate:コンポーネントロードはすぐにコールバック関数
  • を実行する
    コンポーネントdataはなぜ関数なのか
    1つのコンポーネントが複数回多重化されると、複数のインスタンスが作成され、本質的には同じコンストラクション関数が使用され、dataがオブジェクトである場合、オブジェクトは参照タイプに属し、すべてのインスタンスに影響します.
    コンポーネント間の通信方法
    1.親子コンポーネント通信-親コンポーネントはpropsを通じてサブコンポーネントに値を伝達-サブコンポーネントはemitを通じて、onは親コンポーネントに値を伝達する
  • 親子コンポーネント親子コンポーネントインスタンスp a r e n t,parent,parent,children
  • を取得する
  • refインスタンスを取得する方法呼び出しコンポーネントの属性および方法
  • 2.兄弟コンポーネント通信
  • event busインスタンスコンポーネント間通信
  • -Vue.prototype.$bus = new Vue()
  • vuex

  • 3.コンポーネント間通信
  • vuex
  • a t t r s , attrs, attrs,listeners

  • diffアルゴリズムイベント複雑度
    1.静的ノードであるか否かを判断する
  • 静的ノードは、
  • を処理する必要がない.
    2.VNodeがテキストノードかどうか
  • oldVNodeはテキストフェーズではなく、setTextNodeを直接使用してテキストノードに設定し、コンテンツを過去
  • にコピーします.
  • oldVNodeはテキストノードであり、2つの新旧ノードが等しいかどうかを比較し、古いノードの内容が新しいノードの内容
  • に等しくなるようにする.
    3.VNodeは要素ノード
  • VNodeはサブノードもテキストノードも含まず、そのまま旧ノードの内容をクリアすれば
  • である.
  • VNodeはサブノードを含む
  • 古いノードにはサブノードが含まれていないので,新しいノードの内容を古いノードに挿入する
  • を作成する.
  • 古いノードにサブノードが含まれていることを放送するには、比較更新サブノード
  • を再帰的に巡回する必要がある.
  • 古いノードがテキストノードである場合、テキストを空にし、新しいノードの内容を古いノードに挿入する
  • を作成する.

    通常比較DOM-DiffはO(n^3)であり,Vue 2のdiffアルゴリズムは両端比較最適化アルゴリズムと新旧childrenが複数のサブノードである場合のみ黒サイのDiffアルゴリズムで同階層比較を行う必要がある時間複雑度がO(n)である.
    vueのkeep-aliveは何の役に立つの?
    頻繁に変動しないコンポーネントやキャッシュが必要なコンポーネントを包むことで、直接破棄するのではなく、コンポーネントをメモリに保存できます.
  • の利点:コンポーネントの状態を保持するか、複数回のレンダリングを回避し、ページのパフォーマンスを向上させる
  • には、淘汰ポリシーLRUがあります.
  • 新しいデータを配列末尾
  • に配置する
  • キャッシュヒット毎に、キャッシュヒットデータを配列末尾
  • に配置する.
  • keysがいっぱいになったら、ヘッダのデータを
  • 破棄します.
  • ライフサイクルフック:activated:キャッシュコンポーネントがアクティブになったとき、deactivated:キャッシュコンポーネントが破棄されたとき
  • Vueにおけるhistoryとhash実現の原理
    https://juejin.cn/post/6844903589123457031

  • hashモードでは、#の後ろの部分だけを変更すると、ブラウザは対応する場所にスクロールし、Webページは再ロードされません.hashchange()関数
  • をトリガーします
    class Routers {
         
        constructor() {
         
          //   hash callback   
          this.routes = {
         };
          //   hash
          this.currentUrl = '';
          //       hash
          this.history = [];
          //     ,    this.history   ,        history    hash
          this.currentIndex = this.history.length - 1;
          this.refresh = this.refresh.bind(this);
          this.backOff = this.backOff.bind(this);
          //         
          this.isBack = false;
          window.addEventListener('load', this.refresh, false);
          window.addEventListener('hashchange', this.refresh, false);
        }
      
        route(path, callback) {
         
          this.routes[path] = callback || function() {
         };
        }
      
        refresh() {
         
          this.currentUrl = location.hash.slice(1) || '/';
          if (!this.isBack) {
         
            //         ,            ,               
            //                ,       ,        ,      hash  
            //             ,             
            //                       
            if (this.currentIndex < this.history.length - 1) {
          
               this.history = this.history.slice(0, this.currentIndex + 1);
            }
            this.history.push(this.currentUrl);
            this.currentIndex++;
          }
          this.routes[this.currentUrl]();
          console.log('  :', this.currentIndex, 'history:', this.history);
          this.isBack = false;
        }
        //     
        backOff() {
         
          //        true
          this.isBack = true;
          this.currentIndex <= 0
            ? (this.currentIndex = 0)
            : (this.currentIndex = this.currentIndex - 1);
          location.hash = `#${
           this.history[this.currentIndex]}`;
          this.routes[this.history[this.currentIndex]]();
        }
      }
    
  • ルーティングのhashおよび対応するcallback関数を
  • 記憶する.
  • ルーティングのhash変化をトリガすると、対応するcallback関数
  • が実行される.
  • 対応するイベントをリスニングし、classをインスタンス化するときに上のイベントをリスニングするだけで
  • になります.
    historyモード:
  • は、記録局に適用されるpushState()メソッドとreplaceState()メソッドを呼び出します.一般的な方法:
  • window.history.back()後退
  • window.history.forward()前進
  • window.history.go(-3)3ページ後退
  • history.PushStateは、ブラウズ履歴に履歴を追加するために使用されますが、ジャンプはトリガーされません.このメソッドは、3つのパラメータstate,title,url)
  • を受信します.
  • state:指定されたWebサイトに関連するステータスオブジェクトで、popStateイベントがトリガーされると、そのオブジェクトはコールバック関数
  • に転送されます.
  • title:新しいページのタイトル、
  • url:新しいWebサイトは、現在のページと同じドメイン
  • にある必要があります.
  • history.replaceStateメソッドのパラメータはpushStateメソッドと同じです.違いは、レコードを追加するのではなく、履歴の現在のレコードを変更し、ジャンプ
  • をトリガーしないことです.
  • popStateイベントは、同じドキュメントの閲覧履歴が変化するたびにpopStateイベント
  • がトリガーされます.
    class Routers {
         
        constructor() {
         
          this.routes = {
         };
          //       popstate  
          this._bindPopState();
        }
        //       replaceState
        init(path) {
         
          history.replaceState({
         path: path}, null, path);
          this.routes[path] && this.routes[path]();
        }
        //             hashMap  
        route(path, callback) {
         
          this.routes[path] = callback || function() {
         };
        }
        //          pushState
        go(path) {
         
          history.pushState({
         path: path}, null, path);
          this.routes[path] && this.routes[path]();
        }
        //   popstate  
        _bindPopState() {
         
          window.addEventListener('popstate', e => {
         
            const path = e.state && e.state.path;
            this.routes[path] && this.routes[path]();
          });
        }
      }
      
      window.Router = new Routers();
      Router.init(location.pathname); //      
      const content = document.querySelector('body');
      const ul = document.querySelector('ul');
      function changeBgColor(color) {
         
        content.style.backgroundColor = color;
      }
      
      Router.route('/', function() {
         
        changeBgColor('yellow');
      });
      Router.route('/blue', function() {
         
        changeBgColor('blue');
      });
      Router.route('/green', function() {
         
        changeBgColor('green');
      });
      
      ul.addEventListener('click', e => {
         
        if (e.target.tagName === 'A') {
         
          e.preventDefault();
          Router.go(e.target.getAttribute('href'));
        }
      });
    

    vuexの原理
    https://juejin.cn/post/6844904081119510536