VUE常用知识

1、Vue的基本原理

【】当一个Vue实例创建时,Vue会遍历data中的属性,用 Object.defineProperty(vue3.0使用proxy )将它们转为 getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

2、双向绑定数据的原理

【】Vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。主要分为以下几个步骤:

  • 需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
  • compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
  • Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是: ①在自身实例化时往属性订阅器(dep)里面添加自己 ②自身必须有一个update()方法 ③待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退
  • MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果
3、使用 Object.defineProperty() 来进行数据劫持有什么缺点

【】通过下标方式修改数组数据或者给对象新增属性,这都不能触发组件的重新渲染,因为 Object.defineProperty 不能拦截到这些操作

4、MVVM 理解

【】MVVM 分为 Model、View、ViewModel

  • Model 代表数据模型,数据和业务逻辑都在Model层中定义
  • View 代表UI视图,负责数据的展示
  • ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作
5、Computed、Watch、Methods、Fliters

【】对于 Computed:

  • 支持缓存,只有依赖的数据发生了变化,才会重新计算
  • 不支持异步,当Computed中有异步操作时,无法监听数据的变化

【】对于 Watch:

  • 不支持缓存,数据变化时,它就会触发相应的操作
  • 支持异步监听

【】对于 Methods:

  • 同一函数可以定义为一个 method 或者一个计算属性,但是 method 不支持缓存,每次都会调用

【】对于 Fliters:

  • 对数据进行格式化。过滤器用在插值表达式 {{ }}v-bind 表达式 中,然后放在操作符“ | ”后面进行指示
6、slot是什么?有什么作用?原理是什么?

【】slot又名插槽,是Vue的内容分发机制,组件内部的模板引擎使用slot元素作为承载分发内容的出口

【】分为三类:默认插槽,具名插槽和作用域插槽

【】实现原理:当子组件 vm 实例化时,获取到父组件传入的 slot 标签的内容,存放在vm.$slot中,默认插槽为vm.$slot.default,具名插槽为vm.$slot.xxx,xxx 为插槽名,当组件执行渲染函数时候,遇到 slot 标签,使用 $slot 中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可称该插槽为作用域插槽

7、常见的事件修饰符

【】.stop:等同于 JavaScript 中的 event.stopPropagation() ,防止事件冒泡

【】.prevent :等同于 JavaScript 中的 event.preventDefault() ,防止执行预设的行为

【】.capture :与事件冒泡的方向相反,事件捕获由外到内

【】.self :只会触发自己范围内的事件,不包含子元素

【】.once :只会触发一次

8、v-if 和 v-show 的区别

【】手段:v-if 是动态的向DOM树内添加或者删除DOM元素;v-show 是通过设置DOM元素的display样式属性控制显隐

【】编译过程:v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show 只是简单的基于css切换

【】编译条件:v-if 是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译; v-show 是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留

9、data 为什么是一个函数而不是对象

【】首先当多个实例引用同一个对象时,只要一个实例对这个对象进行操作,其他实例中的数据也会发生变化

【】在Vue中,更多的是想要复用组件,那就需要每个组件都有自己的数据,这样组件之间才不会相互干扰。数据以函数返回值的形式定义,这样当每次复用组件的时候,就会返回一个新的data,也就是说每个组件都有自己的私有数据空间,它们各自维护自己的数据,不会干扰其他组件的正常运行

10、nextTick() 的作用

【】在数据变化后执行的某个操作,而这个操作需要使用随数据变化而变化的DOM结构的时候,这个操作就需要方法在nextTick()的回调函数中

【】在vue生命周期中,如果在created()钩子进行DOM操作,也一定要放在nextTick()的回调函数中。因为在created()钩子函数中,页面的DOM还未渲染,这时候也没办法操作DOM

【】$nextTick 本质是对事件循环原理的一种应用,在更新DOM的微任务队列后追加了我们自己的回调函数,具体实现见:添加链接描述Vue中的nextTick是怎么实现的

11、自定义指令

【】一般需要对DOM元素进行底层操作时使用,尽量只用来操作 DOM展示,不修改内部的值。当使用自定义指令直接修改 value 值时绑定v-model的值也不会同步更新;如必须修改可以在自定义指令中使用keydown事件,在vue组件中使用 change事件,回调中修改vue数据

【】全局定义:Vue.directive("focus",{})。 局部定义:directives:{focus:{}}

【】钩子函数:bind inSerted update componentupdate unbind. 钩子函数参数:el. bing. name. value. oldValue. expression. arg. modifers. vnode. oldVnode

12、assets 和 static 的区别

【】assetsstatic 两个都是存放静态资源文件

【】在项目打包时,assets 中放置的静态资源文件会进行打包上传,static 中放置的静态资源文件就不会要走打包压缩格式化等流程

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

