ホームページ  >  記事  >  ウェブフロントエンド  >  【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

青灯夜游
青灯夜游転載
2022-07-06 19:55:144244ブラウズ

この記事では、基本的な知識を整理し、Vue の知識の蓄えを強化するために、Vue の面接の質問の一部を要約して共有します (回答分析付き)。

【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

(学習ビデオ共有: vue ビデオ チュートリアル)

1. Vue.js の基本的な問題

1.1.Vue 応答性の原則

【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

##コア実装クラス: オブザーバー: そのこの機能は、依存関係を収集し、更新をディスパッチするためにゲッターとセッターをオブジェクトのプロパティに追加することです
Dep: 現在の応答オブジェクトの依存関係を収集するために使用されます。サブオブジェクトを含む各応答オブジェクトには Dep インスタンス ((内部のサブオブジェクトはデータが変更されると、各ウォッチャーは dep.notify() を通じて通知されます。
ウォッチャー: オブザーバー オブジェクトのインスタンスは、レンダリング ウォッチャー (レンダー ウォッチャー)、計算プロパティ ウォッ​​チャー (コンピューテッド ウォッチャー)、およびリスナー ウォッチャー (ユーザー ウォッチャー) の 3 つのタイプに分類されます。

ウォッチャーと Dep の関係: Dep は watcher でインスタンス化され、サブスクライバは dep.subs に追加され、dep は dep.subs をトラバースする通知を通じて各ウォッチャーの更新を通知します。

依存関係コレクション: initState 中に、計算された属性が初期化されると、計算されたウォッチャーの依存関係コレクションがトリガーされます。
initState のとき、リスニング属性が初期化されると、ユーザー ウォッチャーの依存関係コレクションがトリガーされます。がトリガーされます。
render() のプロセスにより、レンダー ウォッチャーの依存関係コレクションがトリガーされます。
再レンダリング時には、vm.render() が再度実行され、すべてのサブルーチン内のウォッチャーのサブスクリプションが削除され、再割り当てされます。

更新のディスパッチ: コンポーネント内で応答データが変更され、セッターのロジックがトリガーされます。
dep.notify() を呼び出します。
すべてのサブ (ウォッチャー インスタンス) を走査します。各ウォッチャーの update メソッドを呼び出します。

原則: Vue インスタンスを作成するとき、vue はデータ オプションのプロパティを走査し、Object.defineProperty を使用してゲッターとセッターをプロパティに追加し、データの読み取りをハイジャックします ( getter は Collection に依存するために使用され、setter は更新のディスパッチに使用されます)、内部的に依存関係を追跡し、プロパティがアクセスされ変更されたときに変更を通知します。
各コンポーネント インスタンスには、対応するウォッチャー インスタンスがあり、コンポーネントのレンダリング プロセス中に依存関係のすべてのデータ属性 (依存関係コレクション、計算されたウォッチャー インスタンスおよびユーザー ウォッチャー インスタンス) が記録されます。後で依存関係が変更されると、セッター このメソッドは、このデータに依存するウォッチャー インスタンスに再計算 (更新のディスパッチ) を行うよう通知し、それによって関連するコンポーネントを再レンダリングします。

一文で要約: vue.js はパブリッシュ/サブスクライブ モードと組み合わせたデータ ハイジャックを使用し、Object.defineproperty を使用して
各プロパティのセッターとゲッターをハイジャックし、パブリッシュします。データ変更時のメッセージ サブスクライバーに対して、応答リスニング コールバックをトリガーします

1.2. Vue.js の機能

簡単使いやすさ: シンプル、学習しやすく、すぐに使い始められます

柔軟性: (プログレッシブ) ライブラリと完全なフレームワークの間で自由に拡張できる、活発なエコシステム。
効率的: 最小 gzip 実行サイズ 20kB、超高速仮想 DOM、最も安心な最適化
双方向バインディング: 高い開発効率
コンポーネントベースのコード共有
Web プロジェクト エンジニアリング、可読性の向上安定性と保守性

1.3. Vue.js 双方向バインディングの原理

Vue.js 2.0 はデータ ハイジャック (プロキシ モード) を採用していますパブリッシャー/サブスクライバー モード (PubSub モード) と組み合わせた Object.defineProperty() は、各プロパティのセッターとゲッターをハイジャックし、データ変更時にサブスクライバーにメッセージをパブリッシュし、対応するリスニング コールバックをトリガーするために使用されます。

各コンポーネント インスタンスには、対応するウォッチャー プログラム インスタンスがあります。これは、コンポーネントのレンダリング プロセス中にプロパティを依存関係として記録します。後で、依存関係のセッターが呼び出されるときに、ウォッチャーに再計算するように通知され、その関連付けが行われます。コンポーネントが更新されます。

Vue.js 3.0、Object.defineProperty を放棄し、より高速な ES6 ネイティブ プロキシ (アクセス オブジェクト インターセプター、プロキシとも呼ばれます) を使用しました

ステップ:

1. 観察する必要があるデータ オブジェクトは、サブ属性オブジェクトの属性を含めて再帰的に走査され、セッターとゲッターが追加されます。このオブジェクトに値が割り当てられている場合、セッターは次のようになります。検出されたデータ変更
2.コンパイルはテンプレート命令を解析し、テンプレート内の変数をデータに置き換えてから、レンダリング ページ ビューを初期化し、各命令に対応するノードを更新関数にバインドし、データを監視するサブスクライバです。1 回だけデータが変更されると、通知を受け取り、ビューを更新します。
3. ウォッチャー サブスクライバは、オブザーバーとコンパイルの間の通信のブリッジです。主に行うことは次のとおりです: ① 自分自身を属性サブスクライバに追加します。 (dep) がインスタンス化されるとき ② update() メソッドが必要である ③ dep.notice() によって属性変更が通知されると、独自の update() メソッドを呼び出し、コンパイルでバインドされたコールバックをトリガーできます。成功して引退するだろう。
4. データ バインディングへの入り口として、MVVM はオブザーバー、コンパイル、ウォッチャーを統合します。オブザーバーを使用して独自のモデル データの変更を監視し、コンパイルを使用してテンプレート命令を解析およびコンパイルし、最後にウォッチャーを使用して間のギャップを埋めます。オブザーバーとコンパイル: データ変更 -> 更新の表示、インタラクティブな変更 (入力) の表示 -> データ モデル変更の双方向のバインディング効果を達成するための通信ブリッジ。

1.4. Vue でプロパティ値の変更を監視するにはどうすればよいですか?

たとえば、データ内の obj.a の変更を監視する必要があります。 Vue では次のようにオブジェクト属性の変更を監視できます:

watch: {
      obj: {
      	handler (newValue, oldValue) {
        console.log('obj changed')
      },
      deep: true
    }

deep 属性は深いトラバーサルを表しますが、このように書くと obj のすべての属性変更を監視することになり、これは私たちが望んでいる効果ではないため、いくつかの変更を加えます。 :

watch: {
   'obj.a': {
      	handler (newName, oldName) {
        console.log('obj.a changed')
      }
   }
  }

計算によって実装できる別のメソッドがあります。必要な作業は次のとおりです:

computed: {
    a1 () {
      return this.obj.a    
      }
}

計算されたプロパティの特性を使用してそれを実現します。依存関係が変更されると、新しい値が追加されます再計算されます。

1.5.Vue.js 3.0 は、次の理由により、defineProperty を放棄し、プロキシを使用します。

Object.defineProperty の欠陥

1. 配列を監視するターゲットが変更されると、オーバーヘッドが高くなります。そのため、Vue.js は添字の変更の検出を放棄しました;
2.Object.defineProperty はオブジェクトのプロパティをハイジャックすることしかできませんが、Proxy は直接プロキシ オブジェクトです。 3.Object.defineProperty はオブジェクトの各プロパティを走査する必要があり、プロパティ値もオブジェクトの場合は、詳細な走査が必要です。プロキシはオブジェクトを直接プロキシするため、トラバーサル操作は必要ありません。
4. 新しいプロパティについては、Object.defineProperty を手動で確認する必要があります。 vue2 は、新しく追加されたプロパティも応答するようにするために vm.$set を使用する必要があります。
5.Proxy は、defineProperty にはない 13 種類のインターセプト操作をサポートします。
6.Proxy は、長い目で見ると新しい標準です。 run, JS エンジンはプロキシの最適化を継続しますが、ゲッターとセッターは基本的にターゲットを絞った方法で最適化されなくなります

1.6. これは、新しい属性がVue 2 のデータの object 属性とは何ですか?の解き方?

ビューは更新されません。これは、Vue インスタンスの作成時に新しいプロパティが宣言されていないため、Vue によって応答性の高いプロパティに変換されず、当然ビューの更新がトリガーされないためです。この場合、Vue のグローバルを使用する必要があります。 api $set():

this.$set(this.obj, 'new_property', 'new_value')

1.7. Computed と Watch の違いとそのアプリケーション シナリオ

Computed 計算プロパティ:他のプロパティ値に依存し、計算される 値はキャッシュされ、依存する属性値が変更された場合にのみ、次回計算値を取得するときに計算値が再計算されます。
ウォッチ リスナー: これは、特定のデータの監視コールバックに似た、キャッシュを使用しない監視関数であり、監視対象のデータが変更されるたびに、後続の操作のためにコールバックが実行されます。

アプリケーション シナリオ:

1. 数値計算を実行する必要があり、他のデータに依存する場合は、computed のキャッシュ機能を使用して次のことができるため、computed を使用する必要があります。回避 値が取得されるたびに、値が再計算されます。
2. データ変更時に非同期操作や高コストの操作を実行する必要がある場合は、watch を使用する必要があります。watch オプションを使用すると、非同期操作 (API にアクセス) を実行し、操作を実行する頻度を制限できます。最終結果を得る前に、中間状態をセットアップします。これらは、計算されたプロパティでは実行できないことです。
3. 複数の要因が 1 つの表示に影響を与える場合は、Computed を使用し、1 つの要因の変更が他の複数の要因および表示に影響を与える場合は、Watch;

1.8. Computed との違いMethods

1.computed: 計算されたプロパティは依存関係に基づいてキャッシュされ、関連する依存関係が変更された場合にのみ再評価されます。メソッドの場合、再レンダリングが発生するたびに
2.メソッド呼び出しは常に関数を実行します

1.9. 仮想 DOM、差分アルゴリズム

1. DOM 要素を直接操作するのではなく、ページを再レンダリングするためのデータのみを操作しましょう
2 .Virtual DOM はブラウザのパフォーマンスの問題を解決するように設計されています
データを操作する際、変更された DOM 要素はキャッシュされ、計算後に比較を通じて実際の DOM ツリーにマッピングされます
3. diff アルゴリズム新旧の仮想 DOM を比較します。ノードの種類が同じ場合は、データを比較してデータを変更します。ノードが異なる場合は、そのノードとすべての子ノードを直接削除し、新しいノードを挿入します。各ノードに一意のキーが設定されている場合は、正確に変更する必要があるものを見つけてください。そうしないと、1 つの場所を変更すると他の場所も変更されるという状況が発生します。たとえば、A-B-C-D に新しいノード A-B-M-C-D を挿入したい場合、実際には C と D が変更されます。ただし、キーを設定した後は、B C を正確に見つけて

1.10 を挿入できます。なぜ仮想 DOM が必要なのでしょうか?

1. クロスプラットフォームの利点があります
2. DOM の操作は遅いですが、js は効率的に実行されます。 DOM 比較操作を JS レイヤーに配置して効率を向上させることができます。
3. レンダリング パフォーマンスの向上

1.11. フィルター

Vue のフィルターを使用してデータをフィルター (フォーマット) します。フィルターは変更しませんデータをフィルタリング (フォーマット) し、ユーザーに表示される出力を変更します (計算された属性、メソッドはすべて、データを変更することでデータ形式の出力表示を処理します。)
使用シナリオ: たとえば、時間、数値などの表示形式;

1.12. 一般的なイベント修飾子とその機能

1) .stop: JavaScript のevent.stopPropagation() に相当し、イベントのバブリングを防止します。
2).prevent: JavaScript のevent.preventDefault() に相当し、事前設定されたイベントの実行を防止します。動作 (イベントをキャンセルできる場合は、イベントのさらなる伝播を停止せずにイベントをキャンセルします);
3).capture: 要素がバブルするとき、最初にこの変更シンボル要素でトリガーします。複数のモディファイアがある場合、それらは外側から内側にトリガーされます。たとえば、p1 が p2 にネストされ、p3 が p4 にネストされ、capture が p4 にネストされている場合、実行シーケンスは次のようになります。 p3=》p4=》p2=》p1
4).self: 子要素を除き、スコープ内のイベント自体をトリガーします;
5).once: 1 回だけトリガーされます。

