前端八股文(一)

101 阅读6分钟
  • 原型和原型链
  • less和sass有什么区别
  • Vue实例挂载过程中发生了什么
  • 对生命周期的理解
  • vue给对象添加新属性界面不刷新
  • v-if和v-for为什么不建议一起使用
  • 组件之间信息传递
  • nextTick
  • Vue当中key的作用
  • 虚拟dom
  • diff算法

原型和原型链

原型

每一个函数都一个prototype属性,这个属性称之为原型。因为这个属性的值是对象,所以也称为原型对象

原型的作用:

  • 存放一些属性和方法
  • 实现继承

-proto-

每一个对象都有-proto-属性

作用:指向他的原型对象(相当于在对象和原型之间搭了一条线)

image.png 例子:当我们创建好一个数组之后,可以使用数组的sort、slice等一些方法。

因为在这个数组的prototype身上已经挂载了很多的方法,那我们通过构造函数(new Array),构造了一个数组实例

原型链

如下,我们创建了一个Person的构造函数,我们说只要是构造函数就有原型对象,并且我们创建了一个对象实例,那么只要是对象就有_proto_,通过_proto_牵线我们就可以使用原型上的一些方法,但是如果原型找不到,他不会就此停止,因为我们说原型也是一个对象,他也有_proto_指向他的原型对象,就这么一直寻找直至最后返回null,这样一层一层形成链式结构就称为原型链

image.png

construct proto prototype之间的三角关系

16b1c94e15c05c660a5f765b5dc1e99.jpg

  • constructor指向构造函数,打印对象数据,我们会发现实际上并没有看到,二十被当作一个共享的属性放在他们的原型对象上了
  • prototype是函数独有的,本质上是为了内存着想,比如我们常用的数组,如果我们每声明一个数组对象,就要自己去写方法,是非常占用内存的而且也麻烦,所以在我们去声明一个数组的时候,我们会发现,我们没有写的一些数组方法,我们也可以进行使用,这就是prototype。
  • proto 找到原型对象,基于上面两点,我们会发现,有了prototype,但是我们没法找到我们的原型对象啊,construct也是共享在原型对象中的,此时我们就会想到要是对象有一个属性直接指向自己的原型对象就好了,这就出现了proto,建立他们之间的关系,顺着这个关系我们就可以顺利找到原型对象,调用其方法。那么原型对象也有他自己的原型,这样一层一层的寻找下去,形成一个链式的结构,就是原型链

less和sass有什么区别

本质上都是css的预编译器,用编程的思想去写css。增加了规则嵌套、变量、混合、选择器继承等等。 sass:

没有大括号,严格缩进

 #sidebar
  width: 30%
  background-color: #faa

scss

 #sidebar {
     width: 30%;
     background-color: #faa;
 }

less 跟scss大同小异

Vue实例挂载过程中发生了什么

挂载过程指的是app.mount的过程,整体上基本做了两件事:初始化和建立更新机制

  • 初始化:创建组件实例、初始化组件状态、创建各种的响应式数据
  • 建立更新机制:会立即执行一次组件更新函数,会首次执行渲染函数生成虚拟dom并执行patch将前面获得的虚拟dom转换成真实dom;同时首次执行渲染函数还会创建它内部响应式数据和组件更新函数之间的依赖关系,是的数据变化会执行对应的更新函数

对生命周期的理解

生命周期:vue2和3当中名字 变了原理没变

beforecreate/created、beforemount/mount、beforeupdate/update、beforedestory/destory(vue2)、beforeunmount/unmounted(vue3)

组合式api:

setup:在beforecreate/created之前运行,可以用它来代替两个钩子

  • created:这个时候可以调用methods方法,访问和修改数据
  • mounted:完成dom的挂载和渲染

vue给对象添加新属性界面不刷新

vue2通过Object.defineProperty来实现数据响应式,触发get和set(新的和旧的是否相同,不相同就赋值)

原因:vue不允许再已经创建的实例上动态添加新的响应式数据

解决:

  • Vue.set()
  • 大量对象的时候--Object.assgin(),合并新对象和源对象
  • 不知道怎么做就强制刷新

v-if和v-for为什么不建议一起使用

vue2当中v-for的优先级高,vue3中v-if的优先级高。如果我们的数组很大的时候,但是我们只有其中一个数据需要渲染,那么我们先遍历数组,遍历一次就会进行一次判断,这样会在带来性能方面的浪费,比如我们的页面加载就会不及时,影响用户体验

  • 作用在同一标签时:v-for的优先级会比v-if高

组件之间信息传递

父传子

props

children

props:{  
    // 字符串形式  
 name:String // 接收的类型参数  
    // 对象形式  
    age:{    
        type:Number, // 接收的类型为数值  
        defaule:18,  // 默认值为18  
       require:true // age属性必须传递  
    }  
}  

father
<Children name="jack" age=18 />  

子传父

$emit

children
this.$emit('add', good) 

father
<Children ref="foo" />

nextTick

在dom更新循环结束之后执行回调

原理:利用promise和微任务完成

vue会将回调函数添加在微任务队列,dom执行完成之后会立即执行这个函数

Vue当中key的作用

  • 没有key的时候,会采用就地更新的策略,就是直接更新值,这个时候,对比有key就会快,因为有了key之后他采取的可能是节点迁移,比较耗费性能
  • key的作用:防止dom混乱,

而且注意不能以index为key:比如我一个数据有三个元素,我给三个元素都添加input框,写上他们的值,

image.png 然后我插入一个数据到数组第一个,我会发现,没有key的话

image.png 有了key:

image.png

原因:没有key或者以index为key,都相当于原地变化值,而没有移动节点,所以原先的节点还是在原先的位置

虚拟dom

因为真实的dom操作是比较消耗性能的,一个节点就会有很多属性,虚拟dom的出现就减少了dom 的操作。如果没有虚拟dom,每操作一次dom,浏览器就会马上更新,从头到尾的构建一次dom树。而通过虚拟dom,他不会立即更行,而是将所有更新一次性构建。虚拟dom优势还在于diff算法,diff算法将新旧虚拟dom树进行比较,替换更新节点,避免大量的重复计算。虚拟dom的优势还在于实现了跨平台的功能,不仅仅是浏览器的dom,还可以是安卓和ios的原生组件包括一些gui。

diff算法

  • 从根节点开始递归的比较虚拟dom树和真实dom树的节点
  • 根节点不同则直接替换根节点
  • 子节点更新也是尽量找到最小差异
  • 子节点不同则更新子节点,若子节点相同属性不同,更新子节点属性

比较过程

  • 同级比较
  • 两边向中间收拢

阅读: Sass和Scss的区别 - 掘金 (juejin.cn)