前端面试Vue 高频原理篇+详细解答,还有105道vue面试题集合

本文介绍了一位技术专家分享的关于如何有效学习Web前端,特别是通过体系化的学习资料,包括MVC和MVVM模式的区别,Vue的响应式数据和生命周期管理。同时推荐了一份全面的学习资源包,以及跨平台开发技术Flutter的优势。
摘要由CSDN通过智能技术生成

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

  • 页面组成:由一个外壳页面包裹,多个页面(组件)片段组成

  • 跳转方式:在外壳页面中跳转,将片段页面(组件)显示或隐藏

  • 刷新方式:页面片段的局部刷新

  • 页面的数据跳转:组件间的传值比较容易

  • 跳转后的资源 不会重新加载

  • 缺点:对 SEO 搜索不太友好需要单独做配置,开发难度高一点需要专门的开发框架

iframe 实际上是 MPA,但是可以实现 SPA 的一些效果,但是本身由不少问题。

2.老生常谈之,为什么需要有这些 MVC/MVVM 模式?谈谈你对 MVC,MVVM 模式的区别,


目的:借鉴后端的思想,职责划分和分层

  • Vue, React 不是真正意义上的 MVVM 更不是 MVC,两者核心只处理视图层 view

MVC模式

单向的数据,用户的每一步操作都需要重新请求数据库来修改视图层的渲染,形成一个单向的闭环。比如 jQuery+underscore+backbone

  • M:model 数据存放层

  • V: view:视图层 页面

  • C: controller:控制器 js 逻辑层。

controller 控制层将数据层 model层 的数据处理后显示在视图层 view层,同样视图层 view层 接收用户的指令也可以通过控制层 controller,作用到数据层 model。所以 MVC的缺点是视图层不能和数据层直接交互。

MVVM模式

隐藏了 controller 控制层,直接操控 View 视图层和 Model 数据层。

  • M:model 数据模型

  • V: view 视图模板

  • VM:view-model 视图数据模板(vue处理的层,vue 中的definedProperty 就是处理 VM 层的逻辑)

双向的数据绑定:model 数据模型层通过数据绑定 Data Bindings 直接影响视图层 View,同时视图层 view 通过监听 Dom Listener 也可以改变数据模型层 model

  • 数据绑定和DOM事件监听就是 viewModelVue 主要做的事。也就是说:只要将 数据模型层Model 的数据挂载到 ViewModelVue 就可以实现双向的数据绑定。

  • 加上 vuex/redux 可以作为 vue和reactmodel 数据层。

var vm = new Vue()

复制代码

vm 就是 view-model 数据模型层,data:就是vm view-model 层所代理的数据。

  • 综上两者的区别:MVC 的视图层和数据层交互需要通过控制层 controller 属于单向链接。MVVM 隐藏了控制层 controller,让视图层和数据层可以直接交互 属于双向连接。

3. 说一下对 Vue 中响应式数据的理解


小tip:响应式数据指的是数据发生了变化,视图可以更新就是响应式的数据

  • vue 中实现了一个 definedReactive 方法,方法内部借用 Object.definedProperty() 给每一个属性都添加了 get/set 的属性。

  • definedReactive 只能监控到最外层的对象,对于内层的对象需要递归劫持数据。

  • 数组则是重写的7个 push pop shift unshift reverse sort splice 来给数组做数据拦截,因为这几个方法会改变原数组

  • 扩展:

// src\core\observer\index.js

export function defineReactive (

obj: Object,

key: string,

val: any,

customSetter?: ?Function,

shallow?: boolean

) {

// 准备给属性添加一个 dep 来依赖收集 Watcher 用于更新视图。

const dep = new Dep()

// some code

// observe() 用来观察值的类型,如果是属性也是对象就递归,为每个属性都加上get/set

let childOb = !shallow && observe(val)

Object.defineProperty(obj, key, {

enumerable: true,

configurable: true,

get: function reactiveGetter () {

// 这里取数据时依赖收集

const value = getter ? getter.call(obj) : val

if (Dep.target) {

dep.depend()

// childOb 是对对像进行收集依赖

if (childOb) {

childOb.dep.depend()

//这里对数组和内部的数组进行递归收集依赖,这里数组的 key 和 value 都有dep。

if (Array.isArray(value)) {

dependArray(value)

}

}

}

return value

},

set: function reactiveSetter (newVal) {

// 属性发生改变,这里会通知 watcher 更新视图

}

})

}

复制代码

上面的 Dep(类) 是用来干嘛的?答:用来收集渲染的 WatcherWatcher 又是一个啥东西?答:watcher 是一个类,用于更新视图的

4. Vue 是怎么检测数组的变化的?


  • vue 没有对数组的每一项用 definedProperty() 来数据拦截,而是通过重写数组的方法push pop shift unshift reverse sort splice

  • 手动调用 notify,通知 render watcher,执行 update

  • 数组中如果有对象类型(对象和数组)的话会进行数据拦截。

  • 所以通过修改数组下标和数组长度是不会进行数据拦截的,也就不会有响应式变化。例如arr[0] = 1, arr.length = 2 都不会有响应式

  • 扩展:

// src\core\observer\array.js

const methodsToPatch = [‘push’,‘pop’,‘shift’,‘unshift’,‘splice’,‘sort’,‘reverse’]

