Vue源码常见问题

1,new Vue()都做了什么

1,new Vue ( )是创建 Vue 实例,它内部执行了根实例的初始化过程

2, 初始化过程具体包括以下操作:

  • 合并配置
  • 初始化数据 props、data、computed、watcher 等
  • 初始化事件中心
  • 初始化生命周期 (new Vue()时只调用了beforeCreated、created两个生命周期)
  • 初始化渲染

在这里插入图片描述
在这里插入图片描述
3,new Vue( ) 创建了根实例准备好数据和方法,以备将来执行挂载进使用。

2,说一说你对Vue响应式的理解

1,所谓数据响应式就是数据的更改导致视图层做出更新的机制

2, vue2 中的数据响应式会根据数据类型来做不同处理

  • 如果是对象则采用 object.defineproperty的方式定义数据拦截,当数据被访问或发生变化时,触发set方法并作出晌应;
  • 如果是数组则通过vue变更后的数组原型方法(push,shift,unshift,splice,pop,sort,reverse ),从而作出响应。
  • 如果是基础类型的值,比如说String、Number、Boolean等,它是通过放到对象中,作为对象的属性,从而利用 object.defineproperty对值的变化进行监听。这也就是为什么vue组件中的所有状态都是在一个对象中的原因。

数组的这种机制很好的解决了数据响应化的问题,但在实际使用中也存在一些缺点:比如:

1,新增或删除属性时,无法监听到变化,需要用户使用 vue.set

2,对于 es6 中新产生的 Map 、 Set 这些数据结构不支持等问题。

为了解决Vue数组中的变更方法引起的问题, vue3 重新编写了这一部分的实现:利用ES6的Proxy机制代理要响应化数据,这样我们就不需要使用特殊api, 初始化性能和内存消耗都得到了大幅改善.

3,最后,Vue通过操作数据,再使用virtual Dom 和 patch算法,就可以使我们只需要操作数据,完全不用接触 dom 操作来更新视图,从而大大提升开发效率,降低开发难度。

3,你知道nextTick吗?

这个考查的是对vue异步更新队列的理解

1,由于 vue更新DOM采用是的异步更新策略,导致我们对数据的修改不会立刻体现在 dom 变化上,nextTick的作用就是,在修改数据之后立即使用这个方法,可以获取更新后的 DOM

2,Vue data 中某一个属性的值发生改变后,视图会立即同步执行重新渲染吗?

`不会,因为Vue 是异步执行 DOM 更新的,具体过程如下:`
  • 1、修改数据,这是同步任务,但是此时还未去修改 DOM 。

  • 2、数据发生变化之后,Vue 开启一个异步队列,并缓冲在此事件循环中所有发生改变的数据

    如果同一个数据被多次触发修改,那么也只会被推入到队列中一次。 在缓冲时去除重复数据,对于避免不必要的计算和 DOM 操作。

  • 3、在此事件中所有的同步任务执行完毕后,开始执行异步队列中的任务,更新 DOM。
    nextTick 传入的方法,会在异步任务执行后,作为回调来调用,此时就能获取到更新后的DOM了。

3,简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环 中的所有数据变化完成之后,再统一进行dom更新。

参考链接:https://segmentfault.com/a/1190000012861862

4,你知道key的作用吗

1). key通常用在通过某个列表,对template中的某块模版,进行循环渲染的时候。

2). 这样的话,循环渲染出来的dom就是一模一样的,以致于,在把模版转化成vnode后,其相应的vnode节点也就是一样的。如果不加以区分的话,当数据变化,重新编译模版,再次将模版转化为新的vnode后,在进行新旧vnode比较时。

3)如果设置了key,key就是 vnode 的唯一标记,通过这个 key,我们可以更快的找到新旧vnode 中对应的节点,从而进行比较, 这样就降低了 diff算法的复杂度,使diff 操作更准确、更快速

比如说:我们在列表中间新增了一个数据,
在这里插入图片描述
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的------ 同级节点进行比较。
在这里插入图片描述
这样由于顺序的问题,就导致了原先不需要更新的节点,也变的需要更新了。

即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识,这样通过Diff算法就可以正确的识别此节点所对应的新vnode中对应的节点,从而进行更准确的比较,这样就能减少不必要的dom更新。从而找到正确的位置区插入新的节点。

在这里插入图片描述
4). 从源码角度来说:

  • 在vnode中,用key区分两个相同的节点
    实际的标签中可能存在两个一模一样的两个节点,但是在virtual Dom中无法体现这个区别,这就用到了key以作区分。

  • 加快diff算法的速度
    在新旧vnode的对比中,即在diff算法中,大量使用了tagName和key组合判断节点之间差异的逻辑,以判断这个节点是被修改了、删除了还是新增的。这样就能够尽可能的复用已有元素而不是从头开始渲染。

5,keep-alive的作用是什么

<keep-alive></keep-alive>包裹组件时,主要用于保留组件状态或避免重新渲染

keep-alive 独有的生命周期,分别为 activated 和deactivated。

用 keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子函数,再次显示时,会执行 activated 钩子函数

6, vue-loader是什么?使用它的用途有哪些?

  • 定义:vue-loader 是 webpack 的一个 loader,用于处理 .vue 文件,是解析.vue文件的一个加载器。

7,scss在vue-cli中的安装使用步骤是什么?有哪几大特性?

7.1 使用步骤:

(1) 安装
css-loader、node-loader、sass-loader等加载器模块。

npm install node-sass --save-dev
npm install sass-loader --save-dev

(2) 配制webpack.base.config.js

// 在 rules中添加
{
  test: /\.scss$/,
  loaders: ['style', 'css', 'sass']
}

(3)使用
在组件的style标签上加上lang属性,如lang=“scss”