1.13. v-show 命令と v-if 命令の違いは何ですか?

v-show 要素の表示モードのみを制御します、表示属性を block と none の間で切り替えます; および v -if は、この DOM ノード の有無を制御します。要素の表示/非表示を頻繁に切り替える必要がある場合は、v-show を使用するとパフォーマンスのオーバーヘッドがさらに節約されますが、要素の表示/非表示を 1 回だけ行う必要がある場合は、v-if を使用する方が合理的です。

1.14. v-model はどのように実装されていますか?実際の構文糖衣は何ですか?

これはフォーム要素と v-model="message" に作用します。 v-bind:value="message" v-on:input="message=e v e n t . t a r g e t . v a l u e " は、コンポーネントに作用します。これは本質的に、親子コンポーネント通信用の糖衣構文であり、 prop および を通じて実装されます。 value="message" @input=" $emit('input', $event.target.value)"

1.15.なぜdata オブジェクトではなく関数

JavaScript のオブジェクトは参照型データです。複数のインスタンスが同じオブジェクトを参照する場合、1 つのインスタンスがこのオブジェクト上で動作する限り、他のインスタンスのデータは参照されません。インスタンスも変わります。
Vue では、コンポーネントをより再利用したいため、コンポーネントが互いに干渉しないように、各コンポーネントが独自のデータを持つ必要があります。
したがって、コンポーネントのデータはオブジェクトの形式で記述することはできず、関数の形式で記述する必要があります。データは関数の戻り値の形式で定義されるため、コンポーネントを再利用するたびに新しいデータが返されます。つまり、各コンポーネントには独自のプライベート データ領域があり、それぞれ独自のデータを維持できます。他のコンポーネントの通常の動作を妨げます。

