玩转vue面试题系列4 结合源码分析面试题


玩转vue面试题系列3 结合源码分析面试题

16. 谈谈对Vue组件化的理解

组件的优点:

  1. 组件的复用可以根据数据渲染对应的组件。
  2. 把组件相关的内容放在一起,方便复用,方便维护。
  3. 合理的规划组件,可以做到更新视图的时候是组件级别的更新,不会过于消耗性能。

vue中是如何处理组件的?

  1. 需要使用API,Vue.extend。根据用户传入的对象生成一个组件的构造函数。
  2. 根据组件产生对应的虚拟节点。我们会在生成虚拟节点前,在组件的data中加入一个hook。(data:{hook:{init(){}}})
  3. 做组件初始化,将虚拟节点转换为真实节点(组件的init方法,就是第二步中增加的)。就是调用init方法(init方法中就是 new Sub().$mount())

当然这个题也是需要结合17题来走一遍流程的。

17. Vue组件的渲染流程

  • 先定义组件的选项
  • components -> vm.$options.components[“name”] = {name:{template:””}}
  • createComponent:(这个函数是创建vnode的,并插入相关的hook,如init) 渲染组件name的时候,需要创建name对应的虚拟节点
  • createComponent创建真实节点 -> vm.data.hook.init() -> new Ctor().$mount() -> 组件的初始化完毕

image-20220424133849698

patch 方法,就是我们的vm.__patch__方法

image-20220424134100065

image-20220424134134553

image-20220424134309114

image-20220424134356984

image-20220424134549820

image-20220424134619312

image-20220424134646485

18. vue组件的更新流程

同上一题分析。

组件更新的有几种情况:

  1. data数据更新,就是依赖收集
  2. 属性更新,可以给组件传入属性,属性变化后,触发更新
  3. 插槽变化也要更新

属性props的变化,触发更新,肯定也是来到patch方法。

  • 组件更新会触发组件的prepatch方法,会复用组件,并且比较组件的属性,事件,插槽等
  • 父组件给子组件传递的属性(props)是响应式的,在模板中使用会做依赖收集,收集自己的组件watcher
  • 稍后组件更新了,会重新给props赋值,赋值完成后会触发watcher重新更新

19. vue中异步组件原理

Vue中异步组件的写法有很多。主要用作大的组件进行异步加载。比如markdown组件,editor组件。

先渲染一个注释标签,等组件加载完毕后,在重新渲染。

  • forceUpdate(类似于图片懒加载),使用异步组件会配合webpack

  • 原理就是,异步组件默认不会调用Vue.extend方法,所以Ctor(函数)上不会cid属性,没有cid我们就认为是异步组件了。

image-20220428130555925

  • 会先渲染一个占位组件,有loading就会先渲染loading,此时第一轮结束
  • 如果用户调用了resolve,会将结果赋给factory.resolved上,强制重新渲染。重新渲染的时候,会再次进入到resolveAsyncComponnet中,会直接拿到factory.resolved的结果来渲染。

image-20220428154954662

image-20220428155107000

image-20220428155225772

20. 函数式组件的优势及其原理

  • react中也有两种组件:类组件和函数式组件
  • 函数式组件,没有类就没有this,也就没有状态这些,没有生命周期 beforeCreate等。
  • 函数式组件的好处:就是性能好,不需要创建watcher等
  • 函数式组件就是调用render,拿到返回结果(vnode)所以性能高

image-20220428161544682

21. vue组件间传值的方式及之间的区别

  1. props:父传递数据给儿子
  2. emit :儿子触发组件更新

先看props

  <div id="app">
    <my a="123" c="我是父给子的数据" />
  </div>
  <script src="../dist/vue.js"></script>
  <script>
    const vm = new Vue({
      data() {
        return {
        }
      },
      el: "#app",
      components: {
        "my": {
          props: ["c"],
          // a是普通属性 attrs c是props属性 props->c  attrs->a
          /*
          组件的虚拟节点上 {componentOptions: propsData} propsData -> c
          初始化的时候要对propsData做处理
          将组件的属性挂载到vm.$options.propsData
          声明一个 vm._props 类似于 vm._data
          只有根属性会被观测,其他父组件传递给我们的不需要进行观测
          将所有的属性定义到 vm._props上
          vm.c -> vm._props.c
          */
          template: `<h2 :c="c">我是组件</h2>`
        }
      }
    })
  </script>

首先要搞明白,我们父组件传递给子组件的数据,最开始全都是attrs,也就是属性。但是,我们在创建组件的虚拟dom的时候,会把属性进行抽离:如果我们在props中定义了该属性,表名这个属性是父组件传递的props属性,如果没有定义,该属性概述作为attrs属性。

image-20220430214149996

image-20220430221724530

更新组件的时候,我们会走updateComponentChildren方法

image-20220430231527888

总结一下:props的原理就是把解析后的props,验证后将属性定义在当前实例上的vm._props.这个对象上的属性都是通过 defineReactive方法来定义的。都是响应式的。组件在渲染的过程中,会去vm上的_props取值,(_props属性也会被代理到vm上)

emit方式:

image-20220430233500966

使用emit进行组件通信,那么用到的就是发布订阅模式。

my.$on("cb",cb)

在创建虚拟节点的时候将所有事件,绑定到了listeners,如果是有修饰符.native修饰的事件,会绑定在组件上,最后在nativeOn属性上。在ininEvents方法内,将事件通过add(其实就是 o n ) 方 法 绑 定 事 件 , 通 过 on)方法绑定事件,通过 onemit触发事件。

image-20220501102707287

eventBus原理就是发布订阅, $bus = new Vue()简单的通信可以采用这种方式,但是对于多个组件之间相互通信,会显得有些混乱。

对于 p a r e n t , parent, parent,children,就是在创造子组件的时候,会将父组件的实例传入,在组件本身初始化的时候会构建组件间的父子关系, p a r e n t 获 取 父 组 件 实 例 , 通 过 parent获取父组件实例,通过 parentchildren获取所有的子组件实例。开发中也不建议使用。( p a r e n t . parent. parent.parent… 岂不是回到了jquery)

image-20220501103103930

ref原理:

  • ref可以获取dom元素和组件的实例,(虚拟dom没有处理ref,这里无法拿到实例,也无法获取组件)
  • 创建dom的时候是如何处理ref的
  • 会将用户所有的dom操作及属性,都维护到一个cbs属性中,(create,update,insert,destory…)依次调用cbs中的create方法,这里就包含ref相关的操作,会操作ref,并且赋值。

image-20220501130014260

inject,provide

在父组件通将属性暴露出来,在后代属组件中注入属性。(少用

父级组件提供的数据,在子组件中递归查找,找到就定义在自己的身上。

image-20220501131318169

$attrs, $listeners

  • $attrs:所有组件上的属性,不涵盖props
  • $listeners:组件上所有的事件

image-20220501132237053

通过$attrs属性,可以快速的把非props的属性传递给子组件

image-20220501133453020

image-20220501133506770

其实还有一个Vue.observal,可以创造一个全局的对象用于通信

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尤雨东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值