<style lang="scss" scoped>
/* 写入scss */

</style>
7.2 特性

(1)可以使用变量,如($变量名称=值)。
(2)可以嵌套
(3)可以用混合器,@mixin,可重用性高

@mixin banner {
  width: 100%;
  position: relative;
  color: $deeepBlue;
}
.lead-banner {
  @include banner;
}

(4)使用@extend:允许一个选择器继承另一个选择器

.a1 {
   color: blue;
}
.a2 {
   @extend .a1;
   font-size: 12px;
}

(5)计算功能

p {
   margin: 20px + 30px;
    width: (100% / 6);
}

(6) if、for循环语句(用的不多)

@mixin bgcolor($b) {
  @if($b==5) {
   background-color: #fff;
  } @else if($b == 6) {
   background-color: green;
  } @else {
   background: blue;
  }
}

8、为什么避免v-if和v-for一起使用?

1、当vue处理指令时,当v-for,v-if处于同一节点时,v-for比v-if具有更高的优先级。这意味着v-if将分别重复运行于每个v-for循环中。
2、解决:可以将v-if放在一个包装元素内。

<ul v-if="shouldRenderTodos">
	<li v-for="todo in todos">
		todo
	</li>
</ul>

9、diff算法的逻辑

1、当页面的数据发生变化时,Diff算法只会比较同一层级的节点:

  • 如果节点类型不同,不会再比较这个节点及其以后的子节点了,直接干掉旧的节点,再创建并插入新的节点。
  • 如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新

在这里插入图片描述

10、简述 mixin、extends 的覆盖逻辑

10.1、mixin 和 extends

mixin 和 extends 均是用于合并、拓展组件的,两者均通过mergeOptions 方法实现合并。

区别

  • extends会比mixins先执行。执行顺序:extends > mixins > 组件
  • extends只能暴露一个extends对象,而mixins可以有多个mixin对象,多个mixin时,按照传入顺序依次调用
let mixin = {
      created() {
        console.log('mixin say hi')//mixin比组件先输出
      },
      data() {
          return {
            msg: 10
          }
      },
      methods: {
        foo(){
              console.log('mixin foo()'+this.msg++)
        }
      }

 }
 let extend={
      created() {
        console.log('extend say hi')//extend比先输出mixin
      },
      data() {
          return {
            msg: 20
          }
      },
      methods: {
        foo(){
              console.log('extend foo()'+this.msg++)
        }
      }
 }

 Vue.component('component-a',{
      template:`<div><button @click="foo">componentA</button>{{msg}}</div>`,
      created() {
        console.log('componentA say hi')//后输出
      },
      methods:{
      }, 
      extends:extend,
      mixins:[mixin]
  })

10.2、合并规则

mixin 和 extends的配制与组件自身的配制合并时,如果出现相同时,

组件自身的配制 > mixins > extends;

11、子组件可以直接改变父组件的数据吗?

子组件不可以直接改变父组件的数据。这样做主要是为了维护父子组件的单向数据流。

Vue 提倡单向数据流,即父级 props 的更新会流向子组件,但是反过来则不行。

这是为了防止意外的改变父组件状态,使得数据流混乱。

因此,子组件如果想要修改父组件的数据时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改;

12、vue-cli中assets 和 static 的区别

相同点

  • assets 和 static 两个都是存放静态资源文件,比如说:图片、css、字体图标等

不同点

  • assets 中存放的静态资源文件在项目打包时,会通过打包工具进行压缩体积,代码格式化。而static中的资源则不会。

建议

  • 将 template 需要的样式文件 、js 文件等都可以放置在assets 中,走打包这一流程。减少体积。
  • 项目中引入的第三方的资源文件如 iconfoont.css 等文件可以放置在 static 中,因为这些文件已经经过处理,不需要再处理了;

13、delete和Vue.delete的区别

delete和和Vue.delete都是对数组或对象进行删除的方法。

  • 对于对象来说,没有区别的,使用方法会直接删除对象的属性(物理删除)
let obj = {
name: 'fufu',
  age: 20
}
// delete obj.age  => {name: 'fufu'}
// Vue.delete(obj, 'age') => {name: 'fufu'}
// 测试发现对于对象来说delete和Vue.delete是没有任何区别的
  • 对于数组来说,区别比较大
    • delete只是被删除的元素变成了 empty/undefined,其他的元素的键值还是不变。数组长度也不变。(逻辑删)
    • Vue.delete是直接删除该元素,长度发生变化。(物理删)
let arr = [1,2,3,4,5]
delete arr[2]  //[1,2,empty,4,5]
Vue.delete arr[2]  //[1,2,4,5]

14,对 vue 设计原则的理解

1. 渐进式 JavaScript 框架
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用
Vue 的核心库只关注视图层
如果你需要多个页面,再添加路由router,如果还需要状态管理,再添加vuex,如果还需要其它插件,再安装相应插件。

2.灵活性
渐进式框架的最大优点就是灵活性,如果应用足够小,我们可能仅需要 vue 核心特性即可完成功能
随着应用规模不断扩大,我们才可能逐渐引入路由、状态管理、vue-cli 等库和工具,不管是应用体积还是学习难度都是一个逐渐增加的平和曲线。

3.易用性
vue 提供数据双向绑定、声明式模板语法等。这些使我们只需要关注应用的核心业务即可,只要会写 js、html 和 css 就能轻松编写 vue 应用

4.高效性
一方面,虚拟DOM使得开发者避免了大量的DOM操作;
另一方面,不断优化的diff算法,使我们的应用拥有最佳的性能表现(从最开发的diff算法—》静态标记优化避免不必要的对比)
最后,从vue2到vue3响应式原理的变化,即从Object.defineProperty() ---> Proxy()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值