1.16. Vue テンプレートからレンダリングまでのプロセス

1. parse メソッドを呼び出してテンプレートを ast (抽象構文ツリー、抽象構文ツリー )
2. 静的ノードを最適化します。静的ノードの場合、生成される DOM は決して変更されないため、ランタイム テンプレートの更新が大幅に最適化されます。
3. レンダリング関数を生成します。レンダリングの戻り値は VNode です。VNode は、(ラベル名、子ノード、テキストなど) を含む Vue の仮想 DOM ノードです。

1.17 .Vue テンプレートをレンダリング処理に使用する

parse メソッドを呼び出してテンプレートを ast (抽象構文ツリー) に変換する
静的ノードを最適化します。静的ノードの場合、生成される DOM は決して変更されないため、ランタイム テンプレートの更新が大幅に最適化されます。
レンダリング関数を生成します。レンダリングの戻り値は VNode です。VNode は (ラベル名、子ノード、テキストなど) を含む Vue の仮想 DOM ノードです。

1.18.axios是什么

易用、简洁且高效的http库, 支持node端和浏览器端,支持Promise,支持拦截器等高级配置。

1.19.sass是什么?如何在vue中安装和使用?

sass是一种CSS预编译语言安装和使用步骤如下。

1.用npm安装加载程序( sass-loader、 css-loader等加载程序)。
2.在 webpack.config.js中配置sass加载程序。

