3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因

青灯夜游
リリース: 2022-12-16 19:59:03
転載
3642 人が閲覧しました

今年の雇用情勢はとにかく暗いです。来年は今年よりも悪くなるだろうという「ラッキーメンタル」に基づき、迷わず退職を選択しました。1ヶ月半の努力の末、かなりの好成績をいただきました。給与とプラットフォームは大幅に改善されましたが、心理的な期待とはまだ大きなギャップがあります。したがって、最大の結論は、「裸で話してはいけない」ということです。裸で何も言わないでください!裸で何も言わないでください!面接で受けるプレッシャーや現実と理想のギャップによる精神的ダメージは計り知れないので、そのような環境で生き残るのは良い選択です。

関連おすすめ: 2023年フロントエンド面接の質問まとめ(集)

次に、経験する以下のことをまとめます。通常の状況下でのフロントエンド面接。4 つの段階と 3 つの決定要素:

3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因フロントエンド スタッフとして、テクノロジーの深さと幅広さが第一に挙げられます。3 年が分かれ目です。現時点では、自分自身の正しい方向性と方向性を見つけなければなりません。

第二に、優れたコミュニケーションと表現スキル、服装とパフォーマンス、その他のオフサイトの要素により、面接官のあなたの認識が高まります。

非常に優秀な人もいますが、面接官は面接中に不快感を抱き、あなたのことを傲慢、だらしがない、独善的、自分の意見をはっきりと表現できないと考え、不採用にしてしまいます。それは最悪の損失です。 。

以下は、私の面接準備全体と私が聞かれた質問の概要です。面接プロセス中、面接官とのコミュニケーションは、多くの場合、単純な承認ではないからです。知識 自分なりの要約や簡潔さを表現し、面接官の質問に基づいてその場で補足・改善します。 [推奨学習: Web フロントエンド プログラミング教育 ]

1. 自己紹介

面接官は、自己紹介の範囲を制限するものではありません。面接官はあなたの自己紹介からあなたのことを知りたいと思っているはずです。そのため、自己紹介は簡潔かつスムーズでなければなりません。さまざまな面接官に直面する場合、自己紹介の内容は重要です。したがって、事前に言葉を準備し、つまずかないように、自信を持って注意を払うことが重要です。 スムーズな表現力やコミュニケーション能力も面接官による候補者の評価ポイントの一つです。私も面接官をしたことがありますが、自信があり寛大な候補者は、多くの場合、有利に扱われる可能性が高くなります。

1. 自己紹介 (基本的な状況) と主な履歴書がすべて用意されており、短くなければなりません

2. 技術的および非技術的なことを含む、自分の得意なこと。技術者はあなたの移行を理解でき、技術者以外の人はあなたを人間として理解できます

#3. これまでに行ったプロジェクトの中で最も核となるプロジェクトを選択し、すべてのプロジェクトを推薦のように紹介しないでください

4. あなた自身のアイデア、興味、意見、さらにはあなた自身のキャリアプラン。これが面接官に次のような感情を与えた場合: 「投げる」または「考える」ことに熱心です

例:

面接官、こんにちは、私の名前は xxx、xx の xx 大学を卒業しました。卒業以来、フロントエンド開発関連の仕事に従事してきました。

私が得意とするテクノロジー スタックは vue ファミリー バケットであり、vue2 と vue3 の使用法とソース コードについてはある程度研究しており、パッケージ化ツールは webpack と vite に精通しており、私はこれまでに多くのことを経験してきました。中・大規模プロジェクトをゼロからイチまでプロジェクトを遂行する経験と能力。

前の会社では主にxx製品ラインの責任者として、主な業務を行っていました。 。 。 。 。 。

開発関連の仕事に加えて、要件レビュー、UI/UE インタラクション レビューの審査員、開発スケジュールの責任、メンバーのコラボレーション、メンバー コードのレビュー、組織化など、特定の技術管理の経験もあります。定例ミーティングなど

普段は自分で構築したブログに学習記事や勉強メモを記録したり、オリジナルの技術記事を書いてナゲッツに公開したりしてxx賞を受賞しました。

一般的に、自己紹介は 3 ~ 5 分以内に収めるようにしてください。まず、簡潔かつ要点を絞ったものにし、次に自分の能力や長所を強調することが重要です。

一般的な技術面接官にとって、自己紹介は面接前の習慣的な冒頭の言葉にすぎず、一般的に、履歴書に記載されている基本的な情報で、すでにあなたについての基本的な理解は満たされています。しかし、上司レベルの面接官や人事の場合は、あなたの性格、行動習慣、ストレス耐性などの総合的な能力を評価します。したがって、面接プロセス中はできるだけ前向きであること、継続的な学習が好き、チームワークが好きなど幅広い趣味を持っていること、無条件で残業できることが必要です。もちろんチートをさせるつもりはありませんが、この環境においてはこうした「サイドアビリティ」も競技力をある程度向上させる魔法の武器でもあります。

2. プロジェクト マイニング

現在の市場状況では、面接の通知を受け取った場合、それはあなたのプロジェクト経験とその経験によるものである可能性が高くなります。あなたが募集しているポジション。もっとラインに沿って。 したがって、プロジェクトの準備には次のような特別な注意を払う必要があります。

  • プロジェクトで使用されている

    テクノロジ を深く掘り下げる

  • プロジェクトの管理全体設計アイデア

  • プロジェクトの管理運用プロセス

  • チームコラボレーション能力。

  • プロジェクトの

    最適化ポイントは何ですか

詳細は人によって異なるため割愛します状況を掘り下げてみましょう。

3. 個人的なこと

まず個人的なことについて話させてください。技術面接に合格し、上司や人事の段階に到達したとき、たとえ現在の能力がどれほど素晴らしくても、あなたの個人的な可能性、学習能力、性格、チーム統合、その他のソフト スキルを調べることに加えて、よく聞かれるいくつかの質問を以下に示します。

なぜ転職したのですか。 ?

個人開発から直接始めて、野心を示す:

  • 私は、技術的な雰囲気が優れているだけでなく、より大きなプラットフォームに行きたいと常々思っていました。 、しかしまた、より多くのことを学びました

  • 知識を広げたいです。以前は、いつも x 側で xx 製品を作っていました。技術スタックは比較的単純だったので、xx を勉強しました。
  • 私は前職ではコンフォートゾーンに陥ってしまい、それしかできませんでした。プラットフォームを変更して技術の幅を広げ、新しい技術システムに触れて学びたいと考えています。

あなたと通常のフロントエンドについて教えてください。あなたのハイライトは何ですか?

1. 計画と要約が得意です。担当するプロジェクトを総合的に分析します。1 つはマインドマップを使用して各モジュールの業務を分解する業務分解、もう 1 つはそれを実行することです。コードモジュールを分解し、各コードモジュールを機能に応じて区別することです。再び開発に行きます。これは、やみくもにビジネス開発を行う多くのフロントエンドではできないことだと思います。

2. 私はテクノロジーを専門とするのが好きで、普段は vue のソース コードを学習し続けており、自分の開発したコードもアウトプットしています。以前に書いたような独自の技術記事

teleport のソース コード を 1 行ずつ集中的に読み、書くのに約 30 時間かかりました。ソース コードの各行の機能と役割が説明されています (しかし、なぜ閲覧数といいね数がこんなに低いのでしょう)。

あなたの欠点は何ですか?

私は比較的真面目な気質で内向的なほうなので、自分ももっと外向的になるように努力します。