13、Vue 模版编译原理

【】解析阶段:使用大量的正则表达式对 template 字符串进行解析,将标签、指令、属性等转化为抽象语法树AST

【】优化阶段:遍历AST,找到其中的一些静态节点并进行标记,方便在页面重渲染的时候进行diff比较时,直接跳过这一些静态节点,优化runtime的性能

【】生成阶段:将最终的AST转化为render函数字符串

14、对 SSR 的理解

【】SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端

【】优势:更好的SEO;首屏加载速度更快

【】缺点:服务器端渲染只支持beforeCreate和created两个钩子;更多的服务端负载

15、对 SPA 单页面的理解

【】SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载

【】优点:

  • 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染
  • 基于上面一点,SPA 相对对服务器压力小
  • 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理

【】缺点:

  • 初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载
  • 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理
  • SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势
16、Vue 子组件和父组件的执行顺序

【】加载渲染过程:父组件 beforeCreate. >. 父组件 created. >. 父组件 beforeMount. >. 子组件 beforeCreate. >. 子组件 created. >. 子组件 beforeMount. >. 子组件 mounted. >. 父组件 mounted

【】更新过程:父组件 beforeUpdate. >. 子组件 beforeUpdate. >. 子组件 updated. >. 父组件 updated

【】销魂过程:父组件 beforeDestroy. >. 子组件 beforeDestroy. >. 子组件 destroyed. >. 父组件 destoryed

【】vue 的生命周期钩子核心实现式利用发布订阅模式先把用户传入的生命周期钩子订阅好(内部采用数组的方式存储),然后在创建组件实例的过程中会依次执行对应的钩子方法(发布)

17、组件通信方式

【】props / $emit

【】eventBus 事件总线

【】依赖注入(provide / inject):依赖注入所提供的属性是非响应式的

【】ref / $refs

【】$parent / $children

【】$attrs / $listeners

18、对虚拟 DOM 的理解

【】在浏览器上频繁的操作DOM,会产生一定的性能问题。使用虚拟DOM可以减少直接操作DOM的次数,减少浏览器的重绘及回流

【】Virtual DOM 本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象

【】Virtual DOM 映射到真实DOM要经历VNode的create、diff、patch等阶段

【】虚拟 DOM 的作用:

  • 将真实元素节点抽象成 VNode,有效减少直接操作 dom 次数,从而提高程序性能
  • 方便实现跨平台:可以使用虚拟DOM去针对不同平台进行渲染
19、虚拟 DOM 的解析过程

【】首先对将要插入到文档中的 DOM 树结构进行分析,使用 js 对象将其表示出来,比如一个元素对象,包含 TagName、props 和 Children 这些属性。然后将这个 js 对象树给保存下来,最后再将 DOM 片段插入到文档中

【】当页面的状态发生改变,需要对页面的 DOM 的结构进行调整的时候,首先根据变更的状态,重新构建起一棵对象树,然后将这棵新的对象树和旧的对象树进行比较,记录下两棵树的的差异

【】最后将记录的有差异的地方应用到真正的 DOM 树中去,这样视图就更新了

20、说一下前端登录的流程

【】初次登录的时候,前端调后端的登录接口,发送用户名和密码,后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token,和一个用户信息的值,前端拿到token,将token储存到Vuex中,然后从Vuex中把token的值存入浏览器Cookies中。把用户信息存到Vuex然后再存储到LocalStroage中,然后跳转到下一个页面,根据后端接口的要求,只要不登录就不能访问的页面需要在前端每次跳转页面师判断Cookies中是否有token,没有就跳转到登录页,有就跳转到相应的页面,我们应该再每次发送post/get请求的时候应该加入token,常用方法再项目utils/service.js中添加全局拦截器,将token的值放入请求头中 后端判断请求头中有无token,有token,就拿到token并验证token是否过期,在这里过期会返回无效的token然后有个跳回登录页面重新登录并且清除本地用户的信息

21、DIFF算法的原理

【】在新老虚拟DOM对比时

  • 首先,对比节点本身,判断是否为同一节点,如果不为相同节点,则删除该节点重新创建节点进行替换
  • 如果为相同节点,进行patchVnode,判断如何对该节点的子节点进行处理,先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)
  • 比较如果都有子节点,则进行updateChildren,判断如何对这些新老节点的子节点进行操作(diff核心)
  • 匹配时,找到相同的子节点,递归比较子节点
22、首页加载白屏问题处理