1.20.Vue.js页面闪烁

Vue. js提供了一个v-cloak指令,该指令一直保持在元素上,直到关联实例结束编译。当和CSS一起使用时,这个指令可以隐藏未编译的标签,直到实例编译结束。用法如下

1.21.如何解决数据层级结构太深的问题

在开发业务时,经常会岀现异步获取数据的情况,有时数据层次比较深,如以下代码: , 可以使用vm.$set手动定义一层数据:

vm.$set("demo",a.b.c.d)

1.22.在 Vue. js开发环境下调用API接口,如何避免跨域

config/ index.js内对 proxyTable项配置代理。

1.23.批量异步更新策略

Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
换句话说,只要观察到数据变化,就会自动开启一个队列,并缓冲在同一个事件循环中发生的所以数据改变。在缓冲时会去除重复数据,从而避免不必要的计算和 DOM 操作。

1.24.vue 的 nextTick 方法的实现原理

1.vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
2.microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕

1.25.Vue 组件 data 为什么必须是函数 ?

因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染。
所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。

1.26.v-if和v-for一起使用的弊端及解决办法

由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。

解决办法:

1.在v-for的外层或内层包裹一个元素来使用v-if
2.用computed处理

1.27.vue常用指令

1.v-model 多用于表单元素实现双向数据绑定(同angular中的ng-model)
2.v-bind 动态绑定 作用: 及时对页面的数据进行更改
3.v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods里面
4.v-for 格式: v-for=“字段名 in(of) 数组json” 循环数组或json(同angular中的ng-repeat)
5.v-show 显示内容 (同angular中的ng-show)
6.v-hide 隐藏内容(同angular中的ng-hide)
7.v-if 显示与隐藏 (dom元素的删除添加 同angular中的ng-if 默认值为false)
8.v-else-if 必须和v-if连用
9.v-else 必须和v-if连用 不能单独使用 否则报错 模板编译错误
10.v-text 解析文本
11.v-html 解析html标签
12.v-bind:class 三种绑定方法 1、对象型 ‘{red:isred}’ 2、三元型 ‘isred?“red”:“blue”’ 3、数组型 ‘[{red:“isred”},{blue:“isblue”}]’
13.v-once 进入页面时 只渲染一次 不在进行渲染
14.v-cloak 防止闪烁
15.v-pre 把标签内部的元素原位输出

1.28. 组件传值方式有哪些

1.父传子:子组件通过props[‘xx’] 来接收父组件传递的属性 xx 的值
2.子传父:子组件通过 this.$emit(‘fnName’,value) 来传递,父组件通过接收 fnName 事件方法来接收回调
3.其他方式:通过创建一个bus,进行传值
4.使用Vuex

1.30.vue中 key 值的作用

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM

1.31.为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?

Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性(Vue 为什么不能检测数组变动 )。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组

push();
pop();
shift();
unshift();
splice();
sort();
reverse();

由于只针对了以上 7 种方法进行了 hack 处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。

Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。
Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

1.32.谈一谈 nextTick 的原理

JS 运行机制

JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:

所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。

【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)
主线程的执行过程就是一个 tick,而所有的异步结果都是通过 “任务队列” 来调度。 消息队列中存放的是一个个的任务(task)。 规范中规定 task 分为两大类,分别是 macro task 和 micro task,并且每个 macro task 结束后,都要清空所有的 micro task。

for (macroTask of macroTaskQueue) {
  // 1. Handle current MACRO-TASK
  handleMacroTask();

  // 2. Handle all MICRO-TASK
  for (microTask of microTaskQueue) {
    handleMicroTask(microTask);
  }}

在浏览器环境中 :