1つは様々な検討会を開催することですが、フロントエンドの代表として様々な資料を用意したり、スピーチをしたりする必要があります。

そのため、チーム内で技術的な共有を強化し、毎週定期的にミーティングを主催しています。これにより、表現したり話し合ったりする勇気も得られます。

最近何か新しいテクノロジーに注目しましたか?

    #パッケージ依存関係管理ツール pnpm (依存関係の繰り返しインストールなし、非フラットなノードモジュール構造、シンボリック リンクを介した依存パッケージの追加)
  • ##パッケージ化ツール vite (非常に高速な開発環境)
  • flutter (クロスプラットフォーム、高忠実度、高パフォーマンスに重点を置いた、Google のオープンソース モバイル アプリケーション (アプリ) 開発フレームワーク)
  • rust (js の将来のベースになると聞きました)
  • webpack の後継であるturbopack は、webpack の 10 倍高速であると言われています。 vite、webpack は 700 倍高速であり、You Yuxi は vite の 10 倍ではないことを個人的に検証しました
  • webcomponents
Youさまざまな方向に探索するべきですか、それとも特定の方向に研究を続けるべきですか?

私の個人的な計画は次のとおりです。

3 ~ 5 年で技術的な深みを向上させると同時に、知識の幅、つまり深さと幅を広げていきます。改善するには、主に幅広い点が重要です。主要なフロントエンドを完全に理解した場合にのみ、より良い選択ができるようになります

5 ~ 7 年は、選択する前に蓄積する十分な知識が得られる時期です特定の興味の方向性。さらに勉強して、その分野の専門家になるよう努力してください。

チームの規模、チームの仕様、開発プロセス

これは人によって異なります。規模が異なると、チームの研究開発モデルも大きく異なるため、正直に準備してください。

コードレビューの目標

1. 最も重要なことはコードの保守性です (変数の名前付け、コメント、関数の統一原則など)

2. 拡張性: カプセル化機能 (コンポーネントとコード ロジックが再利用可能かどうか、スケーラビリティ)

3. ES の新機能 (es6、ES2020、ES2021 のオプション チェーン、at)

4 . 関数の使用仕様 (たとえば、マップを forEach として使用する場合)

5. パフォーマンスの向上、アルゴリズムを使用してよりエレガントでパフォーマンスの高いコードを記述する方法

How to lead a codeチーム

私は前の会社で技術管理の役割を担っていました。

0,

開発仕様の実装

, 名前付け、ベスト プラクティスからさまざまなツール ライブラリの使用方法まで、社内 Wiki に投稿しました。新しい人が入ってきた初期の段階では、彼らのコードの品質を優先的にフォローします。1.

チーム分業

: 各人が製品の開発に責任を負いますその後、通常は公開モジュールを開発するために数人を指名します

2、コード品質保証: コードは毎週レビューされ、クロスレビューされたコードが整理され、修正結果の出力記事が wiki

# に配置されます。 ##3,

定期的な組織会議 : 定期的な組織会議を毎週開催し、それぞれの進捗状況とリスクを同期し、それぞれの進捗状況に応じて作業タスクを割り当てます

4,

テクノロジー共有: 不定期で技術共有も開催します。当初は、マイクロ フロントエンド システム、ice stark のソース コード

5、

パブリック デマンド プール : webpack5/vite のアップグレードなどを共有するのは私だけでした。 vue2.7 セットアップ構文シュガーのアップグレードの導入、pnpm の使用、トポロジ マップのパフォーマンスの最適化

6、

最適化プロジェクト: 製品の最初のバージョンがリリースされた後、私も最初の画面の読み込みパフォーマンスを向上させるために、特別なパフォーマンス最適化プロジェクトを開始しました。パッケージング量の最適化。対応する最適化項目を全員が責任を負います

残業についてどう思いますか?

残業には一般的に次の 2 つの状況があると思います。

まず、プロジェクトの進捗が逼迫しているため、もちろんプロジェクトの進捗が第一です。結局のところ、全員がこれに依存しています。

2 番目の問題は、私自身の能力です。ビジネスに慣れていない場合、または新しいテクノロジー スタックを導入していない場合は、追いつくために残業するだけでなく、自分の能力を最大限に活用する必要があると思います。一生懸命勉強して自分の欠点を補うための自由時間

#あなたの興味や趣味は何ですか?

私は通常、読書が好きです。つまり、心理学、時間管理、WeChat でのスピーチスキルに関する本を何冊か読みます。

それから記事を書きます。他の人のコンテンツを記録し、自分のオリジナルの記事を書くだけなので、単にメモを取ることを忘れがちです。このプロセスでは、非常に高い割合の知識が自分のものに変換されるため、自分の金鉱の記事に加えて, また、プロジェクトの成果物に関する記事を wiki に出力することもよくあります

私の他の趣味は、友達とバスケットボールをしたり歌うことです

4. テクノロジー

Be技術面接には必ず注意してください:

簡潔かつ要点を絞って、適切に詳しく説明し、理解できない場合は、理解できないと言ってください

。面接は面接官との対面でのコミュニケーションであるため、要点を話さずに長時間おしゃべりするような候補者は面接官からは好まれません。興味のない部分は無視するので、特定のテクノロジーのコア機能を強調し、そのコアを中心に適切に拡張する必要があります。 大手企業は基本的にアルゴリズムの質問で候補者を選考します。アルゴリズムに近道はありません。段階的に質問に答えて、また質問に答えるしかありません。この点が苦手な方は、事前に計画を立てて勉強してください。 。

技術面接プロセスでは、主にフロントエンド分野に関連するテクノロジーに関する質問が行われます。通常、面接官は貴社の事業所に基づいて質問されますが、多くの場合、面接官は面接での質問に基づいて質問されます。比較的よく知っている技術的な内容を質問するのは、未知のことばかりなので、あらゆる面でかなり厳しいものです。

もしあなたが発展性の高い中~大企業に入りたいのであれば、他人の経験を丸暗記するだけで自分を騙すことはできません。ここでの各要約は非常に短いものですが、これらはすべて私がいくつかを洗練させたものです。各知識を総合的に学習した上で核となる知識を学ぶので、面接官の「思考の発散」を恐れません。

面接プロセスでは、通常、次の 8 つの主要な種類の知識が考慮されます:

JS/CSS/TypeScript/フレームワーク (Vue、React)/ブラウザとネットワーク/パフォーマンスの最適化/フロントエンジニアリング/アーキテクチャ/その他

3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因#したがって、面接前の技術的な準備は決して一朝一夕にできるものではなく、日々の積み重ねが必要です。 1日20分で小さな知識の一つを勉強し、総合的に勉強すれば、長い目で見れば、何年面接しても、雄弁に話せるようになります。

JS の章

JS 学習スタッド赤封筒本と Yu Yu 氏の

In- Depth JS シリーズ ブログ

は基本的にOKです 一般的な JS 面接の質問には、一般に次のようなものがあります。

3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因

プロトタイプ/プロトタイプ チェーンとは何ですか?

プロトタイプの本質は

オブジェクト

です。 コンストラクターを作成すると、この関数にはデフォルトで

prototype

属性が設定され、この属性の値はこの関数のプロトタイプ オブジェクトを指します。 このプロトタイプ オブジェクトは、コンストラクターを通じて作成されたインスタンス オブジェクトに共有プロパティを提供するために使用されます。つまり、

は、プロトタイプ ベースの継承とプロパティ共有を実装するために使用されます

したがって、コンストラクター関数

を通じて作成するインスタンス オブジェクト