【】白屏产生的原因

  • FP(全称“First Paint”,翻译为“首次绘制”) 是时间线上的第一个“时间点”,它代表浏览器第一次向屏幕传输像素的时间,也就是页面在屏幕上首次发生视觉变化的时间
  • FCP(全称“First Contentful Paint”,翻译为“首次内容绘制”) ,它代表浏览器第一次向屏幕绘制 “内容” (文本、图片(包含背景图)、非白色的 canvas 或SVG)
  • FMP(全称“First Meaningful Paint”,翻译为“首次有效绘制”) 表示页面的“主要内容”开始出现在屏幕上的时间点,ajax请求数据之后,首次有效绘制,就是页面加载差不多了,但是可能图片还没加载出来
  • 从FP到FMP这个过程全是白屏

【】解决方法

  • 预渲染、同构、SSR、路由懒加载、quicklink、使用Gzip压缩减少文件体积、外链CSS/JS文件、webpack entry、骨架屏、loading
23、vue模板(template)里为什么不能使用多个头结点

【】只能有一个节点是因为当前 构建 和 diff virutalDOM 的算法还未支撑这样的结构,也很难在保证性能的情况下支撑

【】react 里新增了 Fragment 语法以支持类似多节点的组件,而 Vue3 也提出了类似的语法支持,实际上需要在多节点外包裹一层特殊节点

24、Vue.use 插件机制

【】如果插件是一个对象,必须提供install方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入;该方法需要在调用 new Vue() 之前被调用;当 install 方法被同一个插件多次调用,插件将只会被安装一次

【】原理:功能主要就是两点:安装Vue插件、已安装插件不会重复安装:

  • 先声明一个数组,用来存放安装过的插件,如果已安装就不重复安装
  • 然后判断plugin是不是对象,如果是对象就判断对象的install是不是一个方法,如果是就将参数传入并执行install方法,完成插件的安装
  • 如果plugin是一个方法,就直接执行
  • 最后将plugin推入上述声明的数组中,表示插件已经安装
  • 最后返回Vue实例
25、Vue.extend 是什么

【】

26、new Vue() 做了什么

【】合并配置

【】初始化生命周期

【】初始化事件

【】初始化render函数

【】调用 beforecreate钩子函数

【】初始化state,包括data、props、computed

【】调用 created 钩子函数

【】然后按照生命周期,调用 vm.$mount 挂载渲染

27、vue 项目性能优化

【】v-if 和 v-show 区分使用场景

【】v-for 遍历添加 key 值

【】事件的销毁

【】图片资源懒加载

【】路由懒加载

【】第三方插件的懒加载

【】服务端渲染 or 预渲染

28、Vue2.x 与 Vue3 区别

【】生命周期变化

【】使用 proxy 代替 defineProperty

【】diff 算法提升

【】typeScript 支持

【】打包体积变化

【】其他 API 和功能的改动

29、Vue2 与 Vue3 双向数据绑定的区别

【】vue2 双向数据绑定存在的问题:

  • 对于对象,无法检测 property 的添加和删除
  • 对于数组,无法利用索引直接设置一个数组项,无法直接修改数组长度
  • 解决方法是使用 set 方法

【】set () 的原理

  • 目标是对象,就用 defineReactive 给新增的属性去添加 getter 和 setter
  • 目标是数组,就直接调用数组本身的 splice 方法去出发响应式

【】vue2 使用 Object.defineProperty 对象以及对象属性劫持 + 发布订阅模式,只要数据发生变化直接通知变化,并驱动视图的更新

 <input type="text" id="in"/> 输入的值为:<span id="out"></span>
var int = document.getElementById('in');
var out = document.getElementById('out');
// 定义一个对象
let data ={name:'tcy',age:'20'}
function observe(data){
	//获取所有的data数据对象中的所有属性进行遍历
    const keys = Object.keys(data)
    for (let i = 0; i < keys.length; i++) {
    	let val = data[keys[i]];
       defineReactive(data, keys[i],val)//为每个属性增加监听
    }
}
function defineReactive(obj,key,val){
   Object.defineProperty(obj, key, {
    enumerable: true,//可枚举
    configurable: true,//可配置
    get: function reactiveGetter () {
      //模拟get劫持
      console.log("get劫持");
      return val;
    },
    set: function reactiveSetter (newVal) {
       	//模拟set劫持
     console.log("set劫持,新值:"+newVal);
     val = newVal;
    }
  })
}
observe(data);
int.addEventListener('input', function(e) {
    data.name = e.target.value;
})
data.age=25 // 触发set方法 

【】Vue3.0 中的响应式采用了ES6中的 Proxy 方法,Proxy 对象用于定义基本操作的自定义行为

const p = new Proxy(target, handler);
  • 参数target表示要使用Proxy包装的对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
  • 参数handler是一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为
let obj = {age:18}
obj = new Proxy(obj, {
    get(target, property){
        return target[property]
    },
    set(target, property, value){
        if(target[property] === value) return
        target[property] = value
        observer()
    }
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值