常见的 macro task 有 setTimeout、MessageChannel、postMessage、setImmediate

常见的 micro task 有 MutationObsever 和 Promise.then

异步更新队列

可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
在 vue2.5 的源码中,macrotask 降级的方案依次是:setImmediate、MessageChannel、setTimeout

vue 的 nextTick 方法的实现原理:

vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
考虑兼容问题,vue 做了 microtask 向 macrotask 的降级方案

1.33.谈谈 Vue 事件机制,手写on,off,emit,once

Vue 事件机制 本质上就是 一个 发布-订阅 模式的实现。

class Vue {
  constructor() {
    //  事件通道调度中心
    this._events = Object.create(null);
  }
  $on(event, fn) {
    if (Array.isArray(event)) {
      event.map(item => {
        this.$on(item, fn);
      });
    } else {
      (this._events[event] || (this._events[event] = [])).push(fn);
    }
    return this;
  }
  $once(event, fn) {
    function on() {
      this.$off(event, on);
      fn.apply(this, arguments);
    }
    on.fn = fn;
    this.$on(event, on);
    return this;
  }
  $off(event, fn) {
    if (!arguments.length) {
      this._events = Object.create(null);
      return this;
    }
    if (Array.isArray(event)) {
      event.map(item => {
        this.$off(item, fn);
      });
      return this;
    }
    const cbs = this._events[event];
    if (!cbs) {
     return this;
    }
    if (!fn) {
      this._events[event] = null;
      return this;
    }
    let cb;
    let i = cbs.length;
    while (i--) {
      cb = cbs[i];
      if (cb === fn || cb.fn === fn) {
        cbs.splice(i, 1);
        break;
      }
    }
    return this;
  }
  $emit(event) {
    let cbs = this._events[event];
    if (cbs) {
      const args = [].slice.call(arguments, 1);
      cbs.map(item => {
        args ? item.apply(this, args) : item.call(this);
      });
    }
    return this;
  }}

1.34.vue-router有哪几种导航钩子?

三种:

一种是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。第二种:组件内的钩子;第三种:单独路由独享组件

1.35.vuex是什么?怎么使用?哪种功能场景使用它?

vue框架中状态管理。在main.js引入store,注入。新建了一个目录store,…… export 。
场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

1.36.MVVM と MVC の違いは何ですか?他のフレームワーク(jquery)とどう違うのですか?どのシナリオが適用されますか?

MVVM と MVC は両方とも設計思想です。主なことは、MVC のコントローラーが ViewModel に進化することです。MVVM は主にノードを操作するのではなく、データを通じてビュー層を表示します。 MVC の問題。多数の DOM 操作により、ページのレンダリング パフォーマンスが低下し、読み込み速度が遅くなり、ユーザー エクスペリエンスに影響します。主に、大量のデータ操作を行うシナリオで使用されます。
シナリオ: 多くのデータ操作を含むシナリオ、より便利
【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

1.37. Vue.js テンプレートのコンパイルについての理解を話しましょう

つまり、最初に AST ツリーに変換され、その結果のレンダリング関数が VNODE (Vue 社の仮想 DOM ノード) を返します。
詳細な手順:

最初に、パスを渡します。コンパイラは、テンプレートを AST 構文ツリーにコンパイルします (抽象構文ツリーは、ソース コードの抽象構文構造をツリー表現したものです)。コンパイラは、コンパイラの作成に使用される createCompiler の戻り値です。オプションのマージを担当します。
次に、描画関数を取得するための AST の生成 (AST 構文木を描画関数文字列に変換する処理) が行われます。描画の戻り値は VNode です。VNode は Vue の仮想 DOM ノードであり、 (ラベル名、子ノード、テキストなど) を含む

1.38. の機能とその使用方法?

回答: 動的コンポーネントをラップすると、非アクティブなコンポーネント インスタンスがキャッシュされ、主にコンポーネントの状態を保持したり、再レンダリングを回避したりするために使用されます。
用途: 単純なページ
キャッシュ:
キャッシュしない:

1.39. vue と React の違い

同じ点: どちらもコンポーネント化を促進し、どちらも 'props' の概念を持ち、それぞれが独自の構築ツールを持ち、Reat と Vue はフレームワークの骨格のみを持ち、ルーティングや状態管理などの他の機能はフレームワークから分離されたコンポーネントです。

相違点: React: 一方向データ フロー、構文 - JSX、React では状態を更新するために setState() メソッドを使用する必要があります。 Vue: 双方向データ バインディング、構文 – HTML、状態オブジェクトは必要ありません。データは Vue オブジェクト内で data 属性によって管理されます。小規模なアプリケーションには適していますが、大規模なアプリケーションには適していません。

1.40. vue のライフサイクルを理解していますか?

マスターの記事を参照してください: vue ノート - ライフ サイクルの 2 番目の学習と理解
【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)