は、この関数のプロトタイプ オブジェクトから上記の属性を継承します

インスタンスの属性を読み取るときに、インスタンスが見つからない場合は、そのオブジェクトに関連付けられたプロトタイプ内の属性を探します。見つからない場合は、プロトタイプのプロトタイプが見つかるまで探します。トップレベル (トップレベルは Object.prototype のプロトタイプ、値は null)。

つまり、プロトタイプを介して層ごとに相互接続されたチェーン構造は、プロトタイプチェーンと呼ばれます。

クロージャとは何ですか?

定義: クロージャは、他の関数のスコープ内の変数を参照する関数 を指し、通常はネストされた関数で実装されます。

技術的には、すべての js 関数はクロージャです。

実際的な観点から、次の 2 つの条件を満たす関数はクロージャとみなされます。

  • クロージャは、それを作成したコンテキストが破棄されても存在します。 (例:親関数から戻る)

  • #コード内で自由変数が参照されている(関数パラメータでも関数ローカル変数でもない関数内で使用される変数を自由変数と呼びます)
使用シナリオ:

    プライベート変数の作成
  • vue 内のデータはクロージャである必要がありますパッケージを使用して、各データ内のデータが一意であることを確認し、コンポーネントへの複数の参照によって引き起こされるデータ共有を回避します

    #変数のライフ サイクルを延長します
  • ##の字句環境一般的な関数が関数内にある リターン後に破棄されるが、クロージャは作成されたレキシカル環境への参照を保存する 作成された実行コンテキストが破棄されても、作成されたレキシカル環境はまだ存在する
  • アプリケーション

カリー関数

例、カウンター、遅延呼び出し、コールバック関数など。
  • これを指す

ほとんどの場合、関数の呼び出し方法によって # の値が決まります。 ##this (実行時バインディング)

1. 非厳密モードのグローバル this は window オブジェクトを指し、厳密モードは undefined

2 を指します。オブジェクトのプロパティ メソッドはオブジェクト自体を指します

3. apply、call、bind 最初に渡されたパラメータを指すようにこれを変更できます

4. アロー関数内のこれは、その親スコープを指します、それ自体は存在しませんこれ

#ブラウザのイベントループ?

js コードの実行中に、対応する実行コンテキストが作成され、実行コンテキスト スタックにプッシュされます。

非同期タスクが発生した場合、タスクは一時停止され、他のスレッドに引き渡されて非同期タスクを処理します。非同期タスクが処理されると、コールバック結果がイベント キューに追加されます。 実行スタック内のすべてのタスクが実行されると、つまりメインスレッドがアイドル状態になると、最初のイベント コールバック結果がイベント キューから取得され、このコールバックが実行スタックに追加されます。コードが実行されるなど、このプロセスはイベント ループと呼ばれます。

イベント キューは

マクロ タスク キュー

とマイクロ タスク キューに分かれています。現在の実行スタックが空の場合、メインスレッドはまずマイクロ タスク キューにイベントがあるかどうかを確認します。 . イベントがあればマイクロタスクキューを順番に実行し、マイクロタスクキューが空になるまでタスクキュー内のイベントをコールバックし、存在しない場合はマクロタスクキューで処理します。

一般的なマクロ タスクには、

setTimeout()

setInterval()

setImmediate()、I/O 、ユーザー インタラクション、UI レンダリング一般的なマイクロタスクには、promise.then(),

promise.catch()

,new MutationObserver# が含まれます##、process.nextTick()マクロ タスクとマイクロ タスクの本質的な違い

マクロ タスクには次のような特徴があります。実行とコールバックが必要な非同期タスクをクリアし、他の非同期スレッドからのサポートが必要です。

マイクロ タスクには、実行が必要な明確な非同期タスクはなく、コールバックのみがあり、必要はありません。他の非同期スレッドからのサポート。
  • JavaScript でデータがスタックとヒープに保存される方法
  • 1. 基本的なデータ型はサイズが固定されており、操作が簡単です, そのため、スタックに配置されます Storage
2. 参照データ型のサイズは不確実なので、ヒープ メモリに配置し、メモリ適用時にサイズを自分で決定させます

3. この方法でストレージを分離すると、メモリの占有量を最小限に抑えることができます。スタックの効率はヒープの効率よりも高くなります

4. スタック メモリ内の変数は実行環境終了直後にガベージ コレクションされますが、ヒープ メモリ内の変数への参照はすべて完了する必要があります。リサイクルされる前に

v8 ガベージ コレクションについて話す

1. オブジェクトの生存時間に応じてメモリ ガベージ コレクションを異なる世代に実行し、次を使用します。世代ごとに異なるリサイクル アルゴリズム

2. 新しい世代では、空間対時間のスカベンジ アルゴリズムが使用されます: 空間全体が 2 つのブロックに分割され、変数はそのうちの 1 つのブロックにのみ存在します。変数はスペースの別のブロックにコピーされ、残っていない変数はリサイクルされ、操作が何度も繰り返されます

3. 古い世代では、マークのクリアとマークの並べ替えが使用されます。マークのクリア: すべてを走査します。オブジェクトを使用して、アクセスできる (生きている) オブジェクトをマークし、非アクティブなオブジェクトをガベージとしてリサイクルします。リサイクル後、メモリの不連続を避けるために、マーキングとソートを通じてライブオブジェクトをメモリの一端に移動し、移動が完了した後に境界メモリをクリーンアップする必要があります

関数呼び出しメソッド

1. 通常の function() を使用して直接呼び出され、次のようなパラメータを渡します: function test(x, y) { return x y}test(3, 4)

2. のように、オブジェクトの属性メソッドとして呼び出されます。 const obj = { test: function (val) { return val } }, obj.test(2)

3. call または ## を使用します。 #apply呼び出し、関数のこの点を変更します。つまり、関数の実行コンテキストを変更します。

4,

newコンストラクターを間接的に呼び出してオブジェクトを生成できます。 instance

defer と async

の違い 通常の状況では、script タグが実行されると、ダウンロードと 2 段階の操作が実行されます。 HTML の解析をブロックします;

async と defer can スクリプトの

download フェーズ は非同期実行になります (HTML 解析と同期);

Async は、ダウンロードが完了すると、HTML 解析がブロックされます。

defer は、すべての HTML 解析が完了し、DOMContentLoaded イベントの前に実行されるまで待機します。

ブラウザ イベント メカニズム

