【直接収集】フロントエンド VUE のハイレベルな面接の質問 (1)

1. vue の動的パーミッション バインディング レンダリング リスト (パーミッション リスト レンダリング) について話します。

  1. まず、this.$http.get("rights/list"); のように、サーバーに現在のユーザーの権限データを取得するように要求します。

  2. 権限データを取得した後、リスト内の v-if v-if-else の組み合わせを使用して別のコンテンツを表示します

<template>
 <div>
   <!-- 面包屑导航区 -->
   <el-breadcrumb separator-class="el-icon-arrow-right">
     <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
     <el-breadcrumb-item>权限管理</el-breadcrumb-item>
     <el-breadcrumb-item>权限列表</el-breadcrumb-item>
   </el-breadcrumb>
   <!-- 卡片视图 -->
   <el-card>
     <el-table :data="rightsList" border stripe>
       <el-table-column type="index" label="#"></el-table-column>
       <el-table-column label="权限名称" prop="authName"></el-table-column>
       <el-table-column label="路径" prop="path"></el-table-column>
       <el-table-column label="权限等级" prop="level">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.level === '0'">一级</el-tag>
           <el-tag type="success" v-else-if="scope.row.level === '1'">二级</el-tag>
           <el-tag type="danger" v-else>三级</el-tag>
         </template>
       </el-table-column>
     </el-table>
   </el-card>
 </div>
</template>

<script>
export default {
 data() {
   return {
     // 权限列表
     rightsList: []
  };
},
 created() {
   this.getRightsList();
},
 methods: {
   async getRightsList() {
     //获取权限列表数据
     const { data: res } = await this.$http.get("rights/list");
     if (res.meta.status !== 200) {
       return this.$message.error("获取权限列表失败!");
    }
     this.rightsList = res.data;
  }
}
};
</script>

<style lang='less' scoped>
</style>

2. Vue はどのデザイン パターンを使用しますか?

これはパブリッシュ/サブスクライブ モードに属します。vue では、オブザーバー メソッドと definereactive メソッドの組み合わせを使用してデータを再帰的にハイジャックし、watch クラスを通じて属性をサブスクライブします。Dep クラスは分離に使用されます。データが変更されたとき、データが最初にトリガーされ、メソッドを設定してから、Dep.notiify を呼び出してビューの更新を通知します。

3. vue 操作の実際の dom パフォーマンスのボトルネックについて話す

Vue パフォーマンスのボトルネックとなるいくつかの状況

  1. 一度に大量のデータをレンダリングする場合、データ量が多く複雑な型の場合、Vueがデータを乗っ取ってレンダリングが長くなり、jsの連続実行時間が長すぎます。これにより、ページが長時間操作できなくなり、レンダリング時間が遅すぎ、ユーザーが一度操作してフィードバックを送信するのに時間がかかりすぎます。

    最適化スキーム: この方法を使用するとrequestAnimation、データを分割してバッチでレンダリングすることができます。これにより、js の連続実行時間が短縮され、レンダリング時間が短縮されます。合計の実行時間はレンダリング時間と交換されます。ユーザーは迅速にフィードバックを得ることができ、 js の実行時間が長いためにページと対話できなくなることはありません。

  2. ページ内に大量のデータがある場合、vue の更新はコンポーネントの粒度で更新されるため、変更のごく一部だけでページがフリーズします。現在のコンポーネントで使用されているデータが存在する限り、変更すると、コンポーネントは完全に削除されます。更新すると、多くの時間が無駄になります。

    最適化スキーム: 異なるモジュールを異なるコンポーネントに分割することで、仮想 dom の差分計算時間が長すぎる問題を効果的に軽減できます。たとえば、大量のデータ モジュールを 1 つのコンポーネントだけに配置し、他のコンポーネントを 1 つのコンポーネントに配置します。 vue は更新の粒度としてコンポーネントに基づいており、他のコンポーネントを変更してもテーブルの再差異が発生せず、ページの応答速度が最大数百倍向上します。

  3. 動的スロットのスコープまたは静的スロットの更新

    スロット スコープを使用してこれら 2 つの操作を置き換えると、パフォーマンスも向上します。これは、 use の後插槽作用域、スロットの内容が関数にカプセル化され、親コンポーネントではなく子コンポーネントによってレンダリングされるためです。

4. Vueでのdomの取得、domの操作、domの更新方法

ドムの入手方法は?Vue は dom を取得する特別な方法を提供します。つまり、dom に ref 属性を追加すると、this.$refs.name を通じて dom 要素を取得できます。

domの操作とdomの更新方法は?refs.name を通じて対応する実際の dom を取得し、ネイティブ JS を使用して操作および更新できます。もちろん、vue フレームワーク自体は dom 操作を必要とせず、対応するデータを変更し、命令やテンプレート構文と連携することで簡単に dom の操作や更新を行うことができます。

5. Vue の双方向データ バインディングの原則とは何ですか

Vue2.x では、双方向のデータ バインディングは、パブリッシュ/サブスクライブ モードと組み合わせたデータ ハイジャックによって実現されます。つまり、データとビューが同期され、データが変更され、ビューが変更され、ビューが変更されると、データも変更されます。コア: VUE 双方向データ バインディングに関して、そのコアは Object.defineProperty() メソッドです。

Vue3.x は ES6 構文の Proxy オブジェクトで実装されています。

Object.defineProperty() の欠点:

  1. オブジェクト (Object) のみを監視でき、配列内の変更を監視できません。また、プッシュ、ポップ、シフト、シフト解除、スプライス、ソート、リバースをトリガーすることはできません。

  2. オブジェクトの各プロパティを走査する必要がある

  3. 現在のオブジェクトのプロパティのみをハイジャックできます。深くハイジャックしたい場合は、ネストされたオブジェクトを深くスキャンする必要があります。

 プロキシの利点:

  1. プロキシは、プロパティではなくオブジェクトを直接リッスンできます。

  2. プロキシはアレイの変更を直接監視できます。

  3. プロキシには、apply、ownKeys、deleteProperty、has などに限らず、13 ものインターセプト メソッドがあります。Object.defineProperty にはありません。

  4. プロキシは新しいオブジェクトを返します。目的を達成するために新しいオブジェクトを操作することしかできません。また、Object.defineProperty はオブジェクトのプロパティを走査して直接変更することしかできません。

  5. 新しい標準として、プロキシはブラウザ メーカーが重点を置く継続的なパフォーマンスの最適化の対象となります。これは新しい標準の伝説的なパフォーマンス ボーナスです。

 let arr = [];
 let proxy = new Proxy(arr, {
   get: function(obj, prop){
     return obj[prop];
  },
   set: function(obj, prop, value){
     obj[prop] = value;   //可以被监听到变化
     return true;
  }
});
 setTimeout(()=>{
   proxy.push(1);
}, 2000)

6. mvvm フレームワークとは何ですか

MVVM は、Model-View-ViewModel の短縮形です。これは本質的に MVC (Model-View-Controller) の改良版です。開発プロセスでは、要件の変更や追加により、プロジェクトの複雑性はますます高くなり、コードの量はますます増大し、現時点では MVC では少し難しいことがわかります。特にコントローラー制御層は非常に厚く巨大なため、保守が困難です。