methodsToPatch.forEach(function (method) {

const original = arrayProto[method]

def(arrayMethods, method, function mutator (…args) {

const result = original.apply(this, args)

const ob = this.ob

let inserted

switch (method) {

case ‘push’:

case ‘unshift’:

inserted = args

break

case ‘splice’:

inserted = args.slice(2)

break

}

// 新增的类型再次观察

if (inserted) ob.observeArray(inserted)

// 手动调用 notify 派发更新

ob.dep.notify()

return result

})

})

复制代码

5.Vue 是怎样依赖收集的?(dep 和 Watcher 是什么关系)


tip:Dep 是一个用来负责收集 Watcher 的类,Watcher 是一个封装了渲染视图逻辑的类,用于派发更新的。需要注意的是 Watcher 是不能直接更新视图的还需要结合Vnode经过patch()中的diff算法才可以生成真正的DOM

  • 每一个属性都有自己的 dep 属性,来存放依赖的 Watcher,属性发生变化后会通知 Watcher 去更新。

  • 在用户获取(getter) 数据时 Vue 给每一个属性都添加了 dep 属性来(collect as Dependency)收集 Watcher。在用户 setting 设置属性值时 dep.notify() 通知 收集的Watcher 重新渲染。详情见上面的 defineReactive()

  • Dep依赖收集类 其和 Watcher类 是多对多双向存储的关系

  • 每一个属性都可以有多个 Watcher 类,因为属性可能在不同的组件中被使用。

  • 同时一个 Watcher 类 也可以对应多个属性。

6. Vue 中的模板编译


Vue中模板编译:其实就是将 template 转化成 render 函数。说白了就是将真实的 DOM(模板) 编译成虚拟 dom(Vnode)

  • 第一步是将 template 模板字符串转换成 ast 语法树 (parser 解析器),这里使用了大量的正则来匹配标签的名称,属性,文本等。

  • 第二步是对 AST 进行静态节点 static 标记,主要用来做虚拟 DOM 的渲染优化(optimize优化器),这里会遍历出所有的子节点也做静态标记

  • 第三步是 使用 ast语法树 重新生成 render 函数 代码字符串 code。(codeGen 代码生成器)

为什么要静态标记节点,如果是静态节点(没有绑定数据,前后不需要发生变化的节点)那么后续就不需要 diff 算法来作比较。

7. 生命周期钩子实现原理


  • vue 中的生命周期钩子只是一个回调函数,在创建组件实例化的过程中会调用对应的钩子执行。

  • 使用Vue.mixin({})混入的钩子或生命周期中定义了多个函数,vue 内部会调用mergeHook() 对钩子进行合并放入到队列中依次执行

  • 扩展

// src\core\util\options.js

function mergeHook (

parentVal: ?Array,

childVal: ?Function | ?Array

): ?Array {

const res = childVal

? parentVal

? parentVal.concat(childVal) // 合并

Array.isArray(childVal)

? childVal

[childVal]

parentVal

return res

? dedupeHooks(res)
res

}

复制代码

8.老生常谈之 vue 生命周期有哪些,一般在哪里发送请求?


  • beforeCreate: 刚开始初始化 vue 实例,在数据观测observer之前调用,还没有创建 data/methods 等属性

  • created: vue 实例初始化结束,所有的属性已经创建。

  • beforeMount: 在 vue 挂载数据到页面上之前,触发这个钩子,render 函数此时被触发。

  • mounted: el 被 创建的vm.$el替换,vue 初始化的数据已经挂载到页面之上,这里可以访问到真实的 DOM。一般会在这里请求数据。

  • beforeUpdate: 数据更新时调用,也就是在虚拟 dom 重新渲染之前。

  • updated: 数据变化导致虚拟 dom 发生重新渲染之后发生。

  • beforeDestroy: 实例销毁之前调用该钩子,此时实例还在。vm.$destroy 触发两个方法。

  • destroyed: Vue 实例销毁之后调用。所有的事件监听都会被接触。

请求数据要看具体的业务需求决定在哪里发送 ajax

9.Vue.mixin({})的使用场景和原理


  • 使用场景:用于抽离一个公共的业务逻辑实现复用。

  • 实现原理:调用 mergeOptions() 方法采用策略模式针对不同的属性合并。混入的数据和组件的数据有冲突就采用组件本身的。

  • Vue.mixin({}) 缺陷,1.可能会导致混入的属性名和组件属性名发生命名冲突;2. 数据依赖的来源问题

  • 扩展

export function mergeOptions (

parent: Object,

child: Object,

vm?: Component

): Object {

// some code

if (!child._base) {

if (child.extends) {

parent = mergeOptions(parent, child.extends, vm)

}

if (child.mixins) {

for (let i = 0, l = child.mixins.length; i < l; i++) {

parent = mergeOptions(parent, child.mixins[i], vm)

}

}

学习分享,共勉

题外话,毕竟我工作多年,深知技术改革和创新的方向,Flutter作为跨平台开发技术、Flutter以其美观、快速、高效、开放等优势迅速俘获人心

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
(let i = 0, l = child.mixins.length; i < l; i++) {

parent = mergeOptions(parent, child.mixins[i], vm)

}

}

学习分享,共勉

题外话,毕竟我工作多年,深知技术改革和创新的方向,Flutter作为跨平台开发技术、Flutter以其美观、快速、高效、开放等优势迅速俘获人心

[外链图片转存中…(img-5tyy8bCr-1713479617339)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-G9446b12-1713479617339)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值