DOM イベント フローの 3 つの段階:

  • キャプチャ ステージ: イベントより具体性の低いノードが最初にイベントを受信し、最も具体的なノード (トリガー ノード) が最後にイベントを受信します。イベントが最終目的地に到着する前に阻止すること。

    たとえば、div をクリックすると、クリック イベントが次の順序でトリガーされます: document =>

    =>

    =&gt ;
    、つまり、ドキュメントによってキャプチャされ、DOM ツリーに沿って下方向に伝播され、 になるまで各ノードでキャプチャ イベント がトリガーされます。実際のターゲット要素に到達します。
  • ターゲット フェーズ

    イベントがターゲット ノードに到達すると、イベントはターゲット ステージに入ります。

    イベントはターゲット ノード でトリガーされ (イベントに対応する関数を実行します)、最も外側のドキュメント ノードに伝播されるまで逆に流れます。

  • バブリング フェーズ

    イベントがターゲット要素でトリガーされた後、DOM ツリーに沿ってレイヤーごとにバブルが発生し続けます。最も外側のルート ノードに到達します。

  • すべてのイベントはキャプチャ フェーズとターゲット フェーズを通過する必要がありますが、一部のイベントはバブリング フェーズをスキップします。たとえば、要素がフォーカスを取得したり、バブリングしないフォーカス ブラーを失ったりする場合があります

    拡張子 1#e.target と e.currentTarget の違いは何ですか?

      e.target
    • イベント リスニングをトリガーするオブジェクトを指します。
    • e.currentTarget
    • リスニング イベントが追加されるオブジェクトを指します。
    • 例:
    <ul>
      <li><span>hello 1</span></li>
    </ul>
    
    let ul = document.querySelectorAll(&#39;ul&#39;)[0]
    let aLi = document.querySelectorAll(&#39;li&#39;)
    ul.addEventListener(&#39;click&#39;,function(e){
      let oLi1 = e.target  
      let oLi2 = e.currentTarget
      console.log(oLi1)   //  被点击的li
      console.log(oLi2)   // ul
      console.og(oLi1===oLi2)  // false
    })
    ログイン後にコピー

    イベントは ul にバインドされています。li をクリックすると、ターゲットはクリックされた li になり、currentTarget はバインドされたイベントの ul になります

    イベントのバブリング段階 (上記の例) では、

    e.currenttarget

    e.target は等しくありませんが、イベントのターゲット段階では、 e.currenttargete.target は等しい 関数:

    e.target

    を使用して # を実装できます## イベント委任 、原則は、イベント バブリング (またはイベント キャプチャ) を通じて親要素をリッスンするイベントを追加することであり、e.target はトリガー イベントをトリガーする要素を指します 拡張子 2

    addEventListener パラメータ

    構文:

    addEventListener(type, listener);
    addEventListener(type, listener, options || useCapture);
    ログイン後にコピー

    type: リスニング イベントのタイプ (例: 'click'/'scroll) '/'focus'
    • listener:
    • EventListener

      インターフェイスまたは function を実装するオブジェクトである必要があります。監視対象のイベント タイプがトリガーされると、それが実行されます。

      options: リスナーに関連するオプションのパラメーター オブジェクトを指定します。
    • capture: ブール値。イベント キャプチャ フェーズが EventTarget に伝播されるときにリスナーがトリガーされるかどうか

        once: リスナーが追加後に最大 1 回呼び出せることを示すブール値。true の場合、リスナーは実行後に削除されます。
      • passive: ブール値、リスナーが
      • preventDefault()
      • signal: オプション、AbortSignal
      • を呼び出さないことを示します。 ##abort()
      • メソッドが呼び出され、リスナーが削除されます。
      • useCapture: ブール値、デフォルトは false、リスナーは最後に実行されます。イベント バブリング フェーズ。true は、キャプチャ フェーズの開始時に実行されることを意味します。この機能は、イベントのタイミングを変更して傍受/非傍受を容易にすることです。

    Vue の章

    著者は主に Vue 関連の開発に従事しており、反応関連のプロジェクトも行っています。プロジェクトを実行することです。履歴書に記載されているようなものです。フレームワークの価値はそれほど多くはありませんが、その本質にあります。Vue のソース コード シリーズを学ぶことで、Vue に非常に自信が持てるようになります。学習プロセスも同様で、あるフレームワークの原則をマスターできれば、他のフレームワークを学習するのは時間の問題です。

    3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因

    vue と React の違い

    1. データの変動性

    • React は関数型スタイルを支持しますプログラミング、不変データと一方向のデータ フロー、ビューの更新は setState または onchange
    • Vue によってのみ実現できます。Vue はデータの変動性に基づいて応答性の高いデータを設計し、自動的に更新します。データの変化を監視するビュー

    2. 記述方法

    • Reactでは、jsxインラインスタイルを使用することを推奨していますが、これはすべてjs
    • Vue内にあります。単一ファイル コンポーネント (SFC) の形式で、コンポーネント内でモジュール (tmplate/script/style) に分割されます。もちろん、vue は jsx 形式もサポートしており、vue の ui コンポーネント ライブラリを開発するときに使用できます。

    3 、 diff アルゴリズム

    • Vue2 は両端比較を使用し、Vue3 は高速比較を使用します
    • react主に diff キューを使用して DOM が必要とするものを保存します更新する場合はパッチツリーを取得し、DOMを一括更新する統合操作を行います。の場合、ShouldComponentUpdate() を使用して反応レンダリングを手動で最適化する必要があります。

    拡張: React フックをご存知ですか?

    コンポーネント クラスの記述は非常に重く、レベルが多すぎるとメンテナンスが困難になります。 。

    関数コンポーネントは純粋な関数であり、状態を含めることはできず、ライフサイクル メソッドをサポートしていないため、クラスを置き換えることはできません。

    #React Hooks の設計目的は、機能コンポーネントを強化することです。「クラス」をまったく使用せずに完全に機能するコンポーネントを作成できます

    #React Hooks の意味コンポーネントは可能な限り純粋な関数として作成する必要があり、外部関数と副作用が必要な場合は、フックを使用して外部コードを「フック」する必要があります。

    #vue コンポーネント通信メソッド

    #props / $emit

      ref / $refs
    • ##parent/親 /##peventBus/vuex/pinia/localStorage/sessionStorage/Cookie/windowprovide/inject
    • なぜ vue はレンダリング リストにキーを追加する必要があるのですか?
    • Vue は、同じタイプの vnode (v- によってレンダリングされるリスト ノードなど) の子ノードのグループを更新するプロセスにあります。の場合)、頻繁な作成と破棄による DOM パフォーマンスのオーバーヘッドを軽減するために:

    キーのない子ノード配列の更新は、インプレース更新戦略を使用します。古い子ノード配列と新しい子ノード配列の長さを比較し、まず短い方の長さを基準として使用し、新しい子ノードの部分に直接パッチします。次に、新しい子ノード配列の長さが長い場合は、新しい子ノード配列の残りの部分を直接マウントし、新しい子ノード配列が短い場合は、古い子ノード配列の余分な部分をアンインストールするかどうかを判断します。

    したがって、子ノードがコンポーネントまたはステートフル DOM 要素である場合、元の状態が保持され、不正なレンダリングが発生します。

    キーを使用した子ノードの更新は、

    patchKeyedChildren と呼ばれます。この関数は、コア diff アルゴリズムを実装するためのよく知られた場所です。おおよそのプロセスは、ヘッド ノードを同期し、テール ノードを同期することです。ノードを作成し、新しいノードの追加と削除を処理し、最後に最長増加サブシーケンスを解く方法を使用して未知のサブシーケンスを処理します。これは、既存のノードの再利用を最大限に高め、DOM 操作のパフォーマンスのオーバーヘッドを削減し、インプレース更新によって引き起こされる子ノードのステータス エラーの問題を回避するためです。 まとめると、v-forを使って定数を走査したり、子ノードがプレーンテキストなどの「状態」を持たないノードであれば、キーを追加せずに書く方法が使えます。ただし、実際の開発プロセスでは、より幅広いシナリオを実現し、ステータス更新エラーを回避できるように、キーを均一に追加することをお勧めします。通常、ESlint を使用してキーを v-for の必須要素として設定できます。

    想详细了解这个知识点的可以去看看我之前写的文章:v-for 到底为啥要加上 key?

    vue3 相对 vue2的响应式优化

    vue2使用的是Object.defineProperty去监听对象属性值的变化,但是它不能监听对象属性的新增和删除,所以需要使用$set$delete这种语法糖去实现,这其实是一种设计上的不足。

    所以 vue3 采用了proxy去实现响应式监听对象属性的增删查改。

    其实从api的原生性能上proxy是比Object.defineProperty要差的。

    而 vue 做的响应式性能优化主要是在将嵌套层级比较深的对象变成响应式的这一过程。

    vue2的做法是在组件初始化的时候就递归执行Object.defineProperty把子对象变成响应式的;

    而vue3是在访问到子对象属性的时候,才会去将它转换为响应式。这种延时定义子对象响应式会对性能有一定的提升

    Vue 核心diff流程

    前提:当同类型的 vnode 的子节点都是一组节点(数组类型)的时候,

    步骤:会走核心 diff 流程

    Vue3是快速选择算法

    • 同步头部节点
    • 同步尾部节点
    • 新增新的节点
    • 删除多余节点
    • 处理未知子序列(贪心 + 二分处理最长递增子序列)

    Vue2是双端比较算法

    在新旧字节点的头尾节点,也就是四个节点之间进行对比,找到可复用的节点,不断向中间靠拢的过程

    diff目的:diff 算法的目的就是为了尽可能地复用节点,减少 DOM 频繁创建和删除带来的性能开销

    vue双向绑定原理

    基于 MVVM 模型,viewModel(业务逻辑层)提供了数据变化后更新视图视图变化后更新数据这样一个功能,就是传统意义上的双向绑定。

    Vue2.x 实现双向绑定核心是通过三个模块:Observer监听器、Watcher订阅者和Compile编译器。

    首先监听器会监听所有的响应式对象属性,编译器会将模板进行编译,找到里面动态绑定的响应式数据并初始化视图;watchr 会去收集这些依赖;当响应式数据发生变更时Observer就会通知 Watcher;watcher接收到监听器的信号就会执行更新函数去更新视图;

    vue3的变更是数据劫持部分使用了porxy 替代 Object.defineProperty,收集的依赖使用组件的副作用渲染函数替代watcher

    v-model 原理

    vue2 v-model 原理剖析

    V-model 是用来监听用户事件然后更新数据的语法糖。

    其本质还是单向数据流,内部是通过绑定元素的 value 值向下传递数据,然后通过绑定 input 事件,向上接收并处理更新数据。

    单向数据流:父组件传递给子组件的值子组件不能修改,只能通过emit事件让父组件自个改。

    // 比如
    <input v-model="sth" />
    // 等价于
    <input :value="sth" @input="sth = $event.target.value" />
    ログイン後にコピー

    给组件添加 v-model 属性时,默认会把value 作为组件的属性,把 input作为给组件绑定事件时的事件名:

    // 父组件
    <my-button v-model="number"></my-button>
    
    // 子组件
    <script>
    export default {
      props: {
        value: Number, //  属性名必须是 value
      },
    
      methods: {
        add() {
          this.$emit(&#39;input&#39;, this.value + 1) // 事件名必须是 input
        },
      }
    }
    </script>
    ログイン後にコピー

    如果想给绑定的 value 属性和 input 事件换个名称呢?可以这样:

    在 Vue 2.2 及以上版本,你可以在定义组件时通过 model 选项的方式来定制 prop/event:

    <script>
    export default {
      model: {
        prop: &#39;num&#39;, // 自定义属性名
        event: &#39;addNum&#39; // 自定义事件名
      }
    }
    ログイン後にコピー

    vue3 v-model 原理

    实现和 vue2 基本一致

    <Son v-model="modalValue"/>
    ログイン後にコピー

    等同于

    <Son v-model="modalValue"/> 
    ログイン後にコピー

    自定义 model 参数

    <Son v-model:visible="visible"/>
    setup(props, ctx){
        ctx.emit("update:visible", false)
    }
    ログイン後にコピー

    vue 响应式原理

    不管vue2 还是 vue3,响应式的核心就是观察者模式 + 劫持数据的变化,在访问的时候做依赖收集和在修改数据的时候执行收集的依赖并更新数据。具体点就是:

    vue2 的话采用的是 Object.definePorperty劫持对象的 get 和 set 方法,每个组件实例都会在渲染时初始化一个 watcher 实例,它会将组件渲染过程中所接触的响应式变量记为依赖,并且保存了组件的更新方法 update。当依赖的 setter 触发时,会通知 watcher 触发组件的 update 方法,从而更新视图。

    Vue3 使用的是 ES6 的 proxy,proxy 不仅能够追踪属性的获取和修改,还可以追踪对象的增删,这在 vue2中需要 set/set/delete 才能实现。然后就是收集的依赖是用组件的副作用渲染函数替代 watcher 实例。

    性能方面,从原生 api 角度,proxy 这个方法的性能是不如 Object.property,但是 vue3 强就强在一个是上面提到的可以追踪对象的增删,第二个是对嵌套对象的处理上是访问到具体属性才会把那个对象属性给转换成响应式,而 vue2 是在初始化的时候就递归调用将整个对象和他的属性都变成响应式,这部分就差了。

    扩展一

    vue2 通过数组下标更改数组视图为什么不会更新?

    尤大:性能不好

    注意:vue3 是没问题的

    why 性能不好?

    我们看一下响应式处理:

    export class Observer {
      this.value = value
        this.dep = new Dep()
        this.vmCount = 0
        def(value, &#39;__ob__&#39;, this)
        if (Array.isArray(value)) {
          // 这里对数组进行单独处理
          if (hasProto) {
            protoAugment(value, arrayMethods)
          } else {
            copyAugment(value, arrayMethods, arrayKeys)
          }
          this.observeArray(value)
        } else {
          // 对对象遍历所有键值
          this.walk(value)
        }
      }
      walk (obj: Object) {
        const keys = Object.keys(obj)
        for (let i = 0; i < keys.length; i++) {
          defineReactive(obj, keys[i])
        }
      }
      observeArray (items: Array<any>) {
        for (let i = 0, l = items.length; i < l; i++) {
          observe(items[i])
        }
      }
    }
    ログイン後にコピー

    对于对象是通过Object.keys()遍历全部的键值,对数组只是observe监听已有的元素,所以通过下标更改不会触发响应式更新。

    理由是数组的键相较对象多很多,当数组数据大的时候性能会很拉胯。所以不开放

    computed 和 watch

    Computed 的大体实现和普通的响应式数据是一致的,不过加了延时计算和缓存的功能:

    在访问computed对象的时候,会触发 getter ,初始化的时候将 computed 属性创建的 watcher (vue3是副作用渲染函数)添加到与之相关的响应式数据的依赖收集器中(dep),然后根据里面一个叫 dirty 的属性判断是否要收集依赖,不需要的话直接返回上一次的计算结果,需要的话就执行更新重新渲染视图。

    watchEffect?

    watchEffect会自动收集回调函数中响应式变量的依赖。并在首次自动执行

    推荐在大部分时候用 watch 显式的指定依赖以避免不必要的重复触发,也避免在后续代码修改或重构时不小心引入新的依赖。watchEffect 适用于一些逻辑相对简单,依赖源和逻辑强相关的场景(或者懒惰的场景 )

    $nextTick 原理?

    vue有个机制,更新 DOM 是异步执行的,当数据变化会产生一个异步更行队列,要等异步队列结束后才会统一进行更新视图,所以改了数据之后立即去拿 dom 还没有更新就会拿不到最新数据。所以提供了一个 nextTick 函数,它的回调函数会在DOM 更新后立即执行。

    nextTick 本质上是个异步任务,由于事件循环机制,异步任务的回调总是在同步任务执行完成后才得到执行。所以源码实现就是根据环境创建异步函数比如 Promise.then(浏览器不支持promise就会用MutationObserver,浏览器不支持MutationObserver就会用setTimeout),然后调用异步函数执行回调队列。

    所以项目中不使用$nextTick的话也可以直接使用Promise.then或者SetTimeout实现相同的效果

    Vue 异常处理

    1、全局错误处理:Vue.config.errorHandler

    Vue.config.errorHandler = function(err, vm, info) {};

    如果在组件渲染时出现运行错误,错误将会被传递至全局Vue.config.errorHandler 配置函数 (如果已设置)。

    比如前端监控领域的 sentry,就是利用这个钩子函数进行的 vue 相关异常捕捉处理

    2、全局警告处理:Vue.config.warnHandler

    Vue.config.warnHandler = function(msg, vm, trace) {};
    ログイン後にコピー

    注意:仅在开发环境生效

    像在模板中引用一个没有定义的变量,它就会有warning

    3、单个vue 实例错误处理:renderError

    const app = new Vue({
        el: "#app",
        renderError(h, err) {
            return h("pre", { style: { color: "red" } }, err.stack);
        }
    });
    ログイン後にコピー

    和组件相关,只适用于开发环境,这个用处不是很大,不如直接看控制台

    4、子孙组件错误处理:errorCaptured

    Vue.component("cat", {
        template: `<div><slot></slot></div>`,
        props: { name: { type: string } },
        errorCaptured(err, vm, info) {
            console.log(`cat EC: ${err.toString()}\ninfo: ${info}`);
            return false;
        }
    });
    ログイン後にコピー

    注:只能在组件内部使用,用于捕获子孙组件的错误,一般可以用于组件开发过程中的错误处理

    5、终极错误捕捉:window.onerror

    window.onerror = function(message, source, line, column, error) {};
    ログイン後にコピー

    它是一个全局的异常处理函数,可以抓取所有的 JavaScript 异常

    Vuex 流程 & 原理

    Vuex 利用 vue 的mixin 机制,在beforeCreate 钩子前混入了 vuexinit 方法,这个方法实现了将 store 注入 vue 实例当中,并注册了 store 的引用属性 store,所以可以使用this.store ,所以可以使用 `this.store.xxx`去引入vuex中定义的内容。

    然后 state 是利用 vue 的 data,通过new Vue({data: {$$state: state}} 将 state 转换成响应式对象,然后使用 computed 函数实时计算 getter

    Vue.use函数里面具体做了哪些事

    概念

    可以通过全局方法Vue.use()注册插件,并能阻止多次注册相同插件,它需要在new Vue之前使用。

    该方法第一个参数必须是ObjectFunction类型的参数。如果是Object那么该Object需要定义一个install方法;如果是Function那么这个函数就被当做install方法。

    Vue.use()执行就是执行install方法,其他传参会作为install方法的参数执行。

    所以**Vue.use()本质就是执行需要注入插件的install方法**。

    源码实现

    export function initUse (Vue: GlobalAPI) {
     Vue.use = function (plugin: Function | Object) {
      const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
      // 避免重复注册
      if (installedPlugins.indexOf(plugin) > -1) {
       return this
      }
      // 获取传入的第一个参数
      const args = toArray(arguments, 1)
      args.unshift(this)
      if (typeof plugin.install === &#39;function&#39;) {
       // 如果传入对象中的install属性是个函数则直接执行
       plugin.install.apply(plugin, args)
      } else if (typeof plugin === &#39;function&#39;) {
       // 如果传入的是函数,则直接(作为install方法)执行
       plugin.apply(null, args)
      }
      // 将已经注册的插件推入全局installedPlugins中
      installedPlugins.push(plugin)
      return this
     }
    }
    ログイン後にコピー

    使用方式

    installedPlugins import Vue from &#39;vue&#39;
    import Element from &#39;element-ui&#39;
    Vue.use(Element)
    ログイン後にコピー

    怎么编写一个vue插件

    要暴露一个install方法,第一个参数是Vue构造器,第二个参数是一个可选的配置项对象

    Myplugin.install = function(Vue, options = {}) {
      // 1、添加全局方法或属性
      Vue.myGlobalMethod = function() {}
      // 2、添加全局服务
      Vue.directive(&#39;my-directive&#39;, {
        bind(el, binding, vnode, pldVnode) {}
      })
      // 3、注入组件选项
      Vue.mixin({
        created: function() {}
      })
      // 4、添加实例方法
      Vue.prototype.$myMethod = function(methodOptions) {}
    }
    ログイン後にコピー

    CSS篇

    Css直接面试问答的题目相对来说比较少,更多的是需要你能够当场手敲代码实现功能,一般来说备一些常见的布局,熟练掌握flex基本就没有什么问题了。

    什么是 BFC

    Block Formatting context,块级格式上下文

    BFC 是一个独立的渲染区域,相当于一个容器,在这个容器中的样式布局不会受到外界的影响。

    比如浮动元素、绝对定位、overflow 除 visble 以外的值、display 为 inline/tabel-cells/flex 都能构建 BFC。

    常常用于解决

    • 处于同一个 BFC 的元素外边距会产生重叠(此时需要将它们放在不同 BFC 中);

    • 清除浮动(float),使用 BFC 包裹浮动的元素即可

    • 阻止元素被浮动元素覆盖,应用于两列式布局,左边宽度固定,右边内容自适应宽度(左边float,右边 overflow)

    伪类和伪元素及使用场景

    伪类

    伪类即:当元素处于特定状态时才会运用的特殊类

    开头为冒号的选择器,用于选择处于特定状态的元素。比如:first-child选择第一个子元素;:hover悬浮在元素上会显示;:focus用键盘选定元素时激活;:link + :visted点击过的链接的样式;:not用于匹配不符合参数选择器的元素;:fist-child匹配元素的第一个子元素;:disabled 匹配禁用的表单元素

    伪元素

    伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过::before 来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。示例:

    ::before 在被选元素前插入内容。需要使用 content 属性来指定要插入的内容。被插入的内容实际上不在文档树中

    h1:before {
        content: "Hello ";
    }
    ログイン後にコピー

    ::first-line 匹配元素中第一行的文本

    src 和 href 区别

    • href是Hypertext Reference的简写,表示超文本引用,指向网络资源所在位置。href 用于在当前文档和引用资源之间确立联系

    • src是source的简写,目的是要把文件下载到html页面中去。src 用于替换当前内容

    • 浏览器解析方式

      当浏览器遇到href会并行下载资源并且不会停止对当前文档的处理。(同时也是为什么建议使用 link 方式加载 CSS,而不是使用 @import 方式)

      当浏览器解析到src ,会暂停其他资源的下载和处理,直到将该资源加载或执行完毕。(这也是script标签为什么放在底部而不是头部的原因)

    不定宽高元素的水平垂直居中

    • flex

      <div class="wrapper flex-center">
        <p>horizontal and vertical</p>
      </div>
      
      .wrapper {
          width: 900px;
          height: 300px;
          border: 1px solid #ccc;
      }
      .flex-center {  // 注意是父元素
          display: flex;
          justify-content: center;  // 主轴(竖线)上的对齐方式
          align-items: center;      // 交叉轴(横轴)上的对齐方式
      }
      ログイン後にコピー
    • flex + margin

      <div class="wrapper">
        <p>horizontal and vertical</p>
      </div>
      
      .wrapper {
          width: 900px;
          height: 300px;
          border: 1px solid #ccc;
          display: flex;
      }
      .wrapper > p {
          margin: auto;
      }
      ログイン後にコピー
    • Transform + absolute

      <div class="wrapper">
          <img  src="test.png" alt="3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因" >
      </div>
      
      .wrapper {
          width: 300px;
          height: 300px;
          border: 1px solid #ccc;
          position: relative;
      }
      .wrapper > img {
          position: absolute;
          left: 50%;
          top: 50%;
          tansform: translate(-50%, -50%)
      }
      ログイン後にコピー

      注:使用该方法只适用于行内元素(a、img、label、br、select等)(宽度随元素的内容变化而变化),用于块级元素(独占一行)会有问题,left/top 的50%是基于图片最左侧的边来移动的,tanslate会将多移动的图片自身的半个长宽移动回去,就实现了水平垂直居中的效果

    • display: table-cell

      <div class="wrapper">
        <p>absghjdgalsjdbhaksldjba</p>
      </div>
      
      .wrapper {
          width: 900px;
          height: 300px;
          border: 1px solid #ccc;
          display: table-cell;
          vertical-align: middle;
          text-align: center;
      }
      ログイン後にコピー

    浏览器和网络篇

    浏览器和网络是八股中最典型的案例了,无论你是几年经验,只要是前端,总会有问到你的浏览器和网络协议。

    最好的学习文章是李兵老师的《浏览器工作原理与实践》

    3 年間の面接経験の共有: フロントエンド面接の 4 つの段階と 3 つの決定要因

    跨页面通信的方法?

    这里分了同源页面和不同源页面的通信。

    不同源页面可以通过 iframe 作为一个桥梁,因为 iframe 可以指定 origin 来忽略同源限制,所以可以在每个页面都嵌入同一个 iframe 然后监听 iframe 中传递的 message 就可以了。

    同源页面的通信大致分为了三类:广播模式、共享存储模式和口口相传模式

    第一种广播模式,就是可以通过 BroadCast Channel、Service Worker 或者 localStorage 作为广播,然后去监听广播事件中消息的变化,达到页面通信的效果。

    第二种是共享存储模式,我们可以通过Shared Worker 或者 IndexedDB,创建全局共享的数据存储。然后再通过轮询去定时获取这些被存储的数据是否有变更,达到一个的通信效果。像常见cookie 也可以作为实现共享存储达到页面通信的一种方式

    最后一种是口口相传模式,这个主要是在使用 window.open 的时候,会返回被打开页面的 window 的引用,而在被打开的页面可以通过 window.opener 获取打开它的页面的 window 点引用,这样,多个页面之间的 window 是能够相互获取到的,传递消息的话通过 postMessage 去传递再做一个事件监听就可以了

    详细说说 HTTP 缓存

    在浏览器第一次发起请求服务的过程中,会根据响应报文中的缓存标识决定是否缓存结果,是否将缓存标识和请求结果存入到浏览器缓存中。

    HTTP 缓存分为强制缓存和协商缓存两类。

    强制缓存就是请求的时候浏览器向缓存查找这次请求的结果,这里分了三种情况,没查找到直接发起请求(和第一次请求一致);查找到了并且缓存结果还没有失效就直接使用缓存结果;查找到但是缓存结果失效了就会使用协商缓存。

    强制缓存有 Expires 和 Cache-control 两个缓存标识,Expires 是http/1.0 的字段,是用来指定过期的具体的一个时间(如 Fri, 02 Sep 2022 08:03:35 GMT),当服务器时间和浏览器时间不一致的话,就会出现问题。所以在 http1.1 添加了 cache-control 这个字段,它的值规定了缓存的范围(public/private/no-cache/no-store),也可以规定缓存在xxx时间内失效(max-age=xxx)是个相对值,就能避免了 expires带来的问题。

    ネゴシエーション キャッシュとは、強制キャッシュのキャッシュ結果が無効になる処理であり、ブラウザはキャッシュ識別子を持ってサーバーにリクエストを送信し、サーバーはキャッシュ識別子を介してキャッシュを使用するかどうかを決定します。

    ネゴシエーション キャッシュを制御するフィールドには、last-modified / if-modified-since および Etag / if-none-match が含まれており、後者の優先順位が高くなります。

    一般的なプロセスでは、リクエスト メッセージを通じて last-modified または Etag の値をサーバーに渡し、サーバー内の対応する値と比較します。応答メッセージ内の -none-match 一貫性がある場合、ネゴシエーション キャッシュは有効であり、キャッシュされた結果が使用され、304 が返されます。そうでない場合は、無効で、結果が再度要求され、200 が返されます。を使用すると、ブラウザはまずコンテンツが検索コンテンツであるか URL であるかを判断します。検索コンテンツの場合は、デフォルトの検索エンジンと組み合わせて URL を生成します。たとえば、Google ブラウザは goole.com/search? xxxx. URL の場合は、http/https などのプロトコルを結合します。ページがアップロード前時間を監視しない場合、または実行プロセスの続行に同意する場合、ブラウザのアイコン バーは読み込み状態になります。

    次に、ブラウザ プロセスは、IPC プロセス間通信を介してネットワーク プロセスに URL リクエストを送信します。ネットワーク プロセスは、まずキャッシュ内のリソースを検索します。リソースがあれば、リクエストをインターセプトします。そのまま200を返します、そうでない場合はネットワークリクエスト処理に入ります。 ネットワーク リクエスト プロセスは、ネットワーク プロセスが DNS サーバーに対して、ドメイン名に対応する IP とポート番号を返すように要求します (これらが以前にキャッシュされている場合は、キャッシュされた結果が直接返されます)。はポート番号ではありません。 http のデフォルトは 80 で、https のデフォルトは 443 です。 https の場合は、暗号化されたデータ チャネルを作成するために TLS 安全な接続を確立する必要もあります。

    その後、TCP スリーウェイ ハンドシェイクによりブラウザとサーバー間の接続が確立され、データ送信が行われます。データ送信が完了したら、手を 4 回振ると切断されます。

    接続の場合: keep-alive

    が設定されているため、常に接続を維持できます。

    ネットワーク プロセスは、TCP を通じて取得したデータ パケットを解析します。まず、応答ヘッダーのコンテンツ タイプに基づいてデータ タイプが決定されます。バイト ストリームまたはファイル タイプの場合は、次のようになります。ダウンロードのためにダウンロード マネージャーに引き渡され、ナビゲーション プロセスは終了します。 text/html タイプの場合は、レンダリングするドキュメントを取得するようにブラウザ プロセスに通知されます。

    ブラウザのプロセスは、レンダリング通知を受け取り、現在のページと新しく入力されたページに基づいて同じサイトであるかどうかを判断し、同じサイトである場合は、以前の Web ページで作成されたレンダリング プロセスを再利用します。レンダリングプロセスを新たに作成します。 ブラウザ プロセスは、レンダリング プロセスに「ドキュメントの送信」メッセージを送信します。レンダリング プロセスはメッセージを受信すると、ネットワーク プロセスとのデータ送信チャネルを確立します。データ送信が完了すると、戻ります。 「送信の確認」メッセージをブラウザのサーバー プロセスに送信します。

    ブラウザは、レンダリング プロセスから「送信の確認」メッセージを受信すると、ブラウザのページ ステータス (セキュリティ ステータス、アドレス バー URL、前方および後方履歴メッセージなど) を更新し、Web ページを更新します。時間 ページは白紙ページ(白い画面)です。

    ページ レンダリング プロセス

    (キー メモリ)

    最後に、レンダリング プロセスは、ページの解析とドキュメントのサブリソースの読み込みを実行します。レンダリング プロセスは、HTML をDOM ツリー構造、および CSS をスタイルシート (CSSOM) に変換します。次に、DOM ツリーをコピーし、表示されていない要素を除外して基本的なレンダリング ツリーを作成し、各 DOM ノードのスタイルを計算し、各ノードの位置レイアウト情報を計算してレイアウト ツリーを構築します。

    レイヤは、レイヤ化コンテキストがある場合、またはトリミングが必要な場合に独立して作成されます。これはレイヤ化と呼ばれます。最終的にレイヤ化されたツリーが形成されます。レンダリング プロセスでは、レイヤごとに描画リストが生成され、それが送信されます。合成スレッドは、レイヤーをタイルに分割し (レイヤーのすべてのコンテンツを一度に描画することを回避し、ビューポート部分はタイルの優先順位に従ってレンダリングできます)、タイルをラスター化スレッドでビットマップに変換します。プール。 変換が完了すると、合成スレッドは描画ブロック コマンド DrawQuard をブラウザ プロセスに送信し、ブラウザは DrawQuard メッセージに基づいてページを生成し、ブラウザ上に表示します。

    略記:

    ブラウザのレンダリング プロセスは、HTML を dom ツリーに解析し、css を cssom ツリーに解析します。次に、最初に DOM ツリーをコピーして、次に、表示要素(display: none など)を cssom と組み合わせて各 dom ノードのレイアウト情報を計算し、レイアウト ツリーを構築します。

    レイアウト ツリーが生成されると、レイヤーのスタッキング コンテキストまたはトリミングされた部分に従って階層化され、階層ツリーが形成されます。 レンダリング プロセスでは、各レイヤーの描画リストが生成され、それが合成スレッドに送信されます。一度限りのレンダリングを避けるために、合成スレッドはブロック単位でレンダリングします。レイヤーをタイルに分割して渡します。ラスタライズ スレッド プールを介してタイルをビットマップに変換します。

    変換が完了すると、合成スレッドはタイルを表示するためにブラウザに描画するコマンドを送信します

    TCP と UDP の違い

    UDP は User Dataprogram Protocol (ユーザー データプログラム プロトコル) IP は、IP アドレス情報を介して指定されたコンピューターにデータ パケットを送信します。最後に、UDP はポート番号を通じてデータ パケットを正しいプログラムに配布できます。 UDP は、データが正しいかどうかを検証できますが、再送機構がなく、間違ったデータ パケットを破棄するだけであり、送信後に宛先に到達したかどうかを確認することはできません。 UDPはデータの信頼性は保証できませんが、伝送速度が非常に速いため、オンラインビデオやインタラクティブゲームなど、データの完全性が厳密に保証されない分野でよく使用されます。

    TCP は、UDP データが失われやすく、データ パケットを正しく組み立てることができないという問題を解決するために導入された伝送制御プロトコル (Transmission Control Protocol) です。ストリーム用のベースのトランスポート層通信プロトコル。 TCP は、パケット損失に対処するための再送信メカニズムを提供し、順序が乱れたデータ パケットを完全なファイルに結合できるパケット ソート メカニズムを導入します。

    TCP ヘッダーには、宛先ポートとローカル ポート番号が含まれるだけでなく、並べ替え用のシーケンス番号も提供されるため、受信側はシーケンス番号を使用してデータ パケットを並べ替えることができます。

    TCP と UDP の違い

    TCP 接続のライフサイクルは、リンク段階、データ送信、切断段階の 3 つの段階を経ます。

    接続フェーズ

    は、クライアントとサーバー間のリンクを確立するために使用され、スリーウェイ ハンドシェイクは、クライアントとサーバー間のデータ パケットの送受信を確認するために使用されます。クライアントとサーバーの能力。

    1. クライアントはまず SYN メッセージを送信してサーバーがデータを送信できることを確認し、SYN_SENT 状態に入ってサーバーからの確認を待ちます

    2. サーバーが SYN を受信するとクライアントは ACK 確認メッセージを送信し、サーバーもクライアントがデータを送信できるかどうかを確認するために SYN メッセージをクライアントに送信します。このとき、サーバーは SYN_RCVD 状態

    3 に入ります。クライアントが ACK SYN メッセージを受信すると、データ パケットがサーバーに送信され、ESTABLISHED 状態になります (接続を確立します)。サーバーがクライアントから送信された ACK パケットを受信すると、ESTABLISHED 状態になり、3 方向通信が完了します。ハンドシェイク

    #送信データ フェーズ

    ##このフェーズでは、受信側は各パケットを確認する必要があります;

    したがって、送信側がデータ パケットを送信するとき、指定された時間内に受信されませんでした。受信側からフィードバックされた確認メッセージはパケット損失と判断され、再送信メカニズムがトリガーされます。

    大きなファイルは、送信中に多くの小さなデータ パケットに分割されます。データ パケットが受信側に到着した後、TCP ヘッダーのシーケンス番号に従って並べ替えて、データの整合性を確保します。

    切断フェーズ

    4 回手を振って、双方が確立した接続を切断できることを確認します

    1. クライアントはサーバー FIN への接続を開始します。サーバーは FIN パケットを受信し、確認パケット ACK を送信し、自身のシリアル番号を送信し、サーバーは CLOSE_WAIT 状態に入ります。この時点では、クライアントにはサーバーに送信するデータがありませんが、サーバーにクライアントに送信するデータがある場合、クライアントはそれを受信する必要があります。クライアントはACKを受信後、FIN_WAIT_2状態

    #3に入ります。サーバーはデータ送信完了後、クライアントにFINパケットを送信します。このとき、サーバーはLAST_ACK状態

    #になります。 ##4. クライアントは FIN を受信します パケットは確認パケット ACK を送信します このとき、クライアントは TIME_WAIT 状態に入り、2 MSL 待ってから CLOSED 状態に入り、サーバーはクライアントの ACK を受信した後に CLOSED 状態に入ります。

    4 波の場合、TCP は全二重通信であるため、アクティブなクロージング側が FIN パケットを送信した後も、受信側は依然としてデータを送信する可能性があり、サーバーからクライアントへのデータ チャネルをすぐに閉じることができません。 , つまり、「サーバーからの

    FIN

    パケットをクライアントからの

    ACK

    パケットと組み合わせて送信することはできません。

    ACK

    は最初にのみ確認できます。そして、

    FIN パケットなので、4 つの波は 4 つのパケット インタラクションである必要があります。Content-length わかりますか? Content-length は、http メッセージの長さ、つまり 10 進数で表されるバイト数です。

    コンテンツの長さ > 実際の長さの場合、サーバー/クライアントはメッセージ キューの終わりを読み取るときに次のバイトを待ち続け、無応答タイムアウトが発生します

    content -length < 実際の長さの場合、最初に要求されたメッセージがインターセプトされ、後続のデータ解析で混乱が生じます。

    content-length の値が不明な場合は、Transfer-Encoding: chunked を使用する必要があります。これにより、長さ 0 の終了ブロックが返されるまで、返されるデータを複数のデータ チャンクに分割できます。

    クロスドメインの共通ソリューション

    クロスドメインとは何ですか?

    プロトコルのドメイン名とポート番号が同じであれば同一ドメイン、どちらかが異なっていればクロスドメインです

    解決策

    1. 従来の jsonp:

    人気のチュートリアル
    詳細>
    関連するチュートリアル
    人気のおすすめ
    最新のコース
    最新のダウンロード
    詳細>
    ウェブエフェクト
    公式サイト
    サイト素材
    フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!