そこで誰かが、Controller のデータ処理部分とロジック処理部分を分離し、それを ViewModel という特別なオブジェクトで管理することを考えました。ViewModel は、フロントエンド開発者の組織によって生成および維持されるビュー データ レイヤーです。この層では、フロントエンド開発者がバックエンドから取得したモデル データを変換および処理し、二次パッケージ化を実行して、ビュー層の期待を満たすビュー データ モデルを生成します。

双方向バインディングの実現により、ViewModel のコンテンツがリアルタイムで View レイヤーに表示されます。これは、フロントエンド開発者が DOM を非効率的かつ面倒に操作してビューを更新する必要がなくなるため、非常に興味深いことです。 MVVM フレームワークはすでに最も汚くて疲れています。すべての部分が完成したら、開発者は ViewModel を処理して保守するだけでよく、更新されたデータ ビューもそれに応じて自動的に更新され、真のデータ駆動型開発を実現します。

7. Vue のトークン ストレージについて話す

フロントエンドとバックエンドが完全に分離されている場合、Vue プロジェクトにおけるトークン検証の一般的な考え方は次のとおりです。

1. 初めてログインするとき、フロントエンドはバックエンドのログインインターフェイスを調整し、ユーザー名とパスワードを送信します。

2. バックエンドはリクエストを受信し、ユーザー名とパスワードを検証し、検証が成功した場合はフロントエンドにトークンを返します。

3. フロントエンドはトークンを取得し、localStorage と vuex にトークンを保存し、ルーティング ページにジャンプします。

4. フロントエンドはルートにジャンプするたびに、localStroage にトークンがあるかどうかを判断し、トークンがない場合はログイン ページにジャンプし、トークンがある場合は対応するルーティング ページにジャンプします。

5. バックエンドインターフェイスを調整するたびに、リクエストヘッダーにトークンを追加する必要があります

6. バックエンドはリクエストヘッダーにトークンがあるかどうかを判断し、トークンがある場合はトークンを取得して検証します。検証が成功した場合はデータを返します。検証が失敗した場合は (例:トークンの有効期限が切れている場合)、401 が返されます。リクエスト ヘッダーにトークンがない場合は、401 が返されます。

7. フロントエンドがステータス コード 401 を取得した場合、トークン情報をクリアし、ログイン ページにジャンプします。

8. nextTick の機能をご存知ですか、その理解、内容、使用方法について話します

vm.message = 'new message' と設定すると、コンポーネントはすぐには再レンダリングされません。キューがフラッシュされると、コンポーネントは次のイベント ループ「ティック」で更新されます。ほとんどの場合、このプロセスを気にする必要はありませんが、更新された DOM 状態に基づいて何かを実行したい場合は、注意が必要になる可能性があります。Vue.js は通常、開発者に「データ駆動型」の考え方を使用し、DOM に直接触れないようにすることを推奨していますが、場合によってはそうしなければならないこともあります。データ変更後に Vue が DOM の更新を完了するのを待つために、データ変更直後に Vue.nextTick(callback) を使用できます。こうすることで、DOM の更新が完了した後にコールバック関数が呼び出されます。例えば:

<div id="example">{
   
   {message}}</div>
var vm = new Vue({
 el: '#example',
 data: {
   message: 'old message'
}
})
vm.message = 'new message' // 更改数据
vm.$el.textContent  // 'old message'
Vue.nextTick(function () {
 vm.$el.textContent  // 'new message'
})

9. nextTick と setTimeout の違い

 まず第一に、Vue は DOM を更新するときに非同期で実行します。つまり、データが変更されても、DOM はすぐには変更されません。では、DOM がいつ変更されるかをどうやって知ることができるのでしょうか? つまり、非同期後のトリガータイミングをどうやって知るか?

 nextTick メソッドを使用できます。このメソッドはソース コード内にあります。最初に Promise.then が利用可能かどうかを監視し、promise を使用して監視します。現在の環境が Promise をサポートしていない場合は、MutationObserver にダウングレードします。MutationObserver がサポートしていない場合は、MutationObserver にダウングレードします。 setImmediate がサポートしていない場合は、setTimeout(fn, 0) を使用します。

 nextTick と setTimeout の違いを要約すると、nextTick はまず Promise、MutationObserver、setImmediate などのテクノロジーを使用して監視しようとし、それらがサポートしていない場合は setTimeout が使用されます。

10. vue で実際の dom を操作する代わりに仮想 dom を使用する理由

当初、JS/JQuery を使用していたときは、DOM を頻繁に操作することが避けられず、DOM の変更によりリフローや再描画がトリガーされ、ページのレンダリングのパフォーマンスが低下していました。では、DOM の操作を軽減するにはどうすればよいでしょうか? このとき、仮想 DOM アプリケーションが誕生しました。仮想 DOM の主な目的は、DOM の頻繁な操作によって引き起こされるリフローと再描画によって引き起こされるパフォーマンスの問題を軽減することです。

仮想 DOM (Virtual Dom) は、本来は最初は JS オブジェクトです。データが変更された場合、実際の DOM は非常に高価なので直接操作しません。この JS オブジェクトを操作すると、大量の JS オブジェクトがトリガーされることはありません。 diff アルゴリズムと組み合わせることで、2 つの仮想 DOM 間の変更部分を見つけることができるため、DOM を頻繁に操作することなく、最小限の量で一度に実際の DOM を更新でき、パフォーマンスが向上しました。大幅に改善されました。

写真

仮想 DOM のもう 1 つの利点は、DOM 以外のプラットフォームにレンダリングして、Weex などのフレームワークで使用される SSR や同型レンダリングなどの高度な機能を実現できることです。

11. Vue はコンポーネント値の転送をどのように実行しますか

親は props を使用して子コンポーネントに値を渡すことができます。

子コンポーネントから親コンポーネントに値を渡すには、カスタム イベントの $emit メソッドを使用できます。

写真

マルチレベルのコンポーネントパス値。provide/injectを使用できます。

写真

vuex 状態管理を使用して、関連のないコンポーネントが値を渡す

写真

12. vueでの親子コミュニケーションについての話

親 -> 子: Prop を通じて子コンポーネントにデータを渡し、子コンポーネントは props 属性を通じてデータを受け取ります。

<blog-post title="Vue を使った私の旅"></blog-post>
Vue.component('blog-post', { 
 props: ['title'], 
 template: '<h3>{ 
  
  { title }}</h3>' // 親コンポーネントの値を取得します
})

子 -> 親: 親コンポーネントはイベントをカスタマイズし、子コンポーネントは $emit を使用して完了します。

<!--サブコンポーネントによって渡されたデータ $event が 0.1 であることを取得します--> 
<blog-post v-on:enlarge-text="postFontSize += $event"></blog-post>
Vue.component('blog-post', { 
props: ['title'], 
template: '<h3 v-on:click="$emit('enlarge-text', 0.1)">{ 
  
  { title }}< /h3>' 
})

写真

写真

13. vue コンポーネントの通信と値の受け渡し方法を実現する方法について話します (2 つの質問は同じ答えであり、質問方法が異なります)

