ホームページ  >  記事  >  20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

青灯夜游
青灯夜游転載
2022-05-18 11:46:154705ブラウズ

この記事では、基本的な知識を整理し、Vue の知識の蓄えを強化するために、Vue の典型的な面接の質問 20 個を要約して共有します (ソース コード レベルの詳細な説明付き)。見て!

01-Vue コンポーネント間の通信方法とは

Vue はコンポーネントベースの開発フレームワークであるため、コンポーネント間のデータ通信は vue アプリケーションにとって非常に重要です。 この質問は主に、全員の基本的な Vue スキルと Vue の基本 API の使用習熟度をテストします。 Provide/inject/$attrs などの他の境界知識は、インタビュアーの知識の広さを示しています。


#パラメータをコンポーネントに渡すさまざまな方法

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)


##アイデア分析:

    #私たちが知っているすべての方法の概要
  • コンポーネントの関係に応じた使用シナリオの説明

回答サンプル: 1. コンポーネント通信には 8 つの一般的な方法があります:


props
  • $emit/
  • $on
  • $children
  • /$parent$attrs/
  • $listeners
  • ref
  • $root
  • eventbus
  • vuex
vue3
# のいくつかの放棄された API に注意してください# #https://v3-migration.vuejs.org/breaking-changes/children.html

https://v3-migration.vuejs.org/breaking-changes/listeners-removed.html

https://v3-migration.vuejs.org/breaking-changes/events-api.html#overview

2. コンポーネントの通信については、以下に基づいて議論するのが最も明確です。コンポーネント間の関係 Valid

親子コンポーネント
  • props
      /
    • $emit/ $parent/ ref/$attrs
    兄弟コンポーネント
  • #$parent
      /
    • $root/eventbus/vuex
    #レベル間の関係
  • eventbus
      /
    • vuex/provide inject
02-v-if と v-for ではどちらが優先されますか?

分析:

この質問は常識をテストするもので、ドキュメントv2

で詳しく説明されています。 |

v3; も、プロジェクトで頻繁に遭遇する優れた練習用の質問であり、面接官の API の知識と応用能力を示すことができます。


アイデア分析:

最初に結論を述べます
  • これはなぜですか、詳細を教えてください
  • どのようなシナリオでこの問題が発生する可能性があるか、およびその対処方法
  • 概要、レベルを上げる

回答例:

##実際には

すべきですv-for と v-if は使用しないでください。
  • vue2
  • では、
  • v-for の方が v-if よりも優先されます。

    これらをまとめると、出力レンダリング関数から、最初にループが実行されてから条件が判断されることがわかります。たとえリスト内の要素のごく一部をレンダリングするだけであっても、再レンダリングされるたびにリスト全体を走査し、Waste を比較します。さらに、vue3 ではまったく逆であることに注意してください。v-if は v-for## よりも高い優先順位を持っています。 # したがって、v-if が実行されるとき、呼び出される変数はまだ存在しないため、例外が発生します。 これを行う原因となる状況は、通常 2 つあります。

  • リスト内の項目を
  • フィルタリングするには

    (例:

    v-for="user in users" v-if="user.isActive"
      ) 。この時点で、計算されたプロパティ (
    • activeUsers

      など) を定義し、フィルター処理されたリスト (users.filter(u=>u.isActive) など) を返すようにします。 非表示にする必要があるリストのレンダリングを 回避するには (例

      v-for="user in users" v-if="ShouldShowUsers"## #)。このとき、
    • v-if
    • をコンテナ要素 (

      ulol など) に移動するか、template## のレイヤーで囲みます。 #。 ドキュメントには、v-if

    • v-for
    を同時に使用しないことが明記されています。同じ要素の時間
  • ですが、これは明らかに重要な注意事項です。
  • ソース コードのコード生成部分では、v-if と v-for のどちらが最初に処理されるかが明確にわかります。vue2 と vue3 の順序はまったく逆なので、異なる症状ですが、どうしても一緒に書くことはできません。


理由を理解してください:

テストを実行します。test.html が同じレベルの場合、レンダリング関数はは次のとおりです:

ƒ anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},_l((items),function(item){return (item.isActive)?_c('div',{key:item.id},[_v("\n      "+_s(item.name)+"\n    ")]):_e()}),0)}
}

テストを受けて、test-v3.html

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)


ソース コードで答えを見つけてください。

v2: https://github1s.com/vuejs/vue/blob/HEAD/src/compiler/codegen/index.js#L65-L66

v3:https://github1s.com/ vuejs/core/blob /HEAD/packages/compiler-core/src/codegen.ts#L586-L587


03-Vue のライフ サイクルと各ステージの動作を簡単に説明します

vue の基本知識をテストするための必須の質問。

アイデア

  • コンセプトを与える

  • さまざまな側面を列挙するライフサイクルのステージ

  • プロセス全体の説明

  • 実践と組み合わせる

  • 拡張: vue3 の変更点


回答例

#1. 各 Vue コンポーネント インスタンスは一連の処理を経ます。作成後の初期化手順には、データの観察、テンプレートのコンパイル、DOM へのインスタンスのマウント、データ変更時の DOM の更新が必要です。このプロセス中にライフサイクル フックと呼ばれる関数が実行され、ユーザーが特定の段階で独自のコードを追加する機会が与えられます。

2. Vue のライフ サイクルは、作成前後、読み込み前後、更新前後、破棄前後、合計 8 つのステージに分けることができます。いくつかの特別なシナリオのライフサイクル。デバッグとサーバーサイド レンダリング用の 3 つの新しいシーンが vue3 に追加されました。

#ライフサイクル v2ライフサイクル v3説明 beforeCreatebeforeCreateコンポーネント インスタンスの作成時createdcreatedコンポーネント インスタンス すでに完全に作成されていますcreatedbeforeMountbeforeMount コンポーネントがマウントされる前mountedmountedコンポーネントがインスタンスにマウントされた後beforeUpdatebeforeUpdateコンポーネント データが変更されるとき、 update#updatedupdatedデータ更新後のデータデータbeforeDestroyコンポーネント インスタンスが破棄される前destroyedコンポーネント インスタンスはその後破棄されます
beforeUnmount
unmounted
Lifecycle v2activated# #deactivatederrorCaptured#-
Lifecycle v3 Description
activated keep-alive キャッシュされたコンポーネントがアクティブ化されたとき
deactivated keep-alive キャッシュされたコンポーネントが非アクティブ化されたときに呼び出されます
errorCaptured 子孫からのメッセージをキャプチャ
renderTracked #-
#####-#########renderTriggered#########デバッグ フック、リアクティブな依存関係がトリガーされたときに呼び出されます########## ##-#########serverPrefetch#########ssr のみ、コンポーネント インスタンスがレンダリングされる前に呼び出されますサーバー############