beforeCreate は新規作成後にトリガーされますVue() 最初のフックでは、現在のステージではデータ、メソッド、計算済み、および監視上のデータとメソッドにアクセスできません。

createdインスタンスの作成後に発生します。現段階でデータの観察は完了しています。つまり、データの使用と変更が可能です。ここでデータを変更しても、更新はトリガーされません関数。初期データの取得を実行できます。現在の段階では Dom と対話できません。必要な場合は、vm.$nextTick を通じて Dom にアクセスできます。

beforeMountマウント前に発生します。その前に、テンプレートがインポートされ、レンダリング関数でコンパイルされます。現段階では、仮想 Dom が作成され、レンダリングが開始されるところです。この時点でデータを変更することもできますが、更新はトリガーされません。

mountedマウント完了後に発生します。現段階では、実際の Dom がマウントされ、データが双方向にバインドされ、Dom ノードにアクセスでき、Dom にアクセスできます。 $refs 属性を使用して操作します。

beforeUpdate は更新の前に発生します。つまり、応答データが更新され、再レンダリングの前に仮想 dom がトリガーされます。再レンダリングを行わずに現在のステージのデータを変更できます。

updated更新が完了し、現在のステージのコンポーネント Dom が更新された後に発生します。更新の無限ループが発生する可能性があるため、この期間中にデータを変更しないように注意してください。

beforeDestroyインスタンスが破棄される前に発生します。インスタンスは現在の段階で完全に使用できます。この時点で、タイマーのクリアなどの後処理の仕上げ作業を実行できます。

destroyedインスタンスが破棄された後に発生し、この時点では dom シェルのみが残ります。コンポーネントは逆アセンブルされ、データ バインディングは削除され、リスナーは削除され、すべての子インスタンスは破棄されました。

#1.41. Vue2.x レンダラと Vue3.x レンダラの差分アルゴリズムについてそれぞれ話しましょう

つまり、差分アルゴリズムには次のプロセスがあります

1. 同じレベルを比較してから、子ノードを比較します

2. まず、一方のパーティに子ノードがあり、もう一方のパーティに子ノードがないかどうかを確認します (新しい子に子ノードがない場合は、古い子を削除します)ノード)
3. 子ノードがある状況を比較します (コア差分)
3. 子ノードを再帰的に比較します

2 つのツリー間の通常の Diff の時間計算量は O(n^3) ですが、実際の状況では DOM をレベル間で移動することはほとんどないため、Vue は ## から Diff 最適化を実行します。 #O(n^3) -> O(n)、古い子と新しい子が複数の子ノードである場合にのみ、コア Diff アルゴリズムを同じレベルの比較に使用する必要があります。

Vue2 のコア Diff アルゴリズムは両端比較アルゴリズムを使用しており、同時に古い子と新しい子の両端から比較し、キー値を使用して再利用可能なノードを見つけ、関連する操作を実行します。 。同じ状況下で React の Diff アルゴリズムと比較すると、モバイル ノードの数を減らし、不必要なパフォーマンスの損失を減らすことができ、よりエレガントです。

Vue3.x は

ivi アルゴリズムと inferno アルゴリズムを利用します

VNode のタイプは作成時に決定され、作成中にビット演算を使用して VNode の値が決定されます。これに基づいて、マウント/パッチ プロセス タイプをコア Diff アルゴリズムと組み合わせることで、Vue2.x と比較してパフォーマンスが向上します。 (実際の実装は、Vue3.x ソース コードと併せて参照できます。)

このアルゴリズムは、動的プログラミングのアイデアも使用して、最長の再帰サブシーケンスを解決します。

1.42. Vue に対してどのようなパフォーマンスの最適化を行いましたか?

エンコーディング フェーズ

1. データ内のデータを削減してみてください。データ内のデータにはゲッターとセッター、および対応する 2.watcher## が追加されます。 # 3 が収集されます。.v-if と v-for は一緒に使用できません

4. v-for を使用してイベントを各要素にバインドする必要がある場合は、イベント プロキシを使用してください
5. SPA ページキープアライブ キャッシュ コンポーネントを使用します
6. 多くの場合、v-show の代わりに v-if を使用します
7. キーは一意であることが保証されます
8. 遅延読み込みおよび非同期コンポーネントにはルーティングを使用します
9. 手ぶれ補正とスロットリング
10. オンデマンドでサードパーティ製モジュールをインポート
11. 長いリストを表示領域までスクロールして動的読み込みを行う
12. 画像の遅延読み込み

#SEO の最適化

1. プリレンダリング

2. サーバーサイド レンダリング SSR


パッケージの最適化

1. 圧縮コード

2. ツリーシェイキング/スコープホイスティング
3. cdnを使用してサードパーティモジュールをロード

4. マルチスレッドパッケージングhappypack
5. splitChunksでパブリックファイルを抽出
6.SourceMap の最適化


ユーザー エクスペリエンス

1. スケルトン画面

2.PWA