このタイプの質問は、あなたがそれについてもっと知っていることを示すために最初に分類されます。私は最後まで答えられなかった、または聞き逃しました。面接官はあまり気にしません。コンポーネントコミュニケーションの 4 つの主要なカテゴリ: 父と息子、息子
1. props と $emit
について親  
コンポーネントは props を通じて子コンポーネントにデータを渡し、子コンポーネントは $emit を通じて親コンポーネントにデータを渡してイベントをトリガーします
2。 $attrs と $listeners 
3.
中央イベント バス上の 2 つのメソッド これは親コンポーネントと子コンポーネント間のデータ転送を扱いますが、2 つのコンポーネントが親子ではない場合はどうなるでしょうか。この場合、中央イベント バスのアプローチを使用できます。新しい Vue イベント バス オブジェクトを作成し、bus.$emit を通じてイベントをトリガーし、bus.$on を通じてトリガーされたイベントをリッスンします。
4. 提供と注入
親コンポーネントのプロバイダーを通じて変数が提供され、子コンポーネントの inject を通じて変数が注入されます。サブコンポーネントがどれほど深くても、inject が呼び出される限り、プロバイダー内のデータを注入できます。現在の親コンポーネントの prop 属性からデータを取得することだけに限定されるのではなく、親コンポーネントのライフサイクル内であれば、子コンポーネントはそれを呼び出すことができます。
5. 
v-model 親コンポーネントが v-model を通じて子コンポーネントに値を渡すと、値の prop 属性が自動的に渡され、this.$emit('input', val) を通じて v-model バインディングが自動的に変更されます。 ) 子コンポーネントの値
6、$parent と $children 
7、boradcast とdispatch










8. Vuex はコンポーネント間のデータ対話を処理します。ビジネス ロジックが複雑で、多くのコンポーネントがいくつかの共通データを同時に処理する必要がある場合、現時点では上記の方法はプロジェクトのメンテナンスに役立たない可能性があります。vuex のアプローチは次のとおりです。これらの公開データ データが抽出されると、他のコンポーネントがこの公開データを読み書きできるようになり、分離の目的が達成されます。

14. Vue における Key 値の役割について話す

この可能なキーの機能については、まずキーが必要ないことを示します. コードを書かなくても実行できますが、追加して使用できる場所を示すことをお勧めします.
キャッシュ
一般つまり、キーが v-for と組み合わせて使用​​されている限り、

キーは Vue の vnode にマークされた一意の ID です。このキーを使用すると、diff 操作がより正確かつ高速になります。diff
アルゴリズムのプロセスで、最初に古いノードと新しいノードが識別されます。先頭から末尾までの相互比較で、一致しない場合は、新しいノードのキーが古いノードと比較され、差分アルゴリズムを明確に説明できます。 diff プロセスは次のように要約できます。oldCh と newCh にはそれぞれ、先頭と末尾の 2 つの変数
StartIdx と EndIdx があり、それらの 2 つの変数が相互に比較され、合計 4 つの比較方法があります。4 つの比較のどれも一致しない場合、キーが設定されていれば、そのキーが比較に使用されます。比較プロセス中、変数は中央に傾きます。StartIdx>EndIdx が oldCh と newCh の少なくとも 1 つが指定されたことを示すと、トラバースすると、比較が終了します。これらの 4 つの比較方法は、ヘッド、テール、古いテール、新しいヘッド、古いヘッド、新しいテールです。

正確: キーが追加されない場合、Vue はノードを再利用することを選択します (Vue のインプレース更新戦略)。前のノードの状態が残る 保持すると一連のバグが発生する 高速:キーの一意性をMapデータ構造で最大限に活用できる トラバーサル検索の時間計算量O(n)と比較, Map の計算量は O(1) だけです
講義が終わったら、私なりの意見を書き加えておきます
ID などの主キーを使用することをお勧めします  

15. vue の仮想 dom および diff アルゴリズムについて話す

仮想 DOM は実際には JavaScript オブジェクト (VNode ノード) に基づいたツリーであり、オブジェクト プロパティを使用してノードを記述します。実際、それは実際の DOM を抽象化したものにすぎません。最後に、このツリーは一連の操作を通じて実際の DOM にマッピングできます。

次に、実際の DOM を仮想 DOM にマッピングする例を示します: 
<ul id='list'> 
        <li class='item'>Item 1 </li> 
        <li class='item'>アイテム 2</li> 
        <li class='item'>アイテム 3</li> 
      </ul> 
       