3、Vue生命周期流程图:

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

4、结合实践:

beforeCreate:通常用于插件开发中执行一些初始化任务

created:组件初始化完毕,可以访问各种数据,获取接口数据等

mounted:dom已创建,可用于获取访问数据和dom元素;访问子组件等。

beforeUpdate:此时view层还未更新,可用于获取更新前各种状态

updated:完成view层的更新,更新后,所有状态已是最新

beforeunmount:实例被销毁前调用,可用于一些定时器或订阅的取消

unmounted:销毁一个实例。可清理它与其它实例的连接,解绑它的全部指令及事件监听器


可能的追问

  • setup和created谁先执行?

  • setup中为什么没有beforeCreate和created?


知其所以然

vue3中生命周期的派发时刻:

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/componentOptions.ts#L554-L555

vue2中声明周期的派发时刻:

https://github1s.com/vuejs/vue/blob/HEAD/src/core/instance/init.js#L55-L56


04-能说一说双向绑定使用和原理吗?

题目分析:

双向绑定是vue的特色之一,开发中必然会用到的知识点,然而此题还问了实现原理,升级为深度考查。


思路分析:

  • 给出双绑定义

  • 双绑带来的好处

  • 在哪使用双绑

  • 使用方式、使用细节、vue3变化

  • 原理实现描述


回答范例:

  • vue中双向绑定是一个指令v-model,可以绑定一个响应式数据到视图,同时视图中变化能改变该值。

  • v-model是语法糖,默认情况下相当于:value@input。使用v-model可以减少大量繁琐的事件处理代码,提高开发效率。

  • 通常在表单项上使用v-model,还可以在自定义组件上使用,表示某个值的输入和输出控制。

  • 通过<input v-model="xxx">的方式将xxx的值绑定到表单元素value上;对于checkbox,可以使用true-value和false-value指定特殊的值,对于radio可以使用value指定特殊的值;对于select可以通过options元素的value设置特殊的值;还可以结合.lazy,.number,.trim对v-mode的行为做进一步限定;v-model用在自定义组件上时又会有很大不同,vue3中它类似于sync修饰符,最终展开的结果是modelValue属性和update:modelValue事件;vue3中我们甚至可以用参数形式指定多个不同的绑定,例如v-model:foo和v-model:bar,非常强大!

  • v-model是一个指令,它的神奇魔法实际上是vue的编译器完成的。我做过测试,包含v-model的模板,转换为渲染函数之后,实际上还是是value属性的绑定以及input事件监听,事件回调函数中会做相应变量更新操作。编译器根据表单元素的不同会展开不同的DOM属性和事件对,比如text类型的input和textarea会展开为value和input事件;checkbox和radio类型的input会展开为checked和change事件;select用value作为属性,用change作为事件。


可能的追问:

  • v-modelsync修饰符有什么区别

  • 自定义组件使用v-model如果想要改变事件名或者属性名应该怎么做


知其所以然:

测试代码,test.html

观察输出的渲染函数:

// <input type="text" v-model="foo">
_c(&#39;input&#39;, { 
  directives: [{ name: "model", rawName: "v-model", value: (foo), expression: "foo" }], 
  attrs: { "type": "text" }, 
  domProps: { "value": (foo) }, 
  on: { 
    "input": function ($event) { 
      if ($event.target.composing) return; 
      foo = $event.target.value 
    } 
  } 
})
// <input type="checkbox" v-model="bar">
_c(&#39;input&#39;, { 
  directives: [{ name: "model", rawName: "v-model", value: (bar), expression: "bar" }], 
  attrs: { "type": "checkbox" }, 
  domProps: { 
    "checked": Array.isArray(bar) ? _i(bar, null) > -1 : (bar) 
  }, 
  on: { 
    "change": function ($event) { 
      var $$a = bar, $$el = $event.target, $$c = $$el.checked ? (true) : (false); 
      if (Array.isArray($$a)) { 
        var $$v = null, $$i = _i($$a, $$v); 
        if ($$el.checked) { $$i < 0 && (bar = $$a.concat([$$v])) } 
        else { 
          $$i > -1 && (bar = $$a.slice(0, $$i).concat($$a.slice($$i + 1))) } 
      } else { 
        bar = $$c 
      } 
    } 
  } 
})
// <select v-model="baz">
//     <option value="vue">vue</option>
//     <option value="react">react</option>
// </select>
_c(&#39;select&#39;, { 
  directives: [{ name: "model", rawName: "v-model", value: (baz), expression: "baz" }], 
  on: { 
    "change": function ($event) { 
      var $$selectedVal = Array.prototype.filter.call(
        $event.target.options, 
        function (o) { return o.selected }
      ).map(
        function (o) { 
          var val = "_value" in o ? o._value : o.value; 
          return val 
        }
      ); 
      baz = $event.target.multiple ? $$selectedVal : $$selectedVal[0] 
    } 
  } 
}, [
  _c(&#39;option&#39;, { attrs: { "value": "vue" } }, [_v("vue")]), _v(" "), 
  _c(&#39;option&#39;, { attrs: { "value": "react" } }, [_v("react")])
])

05-Vue中如何扩展一个组件

此题属于实践题,考察大家对vue常用api使用熟练度,答题时不仅要列出这些解决方案,同时最好说出他们异同。

答题思路:

  • 按照逻辑扩展和内容扩展来列举,

    • 逻辑扩展有:mixins、extends、composition api;

    • 内容扩展有slots;

  • 分别说出他们使用方法、场景差异和问题。

  • 作为扩展,还可以说说vue3中新引入的composition api带来的变化


回答范例:

  • 常见的组件扩展方法有:mixins,slots,extends等

  • 混入mixins是分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

    // 复用代码:它是一个配置对象,选项和组件里面一样
    const mymixin = {
       methods: {
          dosomething(){}
       }
    }
    // 全局混入:将混入对象传入
    Vue.mixin(mymixin)
    
    // 局部混入:做数组项设置到mixins选项,仅作用于当前组件
    const Comp = {
       mixins: [mymixin]
    }
  • 插槽主要用于vue组件中的内容分发,也可以用于组件扩展。

    子组件Child

    <div>
      <slot>这个内容会被父组件传递的内容替换</slot>
    </div>

    父组件Parent

    <div>
       <Child>来自老爹的内容</Child>
    </div>

    如果要精确分发到不同位置可以使用具名插槽,如果要使用子组件中的数据可以使用作用域插槽。

  • 组件选项中还有一个不太常用的选项extends,也可以起到扩展组件的目的

    // 扩展对象
    const myextends = {
       methods: {
          dosomething(){}
       }
    }
    // 组件扩展:做数组项设置到extends选项,仅作用于当前组件
    // 跟混入的不同是它只能扩展单个对象
    // 另外如果和混入发生冲突,该选项优先级较高,优先起作用
    const Comp = {
       extends: myextends
    }
  • 混入的数据和方法不能明确判断来源且可能和当前组件内变量产生命名冲突,vue3中引入的composition api,可以很好解决这些问题,利用独立出来的响应式模块可以很方便的编写独立逻辑并提供响应式的数据,然后在setup选项中组合使用,增强代码的可读性和维护性。例如:

    // 复用逻辑1
    function useXX() {}
    // 复用逻辑2
    function useYY() {}
    // 逻辑组合
    const Comp = {
       setup() {
          const {xx} = useXX()
          const {yy} = useYY()
          return {xx, yy}
       }
    }

可能的追问

Vue.extend方法你用过吗?它能用来做组件扩展吗?


知其所以然

mixins原理:

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/apiCreateApp.ts#L232-L233

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/componentOptions.ts#L545

slots原理:

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/componentSlots.ts#L129-L130

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1373-L1374

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/helpers/renderSlot.ts#L23-L24


06-子组件可以直接改变父组件的数据么,说明原因

分析

这是一个实践知识点,组件化开发过程中有个单项数据流原则,不在子组件中修改父组件是个常识问题。

参考文档:https://staging.vuejs.org/guide/components/props.html#one-way-data-flow


思路

  • 讲讲单项数据流原则,表明为何不能这么做

  • 举几个常见场景的例子说说解决方案

  • 结合实践讲讲如果需要修改父组件状态应该如何做


回答范例

  • 所有的 prop 都使得其父子之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。另外,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器控制台中发出警告。

    const props = defineProps([&#39;foo&#39;])
    // ❌ 下面行为会被警告, props是只读的!
    props.foo = &#39;bar&#39;
  • 实际开发过程中有两个场景会想要修改一个属性:

    • **这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。**在这种情况下,最好定义一个本地的 data,并将这个 prop 用作其初始值:

      const props = defineProps([&#39;initialCounter&#39;])
      const counter = ref(props.initialCounter)
    • **这个 prop 以一种原始的值传入且需要进行转换。**在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

      const props = defineProps([&#39;size&#39;])
      // prop变化,计算属性自动更新
      const normalizedSize = computed(() => props.size.trim().toLowerCase())
  • 实践中如果确实想要改变父组件属性应该emit一个事件让父组件去做这个变更。注意虽然我们不能直接修改一个传入的对象或者数组类型的prop,但是我们还是能够直接改内嵌的对象或属性。


07-Vue要做权限管理该怎么做?控制到按钮级别的权限怎么做?

分析

综合实践题目,实际开发中经常需要面临权限管理的需求,考查实际应用能力。

权限管理一般需求是两个:页面权限和按钮权限,从这两个方面论述即可。

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)


思路

  • 权限管理需求分析:页面和按钮权限

  • 权限管理的实现方案:分后端方案和前端方案阐述

  • 说说各自的优缺点


回答范例

  • 权限管理一般需求是页面权限按钮权限的管理

  • 具体实现的时候分后端和前端两种方案:

    前端方案会把所有路由信息在前端配置,通过路由守卫要求用户登录,用户登录后根据角色过滤出路由表。比如我会配置一个asyncRoutes数组,需要认证的页面在其路由的meta中添加一个roles字段,等获取用户角色之后取两者的交集,若结果不为空则说明可以访问。此过滤过程结束,剩下的路由就是该用户能访问的页面,最后通过router.addRoutes(accessRoutes)方式动态添加路由即可。

    后端方案会把所有页面路由信息存在数据库中,用户登录的时候根据其角色查询得到其能访问的所有页面路由信息返回给前端,前端再通过addRoutes动态添加路由信息

    按钮权限的控制通常会实现一个指令,例如v-permission将按钮要求角色通过值传给v-permission指令,在指令的moutned钩子中可以判断当前用户角色和按钮是否存在交集,有则保留按钮,无则移除按钮。

  • 纯前端方案的优点是实现简单,不需要额外权限管理页面,但是维护起来问题比较大,有新的页面和角色需求就要修改前端代码重新打包部署;服务端方案就不存在这个问题,通过专门的角色和权限管理页面,配置页面和按钮权限信息到数据库,应用每次登陆时获取的都是最新的路由信息,可谓一劳永逸!


知其所以然

路由守卫

https://github1s.com/PanJiaChen/vue-element-admin/blob/HEAD/src/permission.js#L13-L14

路由生成

https://github1s.com/PanJiaChen/vue-element-admin/blob/HEAD/src/store/modules/permission.js#L50-L51

动态追加路由

https://github1s.com/PanJiaChen/vue-element-admin/blob/HEAD/src/permission.js#L43-L44


可能的追问

  • 类似Tabs这类组件能不能使用v-permission指令实现按钮权限控制?

    <el-tabs> 
      <el-tab-pane label="⽤户管理" name="first">⽤户管理</el-tab-pane> 
    	<el-tab-pane label="⻆⾊管理" name="third">⻆⾊管理</el-tab-pane>
    </el-tabs>
  • 服务端返回的路由信息如何添加到路由器中?

    // 前端组件名和组件映射表
    const map = {
      //xx: require(&#39;@/views/xx.vue&#39;).default // 同步的⽅式
      xx: () => import(&#39;@/views/xx.vue&#39;) // 异步的⽅式
    }
    // 服务端返回的asyncRoutes
    const asyncRoutes = [
      { path: &#39;/xx&#39;, component: &#39;xx&#39;,... }
    ]
    // 遍历asyncRoutes,将component替换为map[component]
    function mapComponent(asyncRoutes) {
      asyncRoutes.forEach(route => {
        route.component = map[route.component];
        if(route.children) {
          route.children.map(child => mapComponent(child))
        }
    	})
    }
    mapComponent(asyncRoutes)

08 - 说一说你对vue响应式理解?

分析

这是一道必问题目,但能回答到位的比较少。如果只是看看一些网文,通常没什么底气,经不住面试官推敲,但像我们这样即看过源码还造过轮子的,回答这个问题就会比较有底气啦。

答题思路:

  • 啥是响应式?

  • 为什么vue需要响应式?

  • 它能给我们带来什么好处?

  • vue的响应式是怎么实现的?有哪些优缺点?

  • vue3中的响应式的新变化


回答范例:

  • 所谓数据响应式就是能够使数据变化可以被检测并对这种变化做出响应的机制

  • MVVM框架中要解决的一个核心问题是连接数据层和视图层,通过数据驱动应用,数据变化,视图更新,要做到这点的就需要对数据做响应式处理,这样一旦数据发生变化就可以立即做出更新处理。

  • vue を例に挙げると、データ応答性と仮想 DOM およびパッチ アルゴリズムにより、開発者は面倒な DOM 操作にまったく対処する必要がなく、データを操作してビジネスに気を配るだけで済み、大幅に改善されます。開発効率を高め、開発難易度を軽減します。

  • vue2 のデータ応答性はデータ型に応じて処理が異なります。 オブジェクトの場合は、Object.defineProperty() を使用してデータ インターセプトを定義します。データがアクセスまたは変更されると、それを感知して応答します。それが配列の場合、配列オブジェクト プロトタイプの 7 つの変更メソッド を上書きして、これらのメソッドが追加の更新通知を提供して応答できるようにします。このメカニズムはデータの応答性の問題をうまく解決しますが、実際の使用にはいくつかの欠点もあります: たとえば、初期化中の再帰的トラバーサルによりパフォーマンスの低下が発生します。属性を追加または削除するとき、ユーザーは Vue.set/delete を使用する必要があります。特別な API が有効になる可能性がありますが、es6 で生成された新しい Map および Set データ構造などの問題はサポートされていません。

  • これらの問題を解決するために、vue3 はこの部分の実装を書き直しました。ES6 の Proxy プロキシを使用してデータに応答すると、多くの利点があり、プログラミング エクスペリエンスが一貫しています。特別な API を使用することで、初期化パフォーマンスとメモリ消費量が大幅に向上しました。また、レスポンシブ実装コードが独立したリアクティビティ パッケージに抽出されるため、より柔軟に使用でき、サードパーティの拡張機能の開発もより柔軟になります。


#理由を知るvue2 の応答性:

    https://github1s.com/vuejs/vue/blob/HEAD/src/core/observer/index.js#L135-L136
  • vue3 レスポンシブ:

https://github1s.com/vuejs/core/blob/HEAD/packages/reactivity/src/reactive.ts#L89-L90
  • https:// github1s.com/vuejs/core/blob/HEAD/packages/reactivity/src/ref.ts#L67-L68
09 - あなたの理解を教えてくださいと言う仮想 DOM の?

分析

ほとんどすべての既存のフレームワークは、実際の DOM を抽象化するために仮想 DOM を導入しています。これは、今や誰もが知っている VNode と VDOM です。では、なぜ仮想 DOM を導入する必要があるのでしょうか?この質問に答えるだけです!

感想

vdomとは
  • 導入のメリットvdom
  • vdom の生成方法と dom になる方法
  • 後続の diff での vdom の役割

回答例

Virtual dom は、名前が示すとおり、仮想 dom オブジェクトであり、それ自体が
    JavaScript
  • オブジェクトですが、さまざまな属性を通じてビュー構造を記述します。

    vdom を導入すると、次の利点が得られます。
  • 実際の要素ノードを VNode に抽象化し、dom に対する直接操作の数を効果的に削減し、それによってパフォーマンスを向上させます。プログラムのパフォーマンス

    diff、clone、その他の操作など、DOM を直接操作するには制限があります。実要素には多くのコンテンツがあります。diff 操作を直接実行すると、必要なコンテンツ。同様に、クローンを作成する必要がある場合は、そのコンテンツをすべてコピーする必要がありますが、これは必要ありません。ただし、これらの操作を JavaScript オブジェクトに移動すると、操作がより簡単になります。

      DOM 操作は比較的高価な操作です。DOM 操作が頻繁に行われると、ページの再描画やリフローが簡単に発生する可能性があります。ただし、中間処理用の抽象 VNode を使用すると、直接 DOM 操作の数を効果的に減らすことができるため、ページの再描画とリフローが削減されます。リフロー、逆流。
    • クロスプラットフォームの実装を容易にする

    同じ VNode ノードを、異なるプラットフォーム上の対応するコンテンツにレンダリングできます。例: ブラウザーでのレンダリングis dom 要素ノードは、ネイティブ (iOS、Android) の対応するコントロールにレンダリングされ、SSR の実装、WebGL へのレンダリングなどが可能です。

      Vue3 を使用すると、開発者は、さまざまなプラットフォームでのレンダリングの便宜のために、VNode に基づいたカスタム レンダラーを実装できます。
    vdom を生成するにはどうすればよいですか? vue では、コンポーネントのテンプレートを作成することがよくあります。このテンプレートはコンパイラによってレンダリング関数にコンパイルされます。その後のマウント プロセスでレンダリング関数が呼び出され、返されるオブジェクトは仮想 dom です。ただし、これらはまだ実際の DOM ではないため、後続のパッチ プロセスでさらに DOM に変換されます。

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)
#マウントプロセスが完了すると、vue プログラムは更新プロセスに入ります。一部の応答データが変更されると、コンポーネントが再レンダリングされます。このとき、新しい vdom が生成され、最後のレンダリング結果との差分を取得することで変更が取得され、最小限の DOM に変換されます。運用と効率的なアップデート。

その理由を知る

vnode 定義:

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L127-L128

レンダリング関数を観察します: 21-vdom/test - render-v3.html

vnode の作成:

  • createElementBlock:

https://github1s.com/vuejs/core/blob/HEAD /packages/runtime-core/src/vnode.ts#L291-L292

  • createVnode:

https://github1s.com/vuejs/core/blob/ HEAD /packages/runtime-core/src/vnode.ts#L486-L487

  • 最初の呼び出し時間:

https://github1s.com/vuejs/core / blob/HEAD/packages/runtime-core/src/apiCreateApp.ts#L283-L284


mount:

https://github1s.com/vuejs/core/blob / HEAD/packages/runtime-core/src/renderer.ts#L1171-L1172

マウント プロセスをデバッグします: mountComponent

21-vdom/test-render-v3.html


10 - diff アルゴリズムを理解していますか?

分析

vue の更新原則を含む必須の質問は、理解の深さを比較テストします。

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)


#感想

  • diff アルゴリズムは何をするのか

  • #必要性

  • ##実行する場合
  • ##具体的な実行方法
  • #ハイライト: vue3 の最適化について話しましょう

  • ##回答例

1. Vue における diff アルゴリズムは Snabbdom を改変したパッチアルゴリズムと呼ばれるもので、仮想 DOM を実 DOM に変換する場合は patch メソッドで変換する必要があります。 2. 当初、Vue1.x ビューの各依存関係には、それに対応する更新関数があり、正確に更新できるため、仮想 DOM やパッチ適用アルゴリズムのサポートは必要ありません。 Vue1.x ではそれを実行できません。より大規模なアプリケーション。Vue 2.x では、Watcher の粒度を下げるために、各コンポーネントに対応する Watcher が 1 つだけあります。このとき、パッチ適用アルゴリズムを導入して、変更を加えて効率的に更新します。

3. Vue で diff が実行される瞬間は、コンポーネント内の応答的なデータ変更がインスタンスに更新関数の実行をトリガーするときです。更新関数はレンダリング関数を再度実行して、最新の仮想 DOM を取得します。次に、patch 関数を実行し、古い仮想 DOM と新しい仮想 DOM を比較して変更を見つけ、最終的にそれらを対応する DOM 操作に変換します。

4. パッチ プロセスは再帰的プロセスであり、深さ優先と同じレイヤー比較の戦略に従います。例として vue3 パッチを取り上げます:

まず、2 つのノードが一致しているかどうかを判断します。ノードが異なる場合は、削除して再作成します。

双方がテキストの場合は、テキストの内容を更新します。

    双方が要素ノードの場合は、子要素を再帰的に更新し、要素の属性も同時に更新します。
  • 子ノードを更新するときは、いくつかの状況があります。
  • 新しい子ノードがテキストの場合、古い子ノードが配列の場合、クリアされます。テキストが設定されます;
  • 新しい子ノードがテキストの場合、古い子ノードがテキストの場合、テキストは直接更新されます;
    • 新しい子ノードが配列の場合、古い子ノードがテキストの場合、テキストはクリアされ、新しい子ノード配列内の子要素が作成されます;
    • 新しい子ノードは配列であり、古い子ノードも配列です配列を作成し、2 つの子ノード セットを比較し、詳細を更新します。blabla
    • 5. vue3 で導入された更新戦略: コンパイル 定期的にパッチフラグ、ブロックなどを最適化します。

その理由を知る


パッチ キー コードhttps://github1s.com/vuejs/core/ blob/HEAD/packages/runtime-core/src/renderer.ts#L354-L355Debug test-v3.html

11 - vue3 の新機能知っていますか


分析

公式Webサイトにリストされている最も注目すべき新機能: https://v3-migration. vuejs.org/

つまり、次のとおりです。

Composition API20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

SFC コンポジション API 構文シュガー

テレポートポータル
  • フラグメントフラグメント
  • エミットオプション
  • カスタムレンダラー
  • SFC CSS変数
  • サスペンス
  • 上記は API 関連であり、省略できないフレームワーク機能も多数あります。
回答例


1. API レベルでの Vue3 の新機能は主に次のとおりです: コンポジション API、SFC コンポジション API 構文シュガー、テレポート送信 ドア、フラグメント、エミット オプション、カスタム レンダラー、SFC CSS 変数、サスペンス2.さらに、Vue3.0 にはフレームワーク レベルで多くの注目すべき改善点もあります:

高速化

仮想 DOM 書き換え

コンパイラの最適化: 静的プロモーション、パッチフラグ、ブロックなど
  • プロキシに基づく応答システム
    • 小型化: ツリーシェイキングの最適化が向上
    • 保守が容易: TypeScript のモジュール性
    拡張が容易
  • 独立した応答モジュール
  • カスタム レンダラー
    • #その理由を知る

コンパイラの最適化を体験してください

  • https://sfc.vuejs.org/

リアクティブ実装

  • https://github1s .com/vuejs/core/blob/HEAD/packages/reactivity/src/reactive.ts#L90-L91


12 - 動的ルーティングを定義するにはどうすればよいですか?渡された動的パラメータを取得するにはどうすればよいですか?

分析

API の質問では、基本的な能力がテストされます。エラーは許されません。できるだけ詳しく説明してください。

感想

  • 動的ルーティングとは
  • いつ使用するか動的ルーティング、動的ルーティングの定義方法
  • パラメータの取得方法
  • 詳細と注意事項

回答例

  • 多くの場合、特定の一致パターンのルートを同じルートにマッピングする必要があります。コンポーネント、この場合、動的ルーティングを定義する必要があります。

  • たとえば、すべてのユーザーに表示する必要があるが、異なるユーザー ID を持つ User コンポーネントがあるとします。 Vue Router では、パス内で動的フィールドを使用してこれを実現できます。例: { path: '/users/:id'、component: User }:id パスパラメータです

  • #パスパラメータ はコロン : で表されます。ルートが一致すると、その params の値がすべてのコンポーネントで this.$route.params として公開されます。

  • $route.params に加えて、/users/:username/posts/:postId; などの複数のパラメータを指定できます。 、$route オブジェクトは、$route.query$route.hash などの他の有用な情報も公開します。


考えられる質問

  • 動的ルーティング パラメータの変更に対応する方法

https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#ルーティング パラメータの変更への対応

  • 404 Not Found ルーティングをどのように処理するか

https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#すべてのルートをキャプチャするか、-404-not-found-routes


13-vue ルートを最初から書くように頼まれた場合は、あなたのアイデアを教えてください

アイデア分析:

まず、vue ルーティングが解決する必要がある問題について考えてください。ユーザーがジャンプ リンクをクリックしてコンテンツを切り替えても、ページは更新されません。

  • ハッシュまたは履歴 API を使用して、更新せずに URL ジャンプ ページを実現します。
  • 同時に、ハッシュチェンジ イベントまたはポップステート イベントをリッスンしてジャンプを処理します。
  • によるとのハッシュ値または状態値 ルート テーブル内の対応するコンポーネントを照合してレンダリングします

回答例:

SPA アプリケーションのルーティングを解決する必要があります。問題は、 ページ ジャンプのコンテンツが更新されずに変更されることです。 また、ルートもプラグインの形式で存在する必要があるため、次のようになります。

  • 最初に createRouter関数を定義し、ルーター インスタンスを返し、インスタンス内でいくつかの処理を実行します。

    • 渡された構成アイテムを保存します。ユーザーによる
    • #ハッシュまたはポップステート イベントをリッスンする
    • #コールバック内で、パスに従って対応するルートを照合する
  • ルーターを定義するVue プラグインとして、つまり install メソッドを実装し、内部で次の 2 つのことを実行します。

      2 つのグローバル コンポーネントを実装します: router-link と router-view (ページ ジャンプとコンテンツを実装します)それぞれ表示
    • #$route と $router の 2 つのグローバル変数を定義します。現在のルートとルーターのインスタンスにはコンポーネント内でアクセスできます

その理由を知る:

    createRouterインスタンスの作成方法
https://github1s.com/vuejs/router/blob /HEAD/src/router.ts#L355-L356

    イベント リスニング
https: //github1s.com/vuejs/router/blob/HEAD/src/ History/html5.ts#L314-L315

RouterView

    ページジャンプRouterLink
https://github1s.com/vuejs/router/blob/ HEAD/src/RouterLink.ts#L184-L185

    コンテンツ表示 RouterView
https://github1s.com/vuejs/router/blob/HEAD/src/ RouterView.ts#L43-L44


14-キーの役割について教えてください。

分析:

これは特によくある質問であり、主に仮想 DOM とパッチの詳細に対する全員の習熟度がテストされます。面接官の理解度。

アイデア分析:

  • キーの役割はパッチのパフォーマンスを最適化することであるという結論が得られます

  • keyの必要性

  • 実際の使い方

  • まとめ: vueの判断方法はソースから記述可能コードレベル 2 つのノードは同じですか


回答范例:

  • key的作用主要是为了更高效的更新虚拟DOM。

  • vue在patch过程中判断两个节点是否是相同节点是key是一个必要条件,渲染一组列表时,key往往是唯一标识,所以如果不定义key的话,vue只能认为比较的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能。

  • 实际使用中在渲染一组列表时key必须设置,而且必须是唯一标识,应该避免使用数组索引作为key,这可能导致一些隐蔽的bug;vue中在使用相同标签元素过渡切换时,也会使用key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

  • 从源码中可以知道,vue判断两个节点是否相同时主要判断两者的key和元素类型等,因此如果不设置key,它的值就是undefined,则可能永远认为这是两个相同节点,只能去做更新操作,这造成了大量的dom更新操作,明显是不可取的。


知其所以然

测试代码,test-v3.html

上面案例重现的是以下过程

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

不使用key

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)


如果使用key

// 首次循环patch A
A B C D E
A B F C D E

// 第2次循环patch B
B C D E
B F C D E

// 第3次循环patch E
C D E
F C D E

// 第4次循环patch D
C D
F C D

// 第5次循环patch C
C 
F C

// oldCh全部处理结束,newCh中剩下的F,创建F并插入到C前面

源码中找答案:

判断是否为相同节点

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L342-L343

更新时的处理

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1752-L1753


不使用key

20 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

如果使用key

// 首次循环patch A
A B C D E
A B F C D E

// 第2次循环patch B
B C D E
B F C D E

// 第3次循环patch E
C D E
F C D E

// 第4次循环patch D
C D
F C D

// 第5次循环patch C
C 
F C

// oldCh全部处理结束,newCh中剩下的F,创建F并插入到C前面

源码中找答案:

判断是否为相同节点

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/vnode.ts#L342-L343

更新时的处理

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1752-L1753


15-说说nextTick的使用和原理?

分析

这道题及考察使用,有考察原理,nextTick在开发过程中应用的也较少,原理上和vue异步更新有密切关系,对于面试者考查很有区分度,如果能够很好回答此题,对面试效果有极大帮助。

答题思路

  • nextTick是做什么的?

  • 为什么需要它呢?

  • 开发时何时使用它?抓抓头,想想你在平时开发中使用它的地方

  • 下面介绍一下如何使用nextTick

  • 原理解读,结合异步更新和nextTick生效方式,会显得你格外优秀


回答范例:

1、nextTick是等待下一次 DOM 更新刷新的工具方法。

2、Vue有个异步更新策略,意思是如果数据变化,Vue不会立刻更新DOM,而是开启一个队列,把组件更新函数保存在队列中,在同一事件循环中发生的所有数据变更会异步的批量更新。这一策略导致我们对数据的修改不会立刻体现在DOM上,此时如果想要获取更新后的DOM状态,就需要使用nextTick。

3、开发时,有两个场景我们会用到nextTick:

  • created中想要获取DOM时;

  • 响应式数据变化后获取DOM更新后的状态,比如希望获取列表更新后的高度。

4、nextTick签名如下:function nextTick(callback?: () => void): Promise<void></void>

所以我们只需要在传入的回调函数中访问最新DOM状态即可,或者我们可以await nextTick()方法返回的Promise之后做这件事。

5、在Vue内部,nextTick之所以能够让我们看到DOM更新后的结果,是因为我们传入的callback会被添加到队列刷新函数(flushSchedulerQueue)的后面,这样等队列内部的更新函数都执行完毕,所有DOM操作也就结束了,callback自然能够获取到最新的DOM值。


知其所以然:

  • 源码解读:

组件更新函数入队:

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1547-L1548

入队函数:

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/scheduler.ts#L84-L85

nextTick定义:

https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/scheduler.ts#L58-L59

  • 测试案例,test-v3.html


16-watch和computed的区别以及选择?

两个重要API,反应应聘者熟练程度。

思路分析

  • 先看computed, watch两者定义,列举使用上的差异

  • 列举使用场景上的差异,如何选择

  • 使用细节、注意事项

  • vue3变化


computed特点:具有响应式的返回值

const count = ref(1)
const plusOne = computed(() => count.value + 1)

watch特点:侦测变化,执行回调

const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

回答范例

  • 计算属性可以从组件数据派生出新数据,最常见的使用方式是设置一个函数,返回计算之后的结果,computed和methods的差异是它具备缓存性,如果依赖项不变时不会重新计算。侦听器可以侦测某个响应式数据的变化并执行副作用,常见用法是传递一个函数,执行副作用,watch没有返回值,但可以执行异步操作等复杂逻辑。

  • 计算属性常用场景是简化行内模板中的复杂表达式,模板中出现太多逻辑会是模板变得臃肿不易维护。侦听器常用场景是状态变化之后做一些额外的DOM操作或者异步操作。选择采用何用方案时首先看是否需要派生出新值,基本能用计算属性实现的方式首选计算属性。

  • 使用过程中有一些细节,比如计算属性也是可以传递对象,成为既可读又可写的计算属性。watch可以传递对象,设置deep、immediate等选项。

  • vue3中watch选项发生了一些变化,例如不再能侦测一个点操作符之外的字符串形式的表达式; reactivity API中新出现了watch、watchEffect可以完全替代目前的watch选项,且功能更加强大。


可能追问

  • watch会不会立即执行?

  • watch 和 watchEffect有什么差异


知其所以然

computed的实现

  • https://github1s.com/vuejs/core/blob/HEAD/packages/reactivity/src/computed.ts#L79-L80

ComputedRefImpl

  • https://github1s.com/vuejs/core/blob/HEAD/packages/reactivity/src/computed.ts#L26-L27

缓存性

  • https://github1s.com/vuejs/core/blob/HEAD/packages/reactivity/src/computed.ts#L59-L60

  • https://github1s.com/vuejs/core/blob/HEAD/packages/reactivity/src/computed.ts#L45-L46

watch的实现

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/apiWatch.ts#L158-L159


17-说一下 Vue 子组件和父组件创建和挂载顺序

这题考查大家对创建过程的理解程度。

思路分析

  • 给结论

  • 阐述理由


回答范例

  • 创建过程自上而下,挂载过程自下而上;即:

    • parent created
    • child created
    • child mounted
    • parent mounted
  • 之所以会这样是因为Vue创建过程是一个递归过程,先创建父组件,有子组件就会创建子组件,因此创建时先有父组件再有子组件;子组件首次创建时会添加mounted钩子到队列,等到patch结束再执行它们,可见子组件的mounted钩子是先进入到队列中的,因此等到patch结束执行这些钩子时也先执行。


知其所以然

观察beforeCreated和created钩子的处理

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/componentOptions.ts#L554-L555

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/componentOptions.ts#L741-L742

观察beforeMount和mounted钩子的处理

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L1310-L1311

测试代码,test-v3.html


18-怎么缓存当前的组件?缓存后怎么更新?

缓存组件使用keep-alive组件,这是一个非常常见且有用的优化手段,vue3中keep-alive有比较大的更新,能说的点比较多。

思路

  • 缓存用keep-alive,它的作用与用法

  • 使用细节,例如缓存指定/排除、结合router和transition

  • 组件缓存后更新可以利用activated或者beforeRouteEnter

  • 原理阐述


回答范例

  • 开发中缓存组件使用keep-alive组件,keep-alive是vue内置组件,keep-alive包裹动态组件component时,会缓存不活动的组件实例,而不是销毁它们,这样在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

    <keep-alive>
      <component :is="view"></component>
    </keep-alive>
  • 结合属性include和exclude可以明确指定缓存哪些组件或排除缓存指定组件。vue3中结合vue-router时变化较大,之前是keep-alive包裹router-view,现在需要反过来用router-view包裹keep-alive

    <router-view v-slot="{ Component }">
      <keep-alive>
        <component :is="Component"></component>
      </keep-alive>
    </router-view>
  • 缓存后如果要获取数据,解决方案可以有以下两种:

    • beforeRouteEnter:在有vue-router的项目,每次进入路由的时候,都会执行beforeRouteEnter

      beforeRouteEnter(to, from, next){
        next(vm=>{
          console.log(vm)
          // 每次进入路由执行
          vm.getData()  // 获取数据
        })
      },
    • actived:在keep-alive缓存的组件被激活的时候,都会执行actived钩子

      activated(){
      	  this.getData() // 获取数据
      },
  • keep-alive是一个通用组件,它内部定义了一个map,缓存创建过的组件实例,它返回的渲染函数内部会查找内嵌的component组件对应组件的vnode,如果该组件在map中存在就直接返回它。由于component的is属性是个响应式数据,因此只要它变化,keep-alive的render函数就会重新执行。


知其所以然

KeepAlive定义

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/components/KeepAlive.ts#L73-L74

缓存定义

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/components/KeepAlive.ts#L102-L103

缓存组件

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/components/KeepAlive.ts#L215-L216

获取缓存组件

  • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/components/KeepAlive.ts#L241-L242

测试缓存特性,test-v3.html


19-从0到1自己构架一个vue项目,说说有哪些步骤、哪些重要插件、目录结构你会怎么组织

综合实践类题目,考查实战能力。没有什么绝对的正确答案,把平时工作的重点有条理的描述一下即可。

思路

  • 构建项目,创建项目基本结构

  • 引入必要的插件:

  • 代码规范:prettier,eslint

  • 提交规范:husky,lint-staged

  • 其他常用:svg-loader,vueuse,nprogress

  • 常见目录结构


回答范例

  • 从0创建一个项目我大致会做以下事情:项目构建、引入必要插件、代码规范、提交规范、常用库和组件

  • 目前vue3项目我会用vite或者create-vue创建项目

  • 接下来引入必要插件:路由插件vue-router、状态管理vuex/pinia、ui库我比较喜欢element-plus和antd-vue、http工具我会选axios

  • 其他比较常用的库有vueuse,nprogress,图标可以使用vite-svg-loader

  • 下面是代码规范:结合prettier和eslint即可

  • 最后是提交规范,可以使用husky,lint-staged,commitlint


  • 目录结构我有如下习惯:.vscode:用来放项目中的 vscode 配置

    plugins:用来放 vite 插件的 plugin 配置

    public:用来放一些诸如 页头icon 之类的公共文件,会被打包到dist根目录下

    src:用来放项目代码文件

    api:用来放http的一些接口配置

    assets:用来放一些 CSS 之类的静态资源

    components:用来放项目通用组件

    layout:用来放项目的布局

    router:用来放项目的路由配置

    store:用来放状态管理Pinia的配置

    utils:用来放项目中的工具方法类

    views:用来放项目的页面文件


20-实际工作中,你总结的vue最佳实践有哪些?

看到这样的题目,可以用以下图片来回答:

120 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)


思路

查看vue官方文档:

风格指南:https://vuejs.org/style-guide/

性能:https://vuejs.org/guide/best-practices/performance.html#overview

安全:https://vuejs.org/guide/best-practices/security.html

访问性:https://vuejs.org/guide/best-practices/accessibility.html

发布:https://vuejs.org/guide/best-practices/production-deployment.html


回答范例

我从编码风格、性能、安全等方面说几条:

  • 编码风格方面:

    • 命名组件时使用“多词”风格避免和HTML元素冲突
    • 使用“细节化”方式定义属性而不是只有一个属性名
    • 属性名声明时使用“驼峰命名”,模板或jsx中使用“肉串命名”
    • 使用v-for时务必加上key,且不要跟v-if写在一起
  • 性能方面:

    • 路由懒加载减少应用尺寸
    • 利用SSR减少首屏加载时间
    • 利用v-once渲染那些不需要更新的内容
    • 一些长列表可以利用虚拟滚动技术避免内存过度占用
    • 对于深层嵌套对象的大数组可以使用shallowRef或shallowReactive降低开销
    • 避免不必要的组件抽象
  • 安全:

    • 不使用不可信模板,例如使用用户输入拼接模板:template: <div> + userProvidedString + </div>
    • v-html、:url、:style などを慎重に使用して、html、url、style などのインジェクションを回避してください。
  • #etc.. ....


#21 - vuex についてのあなたの理解を簡単に教えてください。

120 以上の Vue の古典的な面接の質問 (ソース コード レベルの詳細な説明付き)

#思考

  • 定義を与える

  • 必要性の説明

  • いつ使用するか

  • 拡張: 個人的な考え、実際の経験など


  • Vuex は、Vue.js アプリケーション専用に開発されたツールです 状態管理パターン ライブラリ 。集中ストレージを使用してアプリケーションのすべてのコンポーネントのステータスを管理し、対応するルールを使用してステータスが予測可能な方法で変化することを保証します。

  • 私たちは、単純な「一方向データ フロー」方法、つまり、状態 -> 表示 -> 操作の一方向ループでアプリケーションを管理することを期待しています。しかし、アプリケーションが状態を共有する 複数のコンポーネント に遭遇した場合、たとえば、複数のビューが同じ状態に依存している場合や、異なるビューの動作が同じ状態を変更する必要がある場合があります。一方向のデータ フローの単純さは、この時点で簡単に破られる可能性があります。したがって、コンポーネントの共有状態を抽出し、グローバル シングルトン モードで管理する必要があります。状態管理のさまざまな概念を定義して分離し、ルールを適用してビューと状態の間の独立性を維持することにより、コードはより構造化され保守しやすくなります。これは vuex の存在の必然性であり、react エコシステムにおける redux と同じ概念です。

  • Vuex は、状態管理を解決する際に、状態、突然変異、アクションなどの多くの概念を導入します。これを導入する必要があるかどうかは、アプリケーションの実際の状況に基づいて判断する必要があります。大規模な単一ページ アプリケーションを開発する予定がない場合、Vuex の使用は面倒で冗長ですが、単純な ストア モード で十分です。ただし、中規模から大規模の単一ページ アプリケーションを構築する場合は、基本的に Vuex が標準です。

  • #vuex の使用中に若干の違和感を感じます


#考えられる質問

    vuex の欠点は何ですか?開発中に何か問題が発生しましたか?
  • アクションと突然変異の違いは何ですか?なぜそれらを区別するのでしょうか?
#22-テンプレートからレンダリングまでのプロセスについて話す

分析

テンプレートからレンダリングまでのプロセスについて尋ねることは、実際には vuecompiler

の動作原理について尋ねることになります。

アイデア

vue コンパイラの概念の紹介
  • 手順コンパイルについて コンパイラの必要性
  • #コンパイラのワークフローの説明

  • #回答例

Vue には、「コンパイラー」と呼ばれる独自のコンパイラ モジュールがあり、その主な機能は、ユーザーが作成したテンプレートをコンパイルして、js で実行可能なレンダリング関数を作成することです。

  • このコンパイル プロセスが必要な理由は、フロントエンド プログラマがビュー テンプレートを効率的に作成できるようにするためです。それに比べて、私たちは依然として、直感的で効率的な HTML を使用してビューを作成することを好みます。手書きのレンダリング関数は非効率であるだけでなく、コンパイル時の最適化機能も失われます。

  • Vue では、コンパイラは最初にテンプレートを解析します。このステップは解析と呼ばれます。終了後、JS オブジェクトが取得されます。抽象構文ツリー AST になり、次にAST を実行する 深層処理の変換プロセスでは、このステップは変換と呼ばれ、最後に以前に取得した AST が JS コード (レンダリング関数) に生成されます。

  • #理由を知る

vue3 コンパイル プロセスを覗いてみよう: https://github1s.com/vuejs/core/blob/HEAD/packages/compiler-core/src/compile.ts#L61-L62

    test,test-v3。 html
  • 考えられる質問

Vue のコンパイラはいつ実行されますか?

#react 用のコンパイラはありますか?
  • 23-Vue インスタンスのマウント中に何が起こりましたか?

##分析

マウント プロセスでは、最も重要な 2 つの作業が完了します:

#初期化更新メカニズムを確立する

    この 2 つのことを明確にしてください。
  • 回答サンプル
    • マウント プロセスは app.mount() プロセスを指します。このプロセスでは、初期化更新メカニズムの確立#という 2 つのことが全体として行われます。

    • ##初期化では、コンポーネント インスタンスが作成され、コンポーネントのステータスが初期化され、さまざまな応答データが作成されます

    • 更新メカニズムを確立するこのステップが実行されます更新関数はコンポーネントのレンダリング関数を初めて実行し、以前に取得した vnode を dom に変換するパッチを実行します; 同時に、レンダリング関数を初めて実行すると、その内部応答間の依存関係が作成されます。データとコンポーネントの更新関数 (将来のデータ変更の原因となる) 対応する更新関数が実行されます。

    #理由を知る

      テスト コード、test-v3.html マウント関数定義
    • https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/apiCreateApp.ts#L277-L278

      ##最初のレンダリング プロセス
    • ##https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-core/src/renderer.ts#L2303-L2304
    • #考えられる質問

    レスポンシブ データを作成する方法

    • 依存関係 方法

    • #元のアドレス: https://juejin.cn/post/7097067108663558151

      著者: ヤン村長
    ## (学習ビデオ共有:
    vue ビデオ チュートリアル

    )

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