キャッシュ (クライアント) も使用できます。キャッシュ、サーバー キャッシュ) の最適化、サーバーでの gzip 圧縮の有効化など。

1.43. ハッシュ ルーティングとヒストリー ルーティングの実装原則について話しましょう。

location.hash

の値は、実際には次のものです。 URLの#。

history

は、実際には HTML5 で提供される API、主に

history.pushState()history.replaceState() を使用して実装されます。 1.44. SPA シングル ページの理解、その利点と欠点は何ですか

SPA (シングル ページ アプリケーション) は、Web ページの初期化時に対応する HTML のみを読み込みます、JavaScript および CSS ページが読み込まれると、SPA はユーザーの操作によってページをリロードしたりジャンプしたりしません

代わりに、ルーティング メカニズムを使用して HTML コンテンツの変換と UI とユーザーの間の対話を実現します。ページのリロードを回避するため

利点:


1. ユーザー エクスペリエンスは優れており、高速です。コンテンツの変更にはページ全体をリロードする必要がなく、不必要なジャンプやレンダリングの繰り返しが回避されます

2、上記の点に基づいて、SPA はサーバーへの負荷が比較的小さいことがわかります。
3. フロントエンドとバックエンドの責任が分離されており、アーキテクチャが明確です。フロントエンドは対話型ロジックを実行し、バックエンドは責任を負います。データ処理用



#欠点:

1. 初期読み込みに時間がかかる: シングルページ Web アプリケーションの機能と表示効果を実現するために

JavaScript と CSS はページの読み込み時に均一に読み込まれる必要があり、一部のページはオンデマンドで読み込まれます
2. 次に進む 戻るルーティング管理: シングルページ アプリケーションはすべてのコンテンツを 1 ページに表示するため、

したがって、ブラウザの進む機能と戻る機能を使用し、すべてのページ切り替えには独自のスタック管理が必要です。
3. SEO は難しいです。すべてのコンテンツが動的に置き換えられて 1 ページに表示されるため、SEO には当然の弱点があります。


1.45.vue.cli でカスタム コンポーネントを使用するにはどうすればよいですか?何か問題が発生しましたか?

最初のステップ: コンポーネント ディレクトリにコンポーネント ファイル (indexPage.vue) を作成します。スクリプトは

export default {}

である必要があります。 : 必要なページ (コンポーネント) にインポートします: importindexPage from '@/components/indexPage.vue'
ステップ 3: vue, のサブコンポーネントのコンポーネント属性に挿入します。コンポーネント:{indexPage}
ステップ 4: テンプレート ビューで使用します。 たとえば、indexPage という名前の場合、使用すると、index-page
# になります。
##1.46 .vue が webpack 設定を使用してオンデマンド読み込みを実装する方法

require.ensure()

は、オンデマンド読み込みを実現するために webpack で提供されます。以前はルートは import によって導入されていましたが、現在は const 定義によって導入されます。
ページのオンデマンド読み込みを行わない導入方法:

import home from '../../common/home.vue' ページのオンデマンド読み込みの導入方法:
const home = r =>require.ensure( [], () =>r (require('../../common/home.vue')))

二、组件 Component

2.1.vue中如何编写可复用的组件 (编写组件的原则)

以组件功能命名
只负责ui的展示和交互动画,不要在组件里与服务器打交道(获取异步数据等)
可复用组件不会因组件使用的位置、场景而变化。尽量减少对外部条件的依赖。

2.2.如何让CSS只在当前组件中起作用?

在每一个Vue.js组件中都可以定义各自的CSS、 JavaScript代码。如果希望组件内写的CSS只对当前组件起作用,只需要在Style标签添加Scoped属性即可

2.3.keep-alive是什么?

如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。

两个重要属性,include 缓存组件名称,exclude 不需要缓存的组件名称。

2.4.如何在 Vue. js动态插入图片

对“src”属性插值将导致404请求错误。应使用 v-bind:src (简写:src)格式代替。

2.5.父子组件的生命周期顺序(可参照上方图解)

加载渲染过程:
beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程:父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程:父beforeUpdate->父updated
销毁过程:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

三、Vuex

3.1.vuex的核心概念

1.state => 基本数据
2.getters => 从基本数据派生的数据
3.mutations => 修改数据,同步
4.actions => 修改数据,异步 (Action 提交的是 mutation,而不是直接变更状态)
5.modules => 模块化Vuex

3.2.vuex是什么?怎么使用?哪种功能场景使用它?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理器,采用集中式存储管理应用的所有组件的状态,主要是为了多页面、多组件之间的通信。
Vuex有5个重要的属性,分别是 State、Getter、Mutation、Action、Module,由 view 层发起一个 Action 给 Mutation,在 Mutation 中修改状态,返回新的状态,通过 Getter暴露给 view层的组件或者页面,页面监测到状态改变于是更新页面。如果你的项目很简单,最好不要使用 Vuex,对于大型项目,Vuex 能够更好的帮助我们管理组件外部的状态,一般可以运用在购物车、登录状态、播放等场景中。

