mitt |
|
它们的具体用法可以参考我的这篇文章盘点Vue2和Vue3的10种组件通信方式(值得收藏) - 掘金 (juejin.cn)
除了上面的传参方式你也可以回答Vuex和Pinia,前提你了解这两个状态管理器,因为你说了大概率下个问题就会问你Vuex和Pinia
vuex
面试问到这个问题的时候,不要上来就开始说什么state
,mutation
...。你要先阐述Vuex干嘛用的,什么时候需要用Vuex。
回答
Vuex是Vue中的全局状态管理框架,它可以管理应用的所有组件的状态。并不是每个项目都需要引入Vuex的,当我们的项目有很多个页面,并且这些页面共享着多个数据状态,此时我们可以引入Vuex。
Vuex有三个核心的概念,state
,mutations
,actions
,其中state
为存放数据的地方,mutations
中的函数作用则是用来修改state
,actions
中一般是用了处理一些异步操作的函数。
Vuex除了上面三个概念还有getters
,moudles
,getters
就像Vue中的计算属性computed
一样用来描述依赖响应式状态state中的复杂逻辑。moudles
则是可以将store分割成模块(module),每个模块都拥有自己的state
,mutations
,actions
等,在大型应用中经常用到
场景:当我们异步获取结果并赋值给state的时候,比如数据请求,我们可以在actions
中进行数据请求,拿到结果通过它的dispatch
方法调用mutations
中修改state
的函数,从而将结果赋值给了state
pinia
这个现在问的好像不多,从我最近面试来看只有我提到了才会问一下,但是以后问的肯定会越来越多。关于pinia问的一般是它和Vuex的区别,确切的说应该是它和Vuex4之间的区别
回答
pinia
其实就是Vuex5,它和Vuex的主要区别有以下几点
Pinia使用更简单,更符合开发者的开发习惯
pinia
中没有了mutations
,状态state
的修改可以直接进行修改,或者在actions
中修改,或者使用它的$patch
方法进行修改
pinia
中没有了modules
,如果想使用多个store,直接使用defineStore
定义多个store传入不同的id即可
更好的TS支持,不需要创建自定义的复杂包装器来支持TS
vue自定义指令
vue 官方提供了v-text、v-for、v-model、v-if 等常用的指令。除此之外vue 还允许开发者自定义指令。面试经常会问什么是自定义指令?你用自定义指令做过哪些功能?
回答1:什么是自定义指令?
自定义指令包含局部指令和全局指令,在模板中使用指令前必须先使用directives
选项注册。局部指令指在某个组件中注册,而全局则是将指令注册到全局,通常在main.js中注册。
自定义指令由一个包含类似组件生命周期钩子的对象来定义。它的生命周期钩子包含created
,beforeMount
,mounted
,beforeUpdate
,updated
,beforeUnmount
,unmounted
,
常用的钩子为mounted
和 updated
,它接受el
,binding
等参数.binding
参数的值一般包含绑定到这个元素上的信息,比如下面这个指令
<div v-example:foo.bar="baz">
它的binding会是这个对象
{
arg: 'foo',
modifiers: { bar: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
回答2:你用自定义指令做过哪些功能?
数据埋点,通过绑定自定义事件传入点击当前元素需要埋点的事件名,在指令中监听当前元素的点击事件后调用后台接口将事件名传入
权限控制,通过绑定自定义事件传入控制当前元素的权限字段,在指令中获取到当前元素根据权限字段来控制该元素的状态(显示,隐藏等)
...
keep-alive
官网描述
<KeepAlive>
は、複数のコンポーネント間を動的に切り替えるときに、削除されたコンポーネント インスタンスをキャッシュする機能を持つ組み込みコンポーネントです。
回答
通常、コンポーネントを切り替えると、前のコンポーネントは破棄されます。また、 < を使用すると、前のコンポーネントが破棄されます。 KeepAlive>
ラップすると、コンポーネントはキャッシュされ、コンポーネントが再度表示されたときに前の状態が保持されます。
-
keep-alive
2 つの属性 include
と exclude
を受け取ります。これらはそれぞれ、キャッシュする必要があるコンポーネントと、キャッシュする必要があるコンポーネントを表します。キャッシュは必要ありません。コンポーネント名の配列、文字列、または正規表現を受け取ります。動的コンポーネント component
またはルート router-view
## を使用するときに使用できます。
#keep-alive は、キャッシュ インスタンスの最大数を示す
max 属性も受け取ります。この数を超えると、アクセスされていないキャッシュ インスタンスは、最も長い時間は破壊されます。
keep-alive には、
activated と
deactivated、
activated という 2 つのライフ サイクルがあります。フックは、初めてマウントされるとき、またはキャッシュから再挿入されるたびに呼び出されます。
deactivatedコンポーネントが DOM から削除されるか、コンポーネントがアンインストールされるとフックが呼び出されます
vue2 Mixin-Mixin
vue3 では Mixin という概念がなくなったので、今後聞かれる機会はどんどん減っていきますが、それでも聞かれる頻度は非常に高いです。一般的に、その概念、利点と欠点について学び、場合によっては、そのライフサイクルの実行順序や親コンポーネントについても質問します。
vue 公式 Web サイトの説明:
Mixin は、Vue コンポーネントで再利用可能な機能を配布する非常に柔軟な方法を提供します。ミックスインには、任意のコンポーネント オプションを含めることができます。コンポーネントがミックスインを使用する場合、ミックスインのオプションはすべてコンポーネント自体のオプションに「混合」されます。
回答1.Mixinの機能は、コンポーネントの公開ロジックを抽出することです。どのコンポーネントを使用する必要がある場合、抽出したものを直接ミックスします。コンポーネントのすぐ内側にパーツを入れる
2.
Mixin のライフ サイクルは、親コンポーネントのライフ サイクルより前に実行されます。
Mixin のプロパティまたはメソッドが親コンポーネントと競合する場合、親コンポーネントが使用されます。
2. 利点: コードの冗長性を削減し、ロジックの再利用性を向上させることができます。
3. 欠点: 名前の競合が発生しやすく、ソースを追跡するのが難しく、後のトラブルシューティングが不便です。
vue 応答性の原則
この質問は非常に頻繁に寄せられます。この質問は、私が経験したほぼすべての面接で聞かれており、Vue では冒頭の質問です。 以下は、vue2 を例として挙げた、私自身の理解した答えです。参考にしてください。
##vue の応答原理は、- Object.defineProperty に基づいています。
この API は、データをハイジャックし、パブリッシャー/サブスクライバー モデルと組み合わせて実装するために使用されます。
は、最初に - Object.defineProperty で
get## を使用します。 #vue 内のデータのすべての属性にアクセスしてハイジャックする関数。これには、データ内のより深い属性のハイジャックが含まれ、ハイジャック メソッドを再帰的に呼び出す必要があります。これは、
Observer クラス
各属性をハイジャックした後、複数のサブスクライバがこの属性にバインドされます watcher- 。この
watcher には、ビューを更新する関数
update が含まれています。
watcher- と属性の対応関係やビューとの接続は、テンプレートの
Compileクラスをコンパイルすることで実現されます。
Compile は dom オブジェクト全体を取得し、要素の子ノードを走査して vue の data 属性を取得します。その後、その属性に
watcher を直接追加して、それにいくつかの更新を加えます。 Method.
各属性 watcher- の複数のサブスクライバが、対応する配列に追加されます。ここでは、
Deps クラスを使用します。実装すると、
watcher を初期化するときに、
Deps の
addSub メソッドが呼び出され、
watcher# に対応するこのクラスの Subs# が追加されます。
#配列内
データ内のプロパティが変更されると、
Object.defineProperty の - set
関数がトリガーされます。プロパティの Deps
クラスの notify
関数が呼び出され、Subs
配列内のサブスクライバー watcher
を走査し、その関数を呼び出します。 update
ビューの更新をトリガーするには
Object.defineProperty と proxy の違い
一般に、次のことができます。応答性の原則について質問した後に質問する 2 つの違い
Answer
##Object.defineProperty
はプロパティをプロキシすることしかできません,Proxy- プロキシはオブジェクトです。
新しいプロパティがオブジェクトに追加され、
Proxy
はそれを監視できますが、 Object.defineProperty- は監視できません。
Object.defineProperty
的代理行为是在破坏原对象的基础上实现的,Proxy 则不会破坏原对象,只是在原对象上覆盖了一层。
数组新增修改,Proxy
可以监听到,Object.defineProperty
不能。
Proxy
不兼容IE11
及以下
vue3内置组件
vue3新增了两个内置组件分别是Teleport
和Suspense
。
可以称之为传送门,作用将其插槽内容渲染到 DOM 中的另一个位置,接收两个参数to(要去的位置)和disabled(是否留在原位置)。接收比如下面代码
<teleport to="#popup">
<video src="./my-movie.mp4">
</teleport>
video将会被传送到id为popup的元素下。
<Suspense>
组件用于协调对组件树中嵌套的异步依赖的处理。
它一般用于包裹多个异步组件处理多个异步组件加载前与完成后的统一状态
<Suspense>
组件有两个插槽:#default
和 #fallback
,在初始渲染时,<Suspense>
将在内存中渲染其默认的插槽内容。如果在这个过程中遇到任何异步依赖,则会进入挂起状态等待异步组件加载完毕。在挂起状态期间,展示的是 #fallback
插槽内容
nextTick及原理
关于nextTick会问到它的用法,然后是它的原理,然后还可能问到JS的时间循环机制。
问题1:vue中的nextTick是干什么用的?
这个其实比较简单,用过都知道它是干嘛的,vue官方的解释是:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
这是什么意思呢,其实vue中修改data不会立刻触发dom更新;而是把需要更新的Watcher加入到queueWatcher队列中,然后在合适的时机在nextTick中调用这些Watcher的更新函数进行dom更新,所以在data刚被修改的时候,我们是获取不到更新后的dom的,这时候便需要调用nextTick函数在它的回调函数中获取到变化后的dom
问题2:nextTick原理
nextTick原理是借助浏览器事件循环来完成的,因为每次事件循环之间都有一次视图渲染,nextTick尽量在视图渲染之前完成dom更新,所以nextTick优先使用的是promise(微任务)实现
每次执行nextTick时会将传入的回调函数放入一个队列中(callbacks数组),然后当在本次事件循环的同步代码执行完毕后开启一个微任务(promise或者MutationObserver)去依次执行这个callbacks中的回调函数。
但是当浏览器不支持promise的时候在vue2中会进行进行降级处理,依次使用setImmediate
、setTimeout
开启一个宏任务执行callbacks
当一个data数据更新时对应的watcher便会调用一次nextTick,将它对应的dom更新操作作为回调函数放入callbacks中,所以当我们想获取这个data更新后的dom需要在其值变化后也调用nextTick将回调函数传入排在上个更新dom的回调函数后面,所以我们可以在这个nextTick的回调函数中获取到更新后的data
问题3:js事件循环机制
不属于vue,后面文章再介绍
vue虚拟dom,diff算法
这题在工作中有用吗是???答案是没有用,但是在面试中有用啊,所以我们要会回答?
问题1:什么是虚拟dom?
简单来说就是一个描述dom结构的js对象
问题2:为什么要用虚拟dom?
问题3:说一下diff算法
diff アルゴリズムの本質は、ノードを可能な限り再利用することを目的として、2 つのオブジェクト間の違いを見つけることです。 vueでは、状態が変化した際に、変更後の仮想DOMと変更前の仮想DOMの差分を計算するアルゴリズムです。
具体的な実装については、数文では明確に説明できません。Vue の両端差分アルゴリズムについて話しましょう - Nuggets (juejin.cn)
という記事をお勧めします。 結論
上記の質問は、基本的に情報を参考にし、私自身の理解を組み合わせてまとめたものですので、多少の間違いや不十分な点があることは避けられません。ぜひご指摘ください。ありがとうございます。 (学習ビデオ共有: Web フロントエンド開発、基本プログラミング ビデオ)