var element = { 
      tagName: 'ul', // ノードタグname 
      props: { // DOM プロパティ、キーと値のペアを保存するためにオブジェクトを使用します
          id: 'list' 
      }, 
      Children: [ // このノードの子ノード
        {tagName: 'li', props: {class: 'item' }、子: [ "Item 1"]}、
        {tagName: 'li'、props: {class: 'item'}、子:
   
補足として、仮想 DOM の利点は
クロスプラットフォームの利点があります。
仮想 DOM は JavaScript オブジェクトに基づいており、実際のプラットフォーム環境に依存しないため、ブラウザ プラットフォーム、Weex、Node、等 

ネイティブ DOM の操作は遅く、js は効率的に実行されます。DOM 比較操作を JS レイヤーに配置して、効率を向上させることができます。
DOM 操作の実行速度は Javascript に比べてはるかに遅いため、大量の DOM 操作を Javascript に転送し、パッチ適用アルゴリズムを使用して本当に更新する必要があるノードを計算し、DOM 操作を最小限に抑えます。これによりパフォーマンスが大幅に向上します。

仮想 DOM は本質的に、JS と DOM の間のキャッシュです。これは、CPU とハードディスクにたとえることができます。ハードディスクは非常に遅いため、それらの間にキャッシュを追加し、DOM は非常に遅いため、JS と DOM の間にキャッシュを追加します。CPU(JS)はメモリ(仮想DOM)上でのみ動作し、最後に変更内容をハードディスク(DOM)に書き込むことで

描画パフォーマンスを向上させ
、合理的かつ効率的にビューを更新します。

diff アルゴリズム
vdom は純粋な JS オブジェクトであるため、その操作は非常に効率的ですが、vdom の変更は最終的に DOM 操作に変換されるため、効率的な DOM 操作を実現するには、一連の効率的な仮想 DOM diff アルゴリズムが必要です。 diff アルゴリズム

には次のような手順が含まれます: 

JavaScript オブジェクト構造を使用して DOM ツリーの構造を表現し、次にこのツリーを使用して実際の DOM ツリーを構築し、状態が変化したときにそれを
ドキュメント

オブジェクトを再構築します。木。次に、新しいツリーを使用して古いツリーと比較 (diff) し、2 つのツリー間の差異を記録します。
2で記録した差分を、1で構築した実際のDOMツリー(パッチ)に適用すると、ビューが更新されます 差分アルゴリズムとは、ツリーを
階層ごとに検索して横断するのではなく、同じ階層のツリーノードを比較することです。したがって、時間計算量はわずか O(n) であり、非常に効率的なアルゴリズムです。

仮想 DOM の実装プロセス

16. vue3.0 について学んだことがありますか? vue3.0 は良いと思いますか? vue3.0 の何がそんなに良いのですか?

この種の質問はオープンです。もっと発言するのは正しいことです。相違点や新しい知識点について話すことができます。  

たとえば、一般的に使用される API は特に使いやすいです

  1. ref、toRefs、toRef、isRef

  • ref は、応答性の高い変数と迅速な DOM アクセスを定義するために使用されます。

  • 基本的な構文:const a = ref(1) // {value:1}

  • 基本的な使用法: 通常、文字列、数値、ブール ベースのデータ型を定義するために使用され、外部パフォーマンスには .value によって均一にアクセスされます。

  • 補足: ref は、DOM オブジェクトやコンポーネント インスタンス オブジェクトにアクセスして DOM 操作を行うこともできます。

  • toRef と toRefs は、オブジェクト変数を応答変数に変換するために使用されます。

  • 基本構文: const msg = toRef(obj, key)// obj[key] を応答可能にする

  • 基本構文: const { msg } = toRefs(obj)// obj 全体を応答可能にします。

  • unref は変数の値を返します

  • 基本構文: const x = unref(x)// x が ref 変数の場合は x.value を返し、x が ref 変数でない場合は x を直接返します。

  • isRef は、変数が ref 応答変数であるかどうかを判断するために使用されます。

  • 基本的な構文:const bol = isRef(x)

function useUpdBoxStyle() { 
 const el = ref(null) 
 const updateStyle = color => { 
   el.value.style.color = color 
} 
 return [el, updateStyle] 
}
  1. 浅い参照、トリガー参照

  • ShallowRef はパフォーマンスの最適化に使用され、オブジェクトの最初のレイヤーのみをプロキシします。

  • 基本的な構文:const obj = shallowRef({a:1,b:{c:{d:{e:2}}}})

  • triggerRef は、これらのshallowRef変数を手動でトリガーしてビューを更新するために使用されます。

  • 基本構文: triggerRef(obj)// obj.value.bcd が変更されると、triggerRef(obj) によってビューが強制的に更新されます。

  • CustomRef カスタム参照。ref 変数を get/set に分割します。

  • 基本的な構文:customRef((track, trigger) =>({get,set})

function useObj() { 
 const obj = { a: 1, b: { c: { d: 2 }}} 
 const obj1 = ref(obj) 
 const obj2 =shallowRef(obj) 
 // console.log('obj1', obj1 ) 
 // console.log('obj2', obj2) 
 const changeObj = (obj, newD) => { 
   // obj1.value.bcd = 100 
   obj.value.bcd = newD 
   triggerRef(obj) 
} 
 return [[obj1, obj2]、changeObj] 
}
  1. リアクティブ、読み取り専用

  • reactive は、reactive 変数 (参照データ型) を定義するために使用されます。

  • 基本的な構文:const arr = reactive([]) // {value: []}

  • refとreactiveの関係は何ですか? ref の背後では、reactive を使用して実装されます。

  • ShallowReactive はパフォーマンスの最適化に使用され、オブジェクトの最初のレイヤーのみをプロキシします。

  • 基本構文: const c = shallowReactive({a:{b:{c:100}}})// このオブジェクトの最初のレイヤーのみをプロキシします

  • readonly リアクティブ変数を「読み取り専用」に変更し、変更された場合に警告を報告します。

  • 基本的な構文:const user = readonly({name:1,age:2})

  • isReadonly は変数が読み取り専用かどうかを判断するために使用され、ブール値を返します。

  • 基本的な構文:const bol = isReadonly(x)

  • isProxy は、変数が応答するかどうかを判断するために使用され、ブール値を返します。

  • 基本的な構文:const bol = isProxy(x)

  • isReactive は、変数がリアクティブ変数かどうかを判断するために使用され、ブール値を返します。

  • 基本的な構文:const bol = isReactive(x)

function useUser() { 
 const user = readonly(reactive({name:'list',age:30})) 
 console.log('user', user) 
 // setTimeout(()=>user.age=40, 2000 ) 
 const x = 1 
 const y = readonly({a:1,b:{c:3}}) 
 console.log('被プロキシ拦截过', isProxy(user), isProxy(x), isProxy(yb) )
 ユーザーを返す
}
  1. toRaw、markRaw

  • toRaw は、リアクティブ変数の生の値を返すために使用されます。

  • 基本構文: const a3 = toRow(reactive(a1))// a1===a3 は true

  • markRaw は、通常の変数を「プロキシ不可」としてマークするために使用されます。

  • 基本構文: const b2 = markRaw(b1)// b2 はリアクティブにはできません

function useRaw() { 
 const a1 = { title: 100 } 
 const a2 = reactive(a1) 
 const a3 = toRaw(a2) 
 console.log('toRow(a2)===a1', a3===a1)
 コンソール。 log('a2===a1', a2===a1) 
 return [a1,a2,a3] 
}
  1. 計算、監視、監視効果

  • computed は、応答変数を再計算するために使用され、依存する応答変数が変更されたときに再計算されます。

  • 基本的な構文: const c = computed(()=>c1.value*c2.value)// 読み取り専用

  • 基本構文: const c = computed({get:()=>c1.value*c2.value,set:(newVal)=>c1.value=newVal})// 書き込み可能および読み取り可能

  • watch は応答変数の変更を監視するために使用され、コンポーネントはそれを初期化しません

  • 基本構文: const stop = watch(x, (new,old)=>{})// stop() を呼び出してリスニングを停止します。

  • 基本的な構文:const stop = watch([x,y], ([newX,newY],[oldX,oldY])=>{})

  • watchEffect は応答変数の変化を監視するために使用され、コンポーネントの初期化が実行されます。

  • 基本的な構文:const stop = watchEffect(()=>ajax({cate,page,size}))

import デフォルト関数 useWatchComputed() { 
const c1 = ref(10) 
const c2 = ref(20) 
const c3 = computed(()=>c1.value*c2.value) // 読み取り専用
// 読み取りおよび書き込み可能
const c4 = computed({ 
  get: ()=>c1.value*c2.value, 
  set: (newVal)=>{ 
    c1.value = parseInt(newVal) / c2.value 
  } 
}) 
const stop1 = watch(c4, ( newC4, oldC4)=>console.log('c4変更', newC4, oldC4)) 
const stop2 = watch([c1,c2], ([newC1,newC2],[oldC1,oldC2])=>{ 
  console.log(' [c1,c2] 新しい値:', [newC1, newC2]) 
  console.log('[c1,c2] 古い値:', [oldC1, oldC2]) 
}) 
const stop3 = watchEffect(()= >{コンソール.log('監視効果', c1.value, c2.value)}) 
const update = (c,v) => c.値 = v
return [[c1,c2,c3,c4],[stop1,stop2,stop3,update]] 
}

2:明るい話題とも言える

  1. パフォーマンスは vue2.x より 1.2 ~ 2 倍高速です

  2. ツリーシェーキング、オンデマンドコンパイルをサポート、vue2.x より小さい

  3. コンポジションAPIをサポート

  4. TS のサポートの向上

  5. より高度なグループ

3. さらに間違いなくパフォーマンス

1. diff アルゴリズムの方が高速です

Vue2.0 では各ノードをグローバルに比較する必要があり、ノードの変更が見つかった場合はノードを更新します。

Vue3.0 は仮想 dom を作成しており、DOM の内容が変更されるかどうか、誰がフラグを持っているかに応じて静的マークを追加します。誰と比較するか。

2.静電気の改善

vue2 では要素が更新に参加しているかどうかに関係なく、毎回再作成されてからレンダリングされますが、vue3 では更新に参加していない要素については静的に改善され、一度だけ作成され、直接再利用できますレンダリング中

3. イベントリスニングキャッシュ

デフォルトでは、onclick は動的にバインドされているため、その変更は毎回追跡されますが、同じ関数であるため、変更を追跡する必要はなく、キャッシュして再利用するだけです。

前に静的マーク 8 が追加され、クリック イベントは動的属性とみなされ、差分アルゴリズムが比較されますが、イベント リスナー キャッシュの後に静的マークはなく、キャッシュが再利用されます。

17. v モデルを理解したことがありますか? 原理は何ですか?

このような原理的な問題を理解していませんなどと言ってはいけません。  

使い方について話しましょう

v-model は本質的に糖鎖構文であり、値 + 入力メソッドの糖鎖構文とみなすことができます。モデルの prop 属性とイベント イベントを通じてカスタマイズできます。

2. v-model は vue の双方向バインディング コマンドで、ページ上のコントロール入力の値を関連するバインディングのデータ属性に同期的に更新でき、また、ページ上の入力コントロールの値も更新できますdata。バインディング属性を更新しています。

そして詳細

Vue の双方向バインディングは、データ ハイジャックとパブリッシャー/サブスクライバー モードを組み合わせることによって実現されます。では、データ ハイジャックとは何でしょうか? vue はどのようにしてデータハイジャックを実行しますか? 率直に言うと、Object.defineProperty() を通じてオブジェクト プロパティのセッター操作とゲッター操作をハイジャックし、データが変更されたときにやりたいことを実行することです。

データの双方向バインディングを実現するには、まずデータをハイジャックして監視する必要があることはすでにわかっているため、すべての属性を監視するためにリスナー オブザーバーをセットアップする必要があります。属性が変更された場合は、更新する必要があるかどうかをサブスクライバー Watcher に通知する必要があります。サブスクライバが多数あるため、これらのサブスクライバを特別に収集し、リスナー Observer とサブスクライバ Watcher の間で一元管理するメッセージ サブスクライバ Dep が必要です。次に、コマンド パーサー Compile も必要です。これは、各ノード要素をスキャンして解析し、関連するコマンド (v-model、v-on など) をサブスクライバー Watcher に初期化し、テンプレート データまたはバインディングの対応する関数を置き換えます。ウォッチャーは、対応する属性の変更を受け取ると、対応する更新関数を実行してビューを更新します。次に、データの双方向バインディングを実現するために次の 3 つの手順を実行します。

1. すべての属性をハイジャックして監視し、変更があった場合にサブスクライバーに通知するために使用されるリスナー オブザーバーを実装します。

2. サブスクライバー ウォッチャーを実装します。各ウォッチャーは更新関数にバインドされており、ウォッチャーはプロパティ変更通知を受信し、対応する関数を実行してビューを更新できます。

3. 各ノードの関連命令 (v-model、v-on、およびその他の命令) をスキャンして解析できるパーサー Compile を実装します。ノードに v-model、v-on およびその他の命令がある場合、パーサー Compile は初期化します。ノードのテンプレート データをビューに表示できるようにし、対応するサブスクライバー (ウォッチャー) を初期化します。

3: 最後に、vue 2.0 では Object.defineProperty を使用し、vue 3.0 では新しい Proxy を使用して各プロパティを監視し、オブジェクト全体を監視します。

18. VUE コンポーネントはどのように iframe と通信するのか

このような質問は実際にはそれほど詳しくないので、面接官は質問の意味を理解していない可能性がありますが、面接官の質問を理解する方法を学ぶ必要があります。

分からない場合は、vue のコンポーネント通信は v を取得するための iframe ページについて話しているとだけ言ってください。

vue コンポーネントには iframe が埋め込まれています。今度は、H5 の新しい機能である PostMessage を使用して、クロスドメインの問題を解決して、iframe 内の親コンポーネントの情報を取得したいと考えています。

postMessage の使用には、次の 2 つの API が含まれています。

onMessage: メッセージ監視

postMessage: メッセージが送信されました

コードと例

<div class="mapbox">
    <iframe name="map" src="http://localhost:8083/setposition.html?add='add'"></iframe>
</div>
clearMap(){
    let map = document.getElementsByName("map")[0].contentWindow
    map.postMessage("clearMap","*")
  }
iframe内:

window.addEventListener('message', function (evt) {
 
  if (evt.data == 'clearMap'){
      clearMap()
  }
  //event.data获取传过来的数据
});

19. VUE のカスタム コマンドを使用したことがありますか? カスタムコマンドのメソッドとは何ですか

この種の質問も同様です。最初に、v-for v-if v-model v-show などのよく使用される命令をいくつか答えてください。命令はグローバルとローカルに分かれています。

次に、カスタム ディレクティブに応答して

ディレクティブを使用してディレクティブをカスタマイズします。カスタム ディレクティブは、グローバル ディレクティブとローカル ディレクティブに分かれています。カスタム ディレクティブにもいくつかのフック関数があります。一般的に使用されるのは、bind と update です。bind と update が同じ動作をトリガーする場合、他のフックは考慮されません. 省略可能。式では複数のフィルターを使用できます。フィルターはパイプ文字「|」で区切る必要があります。実行順序は左から右です。  

20. データを変更するとき、Vue のコンポーネントは非同期で再レンダリングされますか? それとも同期で再レンダリングされますか?

通常、非同期と同期に関する一般的な質問は、データ要求の同期と非同期の問題を指すため、この質問は非常に興味深いです。

ここにコンポーネントを追加してデータを変更します。これはすべての人向けの例です

<body>
  <div id="app">
      <div id="main">{
   
   {num}}</div>
      <button @click="add">更新</button>
  </div>
</body>
<script>
  new Vue({
      el:"#app",
      data:{
          num:10
      },
      methods:{
          add(){
              this.num++;
              console.log(this.num)//11
              console.log(document.getElementById("main").innerHTML);//10
         
          }
      }
  })
</script>

これで説明がつく  

データの更新は同期的ですが、ビューの更新は非同期です

この問題を解決するには、$nextTick を使用してビューの非同期更新の問題を解決する必要があります。

21. .sync 修飾子の機能は次のとおりです。

まず第一に、.sync を見るとき、これがデコレータであることを知る必要があります。同様のデコレータには .stop .prevent などもあります。

実際、この修飾子は、vue が親コンポーネントから渡された動的値を変更するためにサブコンポーネントをカプセル化する文法糖です。これにより、親コンポーネントのメソッドを記述する必要がなくなりますが、サブコンポーネントが発行するときに更新が追加されます。

場合によっては、プロップを「双方向バインド」する必要があるかもしれません。残念ながら、真の双方向バインディングでは、子コンポーネントが親コンポーネントを変更する可能性があり、親コンポーネントと子コンポーネントの両方に明らかな変更源がないため、メンテナンスの問題が生じます。

コードの説明

// ここで、親コンポーネントはタイトル値を子コンポーネントに渡す必要があります
<template>
  <div>  
      <t-title :title.sync="fatherTitle"></t-title>
  </div>
</template>
<script>
import tTitle from './blocks/list';
export default {
  name: 'test1',
  components: { tTitle },
  data() {
      return {
          fatherTitle: '父组件给的标题'
      };
  },
}
</script>
// サブアセンブリ
<template>
  <div>
      <h3>{
   
   { title }}</h3>
      <button @click="changeTitle">改变</button>
  </div>
</template>
<script>
export default {
  props:{
      title: {type: String, default: '默认值11'}
  },
  methods: {
      changeTitle() {
          this.$emit("update:title", "子组件要改自己的标题");
      }
  }
};
</script>

ここで重要なのは、emit のパラメーターは「update」+「:」+「変更するプロパティ」として記述する必要があることです。

This.$emit("カスタム メソッド") は以前に使用されていました

22. Vueマルチコンポーネントネスト通信方法

この問題は実際にはコンポーネント通信に属しており、一般的なコンポーネント通信には、親から子、息子から父、息子から息子、レベル間の通信が含まれます。

この複数のコンポーネントのネストされたコミュニケーションは、実際にはレベルを超えて質問するもう 1 つの方法です

マルチコンポーネント通信

方法 1: プロップをレイヤーごとに渡す

方法 2: 依存関係の注入 Provide ステートメント inject accept

方法 3: public Bus = new Vue() Bus.$on を使用して、bus.$emit() 呼び出しを宣言する

方法 4: vuex グローバル状態管理を使用する

23. vue make css はどのようにして現在のコンポーネントでのみ有効になりますか

現在のコンポーネント <style> は <stylescoped> として記述でき、スコープを追加できます。

このスタイルには通常、lang lang があり、scss スタイラスなどを少なくすることができます。
スコープがなければ、グローバル スタイルです。

24. Vue のキープライブを使用したことがありますか? 役割は何ですか?

  1. 使われたことがない

  2. この機能を使用すると、コンポーネントが切り替わったときに、ラップされたコンポーネントの状態を保存して、コンポーネントが破壊されたり、複数のレンダリングを防止したりすることができます。

25. キープアライブ、これを追加するとライフ サイクルが通常より長くなりますか? キープアライブはキャッシュされていますが、元に戻りたい場合は、どのライフ サイクルで実装する新しい属性を追加しますか?

 通常のコンポーネントよりもライフサイクル フック関数が 2 つ増えます (アクティブ化と非アクティブ化)。ラップされたkeep-aliveコンポーネントは切り替え時に破棄されず、メモリにキャッシュされて非アクティブ化されたフック関数が実行され、アクティブ化されたフック関数は再度レンダリング後に実行されます。再度表示コンポーネントに戻ると、アクティブ化された状態で実行できます。

26. キープアライブに関連するライフサイクルについて話す

 通常のコンポーネントよりもライフサイクル フック関数が 2 つ増えます (アクティブ化と非アクティブ化)。ラップされたkeep-aliveコンポーネントは切り替え時に破棄されず、メモリにキャッシュされて非アクティブ化されたフック関数が実行され、アクティブ化されたフック関数は再度レンダリング後に実行されます。

27. Vue でプロジェクトを作成する手順は何ですか

  1. 使用される公式の cli スキャフォールディング。バージョンが 3.0 より前の場合は、使用します。npm init

  2. 3.0 以降の cli バージョンの使用vue create

  3. vite を使用してプロジェクトを直接ビルドできます。コマンドは ですnpm init vite@latest。プロンプトに従い、ステップごとに操作するだけです。

28. Vueでのrefバインディングの使い方

 コンポーネントやタグに ref 属性を追加すると、グローバル API を使用して$refsJS コード内の dom 要素やコンポーネントを取得し、そのメソッドやプロパティを直接操作できるようになります。

29. vue ナビゲーション ガードと jq ナビゲーション インターセプターの導入

 Vue のナビゲーション ガードは一般的にルーティング ナビゲーション ガードを指し、ページがジャンプするときにフック関数を実行するために使用されます。

 最も使用されるナビゲーション ガードはグローバル ガード router.beforeEach で、主にユーザーのログイン ステータスを確認するために使用されます。3 つのパラメータを to、from、next で受け取ります。

  • to: これから入ろうとするルートオブジェクト

  • from: 現在のナビゲーションから出発するルート

  • 次: コールバック関数。このメソッドを呼び出す必要があります。呼び出さないと、ルートは続行されません。

    jq ナビゲーション インターセプターについて聞いたことはありません。一般に、jQuery の役割は dom 要素を操作することです。jQuery の中心的な機能は要素セレクターです。前述したように、ナビゲーターはサードパーティの jQuery プラグインのクラスである可能性があります。または、ネットワーク リクエスト インターセプト。ネットワーク リクエスト インターセプトの場合、jQuery がリクエストを開始すると、グローバル Ajax リクエスト プラグインをカプセル化できます。これは、ajaxSetup を設定することで実現できます。

 // こちらを参照 https://www.runoob.com/jquery/ajax-ajaxsetup.html 
 $.ajaxSetup({ 
   // url: 'demo_ajax_load.txt', 
   beforeSend() { 
     // リクエストを開始する前に実行
  }, 
   complete( ) { 
     // すべてのリクエストが成功した後に実行
  }, 
});

30. vue でよく使用されるコマンド

  1. フォーム入力用の v-model ディレクティブ。

  2. イベントバインディング用の v-on ディレクティブ。

  3. v-bind ディレクティブは、値を動的にバインドして変数に渡すために使用されます。

  4. v-once コマンドは、イベントは 1 回のみ使用でき、何度クリックしても、一度実行された後は再度実行されません。

  5. v-html コマンドは、span のコンテンツを rawHtml の属性値に置き換え、HTML コードとして直接解析します。

  6. v-for コマンドは、データの走査と配置のために HTML タグと組み合わせて使用​​されます。

  7. v-if命令は条件判定に使用され、domを直接操作します。

  8. v-elseコマンドは条件を判定するコマンドで、条件が成立しない場合に実行するv-ifコマンドと併用します。

  9. v-show コマンドは、true と false に応じて要素の表示状態を切り替えます。

31. vueには数種類のスロットがあり、スロットの役割

 3 つのタイプ: デフォルト スロット、名前付きスロット、スコープ付きスロット

  • デフォルトのスロット

    デフォルトのスロットは <slot> を参照し、<slot> の機能はプレースホルダーと似ています。

    // グローバル サブコンポーネントを定義します
    Vue.component('child', { 
     template: '<div><slot></slot></div>', 
    }); 
    
    var vm = new Vue({ 
     el: '#root ' , 
    });
    <!--参照子コンポーネント--> 
    <div id="root"> 
     <child> 
       <span>私はプレースホルダーです</span> 
     </child> 
    </div>

    上記の子コンポーネントで定義されたスロットは、span タグで置き換えられます。サブコンポーネントでスロットが定義されていない場合、span タグは直接無視され、サブコンポーネントで定義できるスロットは 1 つだけです。

  • 名前付きスロット

    name属性を設定することで表示場所を指定できます

    <base-layout> コンポーネントを定義します。

    <div class="container">
     <header>
       <slot name="header"></slot>
     </header>
     <main>
       <slot></slot>
     </main>
     <footer>
       <slot name="footer"></slot>
     </footer>
    </div>
    <base-layout>
     <template v-slot:header>
       <h1>Here might be a page title</h1>
     </template>
    
     <p>A paragraph for the main content.</p>
     <p>And another one.</p>
    
     <template v-slot:footer>
       <p>Here's some contact info</p>
     </template>
    </base-layout>
  • スコープ付きスロット

    親コンポーネントはスロット ラベルを置き換えますが、コンテンツは子コンポーネントによって提供されます。

    <body>
     <div id="root">
       <child>
         <!--定义一个插槽,该插槽必须放在template标签内-->
         <template slot-scope="props">
           <li>{
         
         {props.value}}</li>
         </template>
       </child>
       <!--!--定义不同的渲染方式-->
       <child>
         <!--slot-scope="props"作用是使props指向子组件中定义的<slot>-->
         <template slot-scope="props">
           <h1>{
         
         {props.value}}</h1>
         </template>
       </child>
     </div>
    </body>
    <script>
     //定义一个全局子组件
     Vue.component('child', {
       data: function () {
         return {
           list: [1, 2, 3, 4],
        };
      },
       template:
         '<div><ul><slot v-for="value in list" :value=value></slot></ul></div>',
    });
    
     var vm = new Vue({
       el: '#root',
    });
    </script>

32. vueでのプラ​​グインの使い方

 直接インストールし、インポートして使用します。Vueでもjsでも、jsであればどのプラグインも同様に使用でき、対応するノードにインポートしてバインドするか、対応するノードを操作するだけです。

33. Vue コンポーネントの遅延ロードと画像の遅延ロード

コンポーネントの遅延読み込み

  1. ルーティング プラグインと組み合わせて使用​​する場合は、インポート メソッドを使用して次のことを実現します。

// 最初のステップは、 import によってインポートされたファイルに注釈を付けることです
// import About from '../components/About.vue'; 
// 2 番目のステップは、アロー関数の形式でコンポーネントを非同期的に導入することです const Routes 
= [ 
{ 
   path: '/about', 
   Component: () => import( /* webpackChunkName: 'about' */ '../components/About.vue' ) 
} 
] 
```` 
2. インポート時のコールバック関数の使い方

```jsなどのコンポーネントのインポート
// コンポーネントの遅延読み込み
const IconList = () => import('components/base/icon-list');

デフォルトのエクスポート {
 コンポーネント: { 
   IconList, 
 }, 
}; 
````

画像の遅延読み込み

つまり、ページを読み込むときに、ページ上の画像が多すぎる場合は、プレースホルダーを使用してその領域にない画像を置き換え、現在表示する必要がある画像のみを読み込むことができます。スクロールバーの位置を監視し、表示領域に画像ラベルが表示されたら、画像のパスを実際のパスにリセットし、画像アドレスを表示します。実際の開発では画像遅延読み込みプラグインを直接利用して実現するのが一般的です。もう 1 つの解決策は、ページ スケルトン画面効果を使用することであり、これもプレースホルダー表示と同様であり、データがロードされるときにプレースホルダー表示のコンテンツを置き換えます。

34. Vue を使用してコンポーネントをカプセル化したことがありますか? コンポーネントは何ですか? どのように実装されているか教えてください

たとえば、バックグラウンド管理では、サイド ナビゲーション コンポーネント、プロジェクトで一般的に使用される echarts チャート (折れ線グラフ、ヒストグラムなど) のカプセル化など、多くのモジュールが再利用されることがよくあります。

パッケージ化コンポーネントは再利用性を考慮する必要があります。

  • 予約済みスロット スロット、複数の呼び出し サブコンポーネントのビュー構造が異なる場合は、サブコンポーネント テンプレートでスロットを予約する必要があります (単一スロット、名前付きスロット、スコープ スロット)

  • データ転送を考慮して、親コンポーネントから渡されたデータを受け取る props コンポーネントを定義し、一方向のデータフローに注意してください。props は直接変更できません。$emit カスタム イベント、親コンポーネントの変更

  • ビジネス ロジックはサブコンポーネントで処理しないでください。サブコンポーネントが異なる親コンポーネントで呼び出される場合、ビジネス処理コードは異なります。サブコンポーネントでビジネスを直接処理しないように注意してください。サブコンポーネントはカスタム イベントを $emit し、データを親コンポーネントに渡す必要があります。親コンポーネント業務を担当します。

35. 管理操作や vuex の理解について話す

Vuex は、プロジェクト内の複数のコンポーネントの公開状態を管理する集中管理方式を採用する Vue の状態管理プラグインです。

Vuex にはウェアハウスの概念があり、コンポーネントの共通の状態をウェアハウスの状態属性に保存します。状態は読み取り専用で、コンポーネントは使用のみ可能で、直接変更することはできません。変更は、これの利点は、データ変更時にソースの追跡が容易であり、複数のコンポーネントによりデータを直接変更することがないため、コンポーネント間でデータが相互に影響を与えることになります。ウェアハウス内に状態データがあり、取得するにはデータ インターフェイスをリクエストする必要があります。vuex はアクション モジュールを設計し、そのアクションでモジュール内で非同期リクエストを送信し、データを取得した後、状態を変更するミューテーションを送信します。状態が変化すると、コンポーネントは自動的に更新され、コンポーネント内のミューテーションのコミットまたはディスパッチ アクションによって状態を変更できます。

具体的なワークフローは以下の通りです

写真

36. Vuex のワークフローについて話す

vuex のウェアハウスには、状態、ミューテーション、アクション、ゲッター、モジュールの 5 つのモジュールがあります。

vuex ウェアハウスの状態でコンポーネントのパブリック状態を定義します。状態は読み取り専用で、直接変更できません。状態を変更するには、ウェアハウス内のミューテーションを動員する必要があります。ゲッターは、vuex で計算されたプロパティとして理解できます。 vuex の状態がコンポーネントで使用される場合、元の値を直接使用するのではなく、新しい値を導出する必要があり、コンポーネント内でゲッターを定義して取得できます。依存関係の状態が変化すると、ゲッターは新しい値を取得するために再計算します。同時に、アクションで非同期リクエストを送信できます。データを取得した後、ミューテーションをコミットして状態を割り当てます。

具体的なコードは次のとおりです。

倉庫コード

const store = new Vuex.Store({
   state: {
       items: [] // 定义一个公共的购物车数据
  },
   getters: {
       // 可以基于已有的state 派生新的状态
       selectedItems (state) {
           // 过滤购物车中未选中的商品
           return state.items.filter(item => item.selected)
      }
  },
   mutations: {
       // 定义mutation来修改state
       INIT_ITEMS(state, items){
           state.items = items
      }
  },
   actions: {
       // action可以发送异步请求,得到数据后commit mutation将请求结果传入
       FETCH_ITEMS({commit}, params = {}){
           // 调用封装好的 接口函数
           fetchItem(params).then(res => {
               if(res.data.code === 200) {
                   commit('INIT_ITEMS', res.data.data)
              }
          })
      }
  }
})

コンポーネントで vuex を使用する

// 获取state
this.$store.state.items // 直接获取
{
   computed: {
...mapState(['items']) // 助手函数获取
  }
}
// 获取getters
this.$store.getters.selectedItems // 直接获取
{
   computed: {
       ...mapGetters(['selectedItems']) // 助手函数获取
  }
}
// 组件中提交action
this.$store.dispatch('FETCH_ITEMS', {token: 'xxx'})
{
   methods: {
       ...mapActions(['FETCH_ITEMS']) // 助手函数 直接调用this.FETCH_ITEMS(params)触发
  }
}
// 组件中也可以直接commit mutation
this.$store.commit('INIT_ITEMS'[,参数])
{
   methods:{
       ...mapMutations(['INIT_ITEMS']) // 助手函数 直接调用this.INIT_ITEMS(参数)
  }
}

37. vuex プロジェクトでどのように使用しますか? 動作原理は何ですか?

原則として:

小規模および中規模のプロジェクトでは、コンポーネントの公開状態があまりない場合、コードの複雑さが増すため、vuex の使用はお勧めできません。コンポーネントと通信したい場合は、イベント バスを直接渡すことができます。中規模および大規模なプロジェクトでは、複数のコンポーネントの公開状態 ほとんどの場合、vuex を使用することをお勧めします

vuex の具体的なワークフローは次のとおりです。

ウェアハウス状態でパブリック状態を定義し、アクションで非同期リクエストを送信し、データを取得した後にミューテーションを呼び出して状態に割り当てます。状態はコンポーネントで使用されます。また、アクションをディスパッチしてミューテーションをトリガーすることもできます。コンポーネントを使用して状態を変更し、ビューを更新します。

具体的なコードは次のとおりです。

倉庫コード

const store = new Vuex.Store({
   state: {
       items: [] // 定义一个公共的购物车数据
  },
   getters: {
       // 可以基于已有的state 派生新的状态
       selectedItems (state) {
           // 过滤购物车中未选中的商品
           return state.items.filter(item => item.selected)
      }
  },
   mutations: {
       // 定义mutation来修改state
       INIT_ITEMS(state, items){
           state.items = items
      }
  },
   actions: {
       // action可以发送异步请求,得到数据后commit mutation将请求结果传入
       FETCH_ITEMS({commit}, params = {}){
           // 调用封装好的 接口函数
           fetchItem(params).then(res => {
               if(res.data.code === 200) {
                   commit('INIT_ITEMS', res.data.data)
              }
          })
      }
  }
})

コンポーネントで vuex を使用する

// 获取state
this.$store.state.items // 直接获取
{
   computed: {
...mapState(['items']) // 助手函数获取
  }
}
// 获取getters
this.$store.getters.selectedItems // 直接获取
{
   computed: {
       ...mapGetters(['selectedItems']) // 助手函数获取
  }
}
// 组件中提交action
this.$store.dispatch('FETCH_ITEMS', {token: 'xxx'})
{
   methods: {
       ...mapActions(['FETCH_ITEMS']) // 助手函数 直接调用this.FETCH_ITEMS(params)触发
  }
}
// 组件中也可以直接commit mutation
this.$store.commit('INIT_ITEMS'[,参数])
{
   methods:{
       ...mapMutations(['INIT_ITEMS']) // 助手函数 直接调用this.INIT_ITEMS(参数)
  }
}

38.非同期を処理するには Vuex のどこに記述する必要がありますか

ウェアハウスのアクションで非同期処理を定義する必要がある

アクションは突然変異に似ていますが、違いは次のとおりです。

  • アクションは、状態を直接変更するのではなく、突然変異を送信します。

  • アクションには任意の非同期操作を含めることができます。

アクションで非同期リクエストを送信し、成功後に結果を渡すミューテーションをトリガーし、ミューテーションの状態に値を割り当てることができます。

const store = new Vuex.Store({
   state: {
       items: [] // 定义一个公共的购物车数据
  },
   mutations: {
       // 定义mutation来修改state
       INIT_ITEMS(state, items){
           state.items = items
      }
  },
   actions: {
       // action可以发送异步请求,得到数据后commit mutation将请求结果传入
       FETCH_ITEMS({commit}, params = {}){
           // 调用封装好的 接口函数
           fetchItem(params).then(res => {
               if(res.data.code === 200) {
                   commit('INIT_ITEMS', res.data.data)
              }
          })
      }
  }
})

39. vuex についてのあなたの理解について話してください

Vuex は、Vue 用に特別に設計された状態管理ツールで、親子コンポーネントおよび非親子コンポーネント間のグローバル コンポーネント通信に使用できます。アプリケーションの状態はストアの中央に配置されます。状態を変更するには、コミットを実行する必要があります。状態を同期的に変更するには、ミューテーションを送信する必要があります。非同期的には、最初にアクションを渡し、次にミューテーションを渡す必要があります。

合計 5 つのモジュールがあります- 状態ストレージ状態- ゲッターは計算されたプロパティのようなもので、ゲッターの戻り値は依存関係に従ってキャッシュされ、依存値が変更された場合にのみ再計算されます。状態内のデータに対して何らかの処理を行うことができます。ミューテーションが Vuex ストアの状態を変更する唯一の方法は、store.commit を通じてミューテーション モジュールに送信されるミューテーションを送信することです。アクションアクションは非同期に変更するメソッドです。状態内の状態 (store.dispatch 経由) ミューテーション モジュールに送信し、コミットを送信して状態内の状態を変更する- モジュールVuex では、ストアをモジュールに分割できます。各モジュールには独自の状態、突然変異、アクション、ゲッター、さらにはネストされたサブモジュールがあり、上から下まで同じ方法で分割されます。

40.vuex - モジュール内の状態のデータを変更する方法、および他のモジュールからデータを取得する方法

単一の状態ツリーを使用するため、アプリケーションのすべての状態が比較的大きなオブジェクトに集中します。アプリケーションが非常に複雑になると、ストア オブジェクトが非常に肥大化する可能性があります。

上記の問題を解決するために、Vuex ではストアをモジュールに分割することができます。各モジュールには独自の状態、ミューテーション、アクション、ゲッター、さらにはネストされたサブモジュールがあり、上から下まで同じ方法で分割されています。

vuex をモジュール化した後、別のモジュールの状態を変更する必要があります。このモジュール内でゲッターを定義できます。具体的なコードは次のとおりです。

// 模块a
const modulea = {
   namespaced: true,
   state: {
       num: 10
  },
   mutations: {
       ADD_NUM(state, n) {
           state.num += n
      }
  }
}
// 模块b
const moduleb = {
   namespaced: true,
   state: {
       num: 10
  },
   getters: {
       // 在这里拿到 模块a numstate
     moduleaNum (state, getters, rootState, rootGetters) {
         // 模块下的getter有四个参数分别是当前模块的state,当前模块的getters,以及根state个根getters可以通过rootState获取其他模块的state
         return rootState.modulea.num
         
    }  
  },
   mutations: {
       ADD_NUM(state, n) {
           state.num += n
      }
  }
}

41. vuex のステータスとステータスの変更方法

vuex の状態は、ウェアハウスの state 属性に保存されます。状態は読み取り専用で、直接変更できません。変更するには、mutation を呼び出す必要があります。

const store = new Vuex.Store({
   state: {
       num: 10
  },
   mutations: {
       ADD_NUM (state, n) {
           state.num += n
      }
  }
})
// 在组件中直接出发mutaion
this.$store.commit('ADD_NUM', 10)
// 或者助手函数 提交 mutation
{
   methods: {
       ...mapMutations(['ADD_NUM'])
  }
}
// 直接调用即可
this.ADD_NUM(10)

42. プロジェクト内のどこで vuex を使用するか、vuex の適用シナリオ

原則として:

小規模および中規模のプロジェクトでは、コンポーネントの公開状態があまりない場合、コードの複雑さが増すため、vuex の使用はお勧めできません。コンポーネントと通信したい場合は、イベント バスを直接渡すことができます。中規模および大規模なプロジェクトでは、複数のコンポーネントの公開状態 ほとんどの場合、vuex を使用することをお勧めします

プロジェクトでは、電子商取引 Web サイトのショッピング カート データなど、複数のコンポーネントの公開状態を vuex に保存できます。バックグラウンド管理ロール認証における異なるロールのサイドバーデータと、異なるロールでアクセス可能なルーティングデータをvuexに格納することができ、そのデータが保存されます。

おすすめ

転載: blog.csdn.net/shi15926lei/article/details/132220284