3.3.多个组件之间如何拆分各自的state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块

1.公共的数据部分可以提升至和他们最近的父组件,由父组件派发
2.公共数据可以放到vuex中统一管理,各组件分别获取

3.4.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?

1.如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。

2.如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便

3.5.Vuex中如何异步修改状态

actions与mutations作用类似,都是可以对状态进行修改。不同的是actions是异步操作的。

actions是可以调用Mutations里的方法的。

const actions={
	addActions(context){
		context.commit('add',10);//调用mutations中的方法
		setTimeout(()=>{context.commit('reduce')},5000)
	//	setTimeOut(()=>{context.commit('reduce')},3000);
		console.log('我比reduce提前执行');
	},
	
	reduceActions({commit}){
		commit('reduce');
	}}

3.6.Vuex中actions和mutations的区别

Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }})

Action Action 类似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }})

3.7.怎么在组件中批量使用Vuex的state状态?

使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中

import {mapState} from 'vuex' export default{ computed:{ ...mapState(['price','number']) } }

3.8.Vuex中状态是对象时,使用时要注意什么?

对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改。

四、Router

4.1.vue-router 路由模式有几种

1.Hash: 使用 URL 的 hash 值来作为路由。支持所有浏览器。 带#。如:http://localhost:8080/#/pageA。改变hash,浏览器本身不会有任何请求服务器动作的,但是页面状态和url已经关联起来了。
2.History: 以来 HTML5 History API 和服务器配置。参考官网中 HTML5 History 模式,不带#, 如:http://localhost:8080/ 正常的而路径,并没有#。基于HTML5的 pushState、replaceState实现
3.Abstract: 支持所有 javascript 运行模式。如果发现没有浏览器的 API,路由会自动强制进入这个模式。

4.2.vue-router如何定义嵌套路由

通过children 数组:

const router = new VueRouter({
  routes: [
    {
      path: "/parentPage",
      component: testPage,
      children: [
        {
          path: "/childrenA",
          component: childrenComponentA,
        },
        {
          path: "/childrenB",
          component: childrenComponentB,
        },
      ],
    },
    {
      // 其他和parentPage平级的路由
    },
  ],});

4.3.vue-router有哪几种导航钩子?

1.全局导航钩子:router.beforeEach(to,from,next)
2.组件内的钩子beforeRouteEnter (to, from, next) beforeRouteUpdate (to, from, next) beforeRouteLeave (to, from, next)
3.单独路由独享组件 beforeEnter: (to, from, next)

参数:有to(去的那个路由)、from(离开的路由)、next(一定要用这个函数才能去到下一个路由,如果不用就拦截)最常用就这几种

4.4. $ route和$ router的区别

1、$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。

1.$route.path 字符串,对应当前路由的路径,总是解析为绝对路径如"/foo/bar"。
2. $route.params 一个 key/value 对象,包含了 动态片段 和 全匹配片段, 如果没有路由参数,就是一个空对象。
3. $route.query 一个 key/value 对象,表示 URL 查询参数。 例如,对于路径 /foo?user=1,则有$route.query.user == 1, 如果没有查询参数,则是个空对象
4. $route.hash 当前路由的hash值 (不带#) ,如果没有 hash 值,则为空字符串
5. $route.fullPath 完成解析后的 URL,包含查询参数和hash的完整路径。
6. $route.matched 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
7. $route.name 当前路径名字
8. $ route.meta 路由元信息

2、$router是“路由实例”对象包括了路由的跳转方法,钩子函数等

实例方法:

1)、push

1.字符串this.$router.push('home')
2. 对象this.$router.push({path:'home'})
3. 命名的路由this.$router.push({name:'user',params:{userId:123}})
4.带查询参数,变成 /register?plan=123this.$router.push({path:'register',query:{plan:'123'}})
push方法其实和是等同的。
注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。

2)、go
页面路由跳转
前进或者后退this.$router.go(-1) // 后退

3)、replace
push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,
不会向 history 栈添加一个新的记录

4.5.路由之间跳转的方式

1.声明式(标签跳转)
2.编程式( js跳转)

4.6.active-class是哪个组件的属性

vue-router 模块 的router-link组件

4.7.vue-router实现路由懒加载(动态加载路由)

把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应的组件即为路由的懒加载,可以加快项目的加载速度,提高效率

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      name: 'Home',      
      component:() = import('../views/home')
	}
  ]})

4.8.怎么定义vue-router的动态路由以及如何获取传过来的动态参数?

在router目录下的index.js文件中,对path属性加上/:id
使用router对象的params id

面试官:我难道问不倒这小子了?(面试官持续懵逼中) 对大家有帮助的话三连呀~ 持续更新

[関連ビデオ チュートリアルの推奨事項: vuejs エントリ チュートリアルWeb フロントエンド エントリ]

以上が【吐血】Vue.js面接の質問まとめと回答分析(取りに来てください)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。