作为前端开发中现行最火的框架之一,Vue 在面试中出现的频率不断增加。基于此,总结了一些 Vue 方面经常出现的面试题,留给自己查看消化,也分享给有需要的小伙伴。
就算工作时间再久,不刷题,是不能那么容易过面试的。我相信就算你是面试官,也不会百分百了解你所问的问题,也不能做到面面俱到。我一直相信,成功的面试都是双方的缘分到了。缘分到了,自然水到渠成。
1.vue解决了什么问题
- 不用大量地操作DOM,把重点放到处理数据和业务逻辑上(数据和视图分离,数据驱动视图),可能提高了编码效率,更快的实现业务。
- 解决了工程化,模块化的问题,更方便的组织和构建复杂应用。
- 提供统一ui库,提升开发效率。
- 更加可维护。
2.Vue设计原则理解
- 渐进式js框架
- 易用、灵活、高效
渐进式
与其他大型框架不同,自底向上逐层应用。核心库只关注视图层,易于上手,还便于与第三方库和自有项目整合。
渐进式在于,如果只是单页应用,完全可以直接引入Vue来开发;如果应用程序有了一定的规模,我们可以考虑引入vue-router路由;如果需要维护很多公共的状态,那么可以引入vuex;如果要做大型应用,我们可以引入Vue-cli脚手架等等。vue的全家桶就体现了渐进式的思想。
易用性
响应式和申明式的模板语法便于快速上手,不需要管底层原理,只要会html、js、css直接就可以开发应用。
灵活性
渐进式的思想最大优点就是灵活。不管是构建大型应用、还是只开发单页、还是与既有项目整合。
高效性
超快的虚拟DOM和diff算法使得我们的应用拥有较高的性能表现。Vue后续版本也得以体现,比如使用Proxy,比如优化diff算法。
3.Vue数据为什么是异步更新?
vue是组件级更新,也就是说,每一次的更新都是渲染整个组件。Vue组件中的每个data数据都会收集依赖,如果是同步的话,一旦修改了data
属性,便会触发对应的 watcher
,然后调用对应 watcher
下的 update
方法更新视图,那么会导致视图频繁更新,性能堪忧。
如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以为了性能, Vue 会在本轮数据更新后,在异步更新视图。这也是nextTick 产生的原因。异步渲染核心思想是 nextTick 。
作用:
nextTick 接收一个回调函数作为参数,并将这个回调函数延迟到DOM更新后才执行,减少操作DOM的次数
使用场景:想要操作 基于最新数据生成的DOM 时,就将这个操作放在 nextTick 的回调中;
实现原理
将传入的回调函数包装成异步任务,异步任务又分微任务和宏任务(setTimeout、promise那些),定义了一个异步方法,多次调用nextTick会将方法存入队列,通过异步方法清空当前队列。
异步更新是Vue会在本轮数据更新后,再去异步更新视图。这也是为了提高性能的考虑。具体实现是:只要侦听到数据变化,Vue 将开启一个队列,将在同一事件循环中发生的所有数据变更进行缓存。如果同一个 watcher 被多次触发,只会被推入到队列中一次。最终执行队列中的run方法更新视图,这里涉及到nextTick。所以相同的watcher最终只会更新一次。
nextTick相当于是一个防抖操作,但类似于setTimeout(flushCallbacks, 0)
,它的防抖并不是说某一个时间段内的任务只执行一次。而是等到所有主线程的宏任务都执行完才去执行任务队列中的任务。而任务队列的执行顺序是优先微任务的,所以首选promise
。不支持promise
的话再用MutationObserver
,如果都不支持,再考虑异步宏任务setImmediate
(高版本IE),再不济只能用setTimeout 0
4. 解释单向数据流和双向数据绑定
单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。数据只能从⼀个⽅向来修改状态。
vue 组件间传递数据是单向的,即数据总是由父组件传递到子组件,子组件在其内部可以有自己维护的数据,子组件无权修改父组件传递给它的数据。这样做是为了组件间更好的解耦,在开发中可能有多个子组件依赖于父组件的某个数据,假如子组件可以修改父组件数据的话,一个子组件变化会引发所有依赖这个数据的子组件发生变化。而单向数据流会防止从子组件意外改变父级组件的状态而导致的数据混乱,让开发变得复杂。
缺点就是写起来不太方便。如在Vuex中要使UI发生变更就必须创建各种 action
来维护对应的 state
。子组件要改变父组件状态时只能通过$emit
方法触发父组件相应的事件来实现。
双向数据绑定:即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。双向数据绑定就是在单向绑定的基础上给输入框元素(input、textare等)添加了 change(input) 事件,来动态修改数据和视图。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。
5.对 MVC、MVP、MVVM的理解
两者都是框架模式,设计目标为了解决view和model的耦合问题,解决代码分层,解决维护性问题。
MVC:Model
代表数据模型,数据Model层中定义;View
代表UI视图,负责数据的展示;Controller
负责业务逻辑处理。
早起专注于服务端(后端),当时ajax还没有火起来,这时前后端虽然有一些分离,但依然绑定在一起。如java的springMVC、ASP.net、PHP的mvc等,前端的backBonejs。优点是分层清晰。缺点是数据流混乱、控制层臃肿,代码不易读,不易维护,灵活性依然有问题。
View
传送指令到Controller
Controller
完成业务逻辑后,要求Model
改变状态Model
将新的数据发送到View
,用户得到反馈- 所有通信都是单向的,最后controller会很臃肿,不易维护。
MVP
MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理。MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
MVVM:分为Model、View、ViewModel三者
这种模式不仅解决了耦合性问题,而且通过Viewmodel层数据和视图的映射关系,减少了很多繁琐的代码,尤其是DOM操作的代码。在提高开发效率,可读性的同时,还保持了优越的性能。
- Model 代表数据模型,数据和业务逻辑都在Model层中定义;
- View 代表UI视图,负责数据的展示;
- ViewModel-数据响应层,负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;
- Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。
- 这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。
Vue中的MVVM模式理解
MVVM是由MVC发展而来的。两者都以数据为核心,MVC最初的用意是为了将视图和逻辑层分离。MVVM比MVC的的最大优势在于MVVM把大量的与页面视图相关的逻辑单独抽离出来(viewModel)构成了一个库。而Vue就是一个vm(viewModel)库。最简单的就是v-model指令,把数据与输入框做一个关联,不需要自己再去监听,Vue内部帮我们搞定。viewModel最多体现在Vue的各种指令上。
MVVM模式在react中的对应关系
- M(odel):对应组件的方法或生命周期函数中实现的业务逻辑和this.state中保存的本地数据,如果React集成了redux +react-redux,那么组件中的业务逻辑和本地数据可以完全被解耦出来单独存放当做M层,如业务逻辑放在Reducer和Action中。
- V(iew)-M(odel):对应组件中的JSX,它实质上是Virtual DOM的语法糖。React负责维护 Virtual DOM以及对其进行diff运算,而React-dom 会把Virtual DOM渲染成浏览器中的真实DOM
- View:对应框架在浏览器中基于虚拟DOM生成的真实DOM(并不需要我们自己书写)以及我们书写的CSS
- 绑定器:对应JSX中的命令以及绑定的数据,如className={ this.props.xxx }、{this.props.xxx}等等
MVVM的双绑和单绑区别
- 一般只有UI表单控件才存在双向数据绑定,非UI表单控件只有单向数据绑定。
- 单向数据绑定是指:M的变化可以自动更新到ViewModel,但ViewModel的变化需要手动更新到M(通过给表单控件设置事件监听)
- 双向数据绑定是指念:M的变化可以自动更新到ViewModel,ViewModel的变化也可以自动更新到M
- 双向绑定 = 单向绑定 + UI事件监听。双向和单向只不过是框架封装程度上的差异,本质上两者是可以相互转换的。
优缺点:在表单交互较多的情况下,单向数据绑定的优点是数据更易于跟踪管理和维护,缺点是代码量较多比较啰嗦,双向数据绑定的优缺点和单向绑定正好相反。
MVVM的优点
MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也观察不到View,这种低耦合模式提高代码的可重用性。
6.Vue组件化理解
组件是独立的可复用的代码组织单元。组件化是便于复用、测试和维护。而且可以实现分而治之,大幅提高开发效率。
组件系统是Vue的核心特性之一。是一种规范,这种规范使得开发变得更可控。他使得开发者可以使用小型的可复用的组件来构建大型应用。
这种规范,使得组件之间相互影响制约,更好的进行团队协作。包括布局和样式可以独立、解耦。
Vue的更新粒度是组件级别的,组件的数据变化只会影响当前组件的更新,但是在组件更新的过程中,也会对子组件做一定的检查,判断子组件是否也要更新,并通过某种机制避免子组件重复更新。
组件分为:页面组件、业务组件(如登录框)、通用组件(如按钮、弹窗等UI组件)。
组件开发应该是高内聚(更加独立)、低耦合(组件之间不应有太多依赖关系)的。
Vue组件是基于配置的。我们通常写的组件是配置选项而非组件实例。框架后期会生成对应的构造函数。他们基于VueComponent,是Vue的扩展。
vue组件的构造函数在内部通过extend来创建,创建构造函数时会继承Vue且传入当前vue实例,Vue每一个组件都是一个Vue的实例。组件实例是继承自Vue的。
全局组件会立刻调用extend生成构造函数,在当前Vue实例化之前就已经创建了。而局部组件在运行时某个时刻才会生成。
合理使用组件能提升性能:每一个组件在实例化时(mountComponent)都会实例化自己的Watcher,每一个watchar中都有其更新函数。这样每次更新时只更新当前组件本身。所以应该尽量地细粒化组件,提高渲染的性能(这样每次更新视图时打补丁的范围就比较小了)。
组件有父子组件、根实例,组件或路由切换避免丢失状态。
单文件Vue的组件不仅仅是DOM层面的封装。也包含了组件的方法、逻辑、数据、样式。
单文件组件并不是实例的直接导出,而是经过webpack的vue-loader,将vue后缀的文件进行编译,最终导出的是js对象(组件配置对象而非构造函数)。
Vue组件常用的功能有:属性prop、插槽slot、自定义事件等,通常用于组件通信和扩展。
Vue组件遵循单向数据流原则。
7. 对比 原生或jQuery与Vue 有什么不同
原生专注视图层,通过操作 DOM 去实现页面的一些逻辑渲染;
Vue 专注于数据层,通过数据的双向绑定,最终表现在 DOM 层面,减少了 DOM 操作。更直白来说就是不操作DOM,用数据来渲染,通过虚拟的抽象数据层来直接更新页面。当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去操作dom。相当于数据与DOM之间做了一个映射。更简单,更方便,程序员只需要关注核心的业务逻辑和数据变化,不需要关注诸如DOM操作等其他层面。
Vue 使用了组件化思想,提高了开发效率,方便复用,便于协同开发。
Vue的核心是数据驱动,组件系统。
jquery是以程序逻辑为重,事件驱动。所谓的事件驱动简单来说就是用户通过点击,修改,删除,输入等等,来操作DOM,并触发对应的事件,然后通过后台响应处理,随之更新UI。
具体:
- jquery是使用选择器()选取DOM对象,对其进行赋值、取值、事件绑定等操作,和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。jquery侧重样式操作,动画效果等;可以应用于一些html5的动画页面,一些需要js来操作页面样式的应用。
- Vue 则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的 DOM 对象,他们通过 Vue 对象这个 vm 实现相互的绑定。这就是传说中的 MVVM。vue侧重数据绑定,可以应用于复杂数据操作的后台页面。
8.Vue组件化优势
每一个组件都是一个实例,每一个实例都可以作为一个组件挂载到一个实例上。每个组件是一个vueComponent的实例。方便我们进行单文件组件开发。
- 提高开发效率
- 方便重复使用
- 简化调试步骤,更快聚焦问题
- 提升项目的可维护性
- 便于多人协同开发
9.Vue 等单页面应用的优缺点
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点:
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染。良好的交互体验。
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;便于提高开发效率。后端不再负责模板渲染、输出页⾯⼯作,后端API通⽤化,即同⼀套后端程序代码,不⽤修改就可以⽤于Web界⾯、⼿机、平板等多种客户端。
- 单页应⽤没有页⾯之间的切换,就不会出现“⽩屏现象”,也不会出现假死并有“闪烁”现象,用户体验及交互比较流畅。
- 组件化开发,有利于复用和维护。
- 只有一个Html,前端js承担了页面所有切换和渲染,相对服务器压⼒⼩,服务器只⽤出数据就可以,不⽤管展⽰逻辑和页⾯合成,吞吐能⼒会提⾼⼏倍。
缺点:
- 首屏加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
- 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理
- SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
- 容易造成Css命名冲突。
- 页⾯的复杂度很⾼,需要⼀定的技能⽔平,开发成本⾼
10. 单页⾯(SPA)和多页⾯区别
- 单页应⽤ 页⾯跳转---->js渲染,整个项目只有一个Html文件,优点:页⾯切换快 缺点:⾸屏加载稍慢,seo差
- 多页应⽤ 页⾯跳转---->返回html 优点:⾸屏时间快,seo效果好 缺点:页⾯切换慢
11.理解虚拟DOM
浏览器工作流程大致分5步:构建DOM树 –> 创建样式规则Style Rules -> 构建渲染树Render tree -> 布局Layout –> 绘制页面。
源生操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍。比如当你在一次操作时,需要更新10个DOM节点,理想状态是一次性构建完DOM树,再执行后续操作。但浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,所以最终执行10次流程。
虚拟DOM就是为了解决这个浏览器性能问题而被设计出来的。例如前面的例子,假如一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性附到DOM树上,通知浏览器去执行绘制工作,这样可以避免大量的无谓的计算量。
真实的DOM节点,包含着很多属性。虚拟DOM是用js对象模拟DOM节点,好处是:页面的更新可以先全部反映在js对象上,操作js对象的速度显然要快多了。等对象操作完成再一次性渲染。
12.Vue虚拟DOM和diff算法
虚拟dom
使用JS对象来模拟DOM结构,就是所谓的虚拟dom。由于dom操作非常昂贵(吃性能),所以把DOM变化的对比,放在JS层来做,页面的更新可以先全部反映在js对象上,操作js对象的速度显然要快多了。等对象操作完成再一次性渲染,提高dom渲染效率。
由于渲染真实DOM的开销很大,有时候我们修改了某个数据,如果直接渲染到真实dom上会引起整个dom树的重绘和重排,如果想要只更新我们修改的那一小块dom而不要更新整个dom,就用到了虚拟dom和diff算法。
diff算法
diff算法即差异查找算法。对于DOM结构即为tree(dom树)的差异查找算法。
diff算法是虚拟DOM的必然产物。通过新旧虚拟DOM的对比,将最终的变化反映到真实DOM上。
diff算法是⼀种通过同层的树节点进⾏⽐较的⾼效算法,避免了对树进⾏逐层搜索遍历,所以时间复杂度只有 O(n)。
而vue采用虚拟dom形式模拟真实dom,故其差异查找实质是对两个JavaScript对象的差异查找。
Vue为什么使用diff
因为vue中Watcher粒度的降低,一个组件对应一个watcher,只有引入diff才能精准地找到发生变化的位置。
diff算法有两个⽐较显著的特点
- ⽐较只会在同层级进⾏, 不会跨层级⽐较。
- 在diff⽐较的过程中,循环从两边向中间收拢。
Vue的diff过程(阐述1)
当数据发生改变时,set方法会让调用Dep.notify
通知所有订阅者Watcher,内部会尝试将Watcher添加到异步更新队列,在每一次事件循环结束时会清空这些队列。
这时所有的watcher尝试执行其对应的更新函数,更新函数调用了组件的渲染函数和更新函数。这时会重新生成最新的虚拟DOM,然后执行更新函数比较新旧虚拟DOM,这时是真正的diff执行时刻,这个过程称为patch(打补丁),更新相应的视图。
diff调用名为patch
的函数,比较新旧节点,一边比较一边给真实的DOM打补丁。(patch意为补丁)。
diff算法采用:深度优先,同层比较的策略。
- 两个节点先判断是否都拥有子节点或文本节点然后做不同的操作
- 比较两组子节点的算法是diff的核心。首先假设子节点的头尾节点可能相同,做比对尝试,减少循环次数。
- 如果没有相同节点则按照通用方式遍历查找。借助key的方式可以高效得找到相同节点。
- 当找不到相同节点时,再按情况处理剩余节点。剩余的节点要么是批量删除,要么是批量新增。
比较只会在同层级进行, 不会跨层级比较。
Vue的diff过程(阐述2)
⾸先定义 oldStartIdx、newStartIdx、oldEndIdx 以及 newEndIdx 分别是新⽼两个 VNode 的两边的索引。
接下来是⼀个 while 循环,在这过程中,oldStartIdx、newStartIdx、oldEndIdx 以及 newEndIdx 会逐渐向中间靠拢。while 循环的退出条件是直到⽼节点或者新节点的开始位置⼤于结束位置。
while 循环中会遇到四种情况:
- 情形⼀:当新⽼ VNode 节点的 start 是同⼀节点时,直接 patchVnode 即可,同时新⽼ VNode 节点的开始索引都加 1。
- 情形⼆:当新⽼ VNode 节点的 end 是同⼀节点时,直接 patchVnode 即可,同时新⽼ VNode 节点的结束索引都减 1。
- 情形三:当⽼ VNode 节点的 start 和新 VNode 节点的 end 是同⼀节点时,这说明这次数据更新后 oldStartVnode 已经跑到了oldEndVnode 后⾯去了。这时候在 patchVnode 后,还需要将当前真实 dom 节点移动到 oldEndVnode 的后⾯,同时⽼ VNode 节点开始索引加 1,新 VNode 节点的结束索引减 1。
- 情形四:当⽼ VNode 节点的 end 和新 VNode 节点的 start 是同⼀节点时,这说明这次数据更新后 oldEndVnode 跑到了oldStartVnode 的前⾯去了。这时候在 patchVnode 后,还需要将当前真实 dom 节点移动到 oldStartVnode 的前⾯,同时⽼ VNode节点结束索引减 1,新 VNode 节点的开始索引加 1。
while 循环的退出条件:直到⽼节点或者新节点的开始位置⼤于结束位置。
- 情形⼀:如果在循环中,oldStartIdx⼤于oldEndIdx了,那就表⽰oldChildren⽐newChildren先循环完毕,那么newChildren⾥⾯剩余的
节点都是需要新增的节点,把[newStartIdx, newEndIdx]之间的所有节点都插⼊到DOM中 - 情形⼆:如果在循环中,newStartIdx⼤于newEndIdx了,那就表⽰newChildren⽐oldChildren先循环完毕,那么oldChildren⾥⾯剩余
的节点都是需要删除的节点,把[oldStartIdx, oldEndIdx]之间的所有节点都删除
13.虚拟dom的作用(目的)
什么是虚拟DOM?
虚拟DOM其实就是⼀个JavaScript对象。通过这个JavaScript对象来描述真实DOM。
虽然虚拟dom通过diff算法,再利用vue数据异步更新机制, 能够尽可能地减少整个dom的重绘和频繁的渲染。除了将dom转为vdom,然后还要执行diff算法,最终的渲染还是要操作真实dom,所以效率并没有很高。而vue官方也从来没说过虚拟DOM效率有多高。
虚拟dom和diff算法只有在dom元素剧烈变化的时候才会体现他的好处:可以局部替换HTML标签(替换 vnode)。
虚拟dom的作用
- 由于虚拟dom和真实dom很相似。而虚拟dom是js对象,这就可以实现组件的高度抽象化。
- 可以适配 DOM 以外的渲染目标。
- 不用再依赖html解析器进行模板解析。为框架跨平台提供了可能。比如React Native、weex、服务端渲染(ssr)。
- 提高渲染性能。
虚拟 dom 为什么会提⾼性能?
真实DOM的操作,⼀般都会对某块元素的整体重新渲染,采⽤虚拟DOM的话,当数据变化的时候,只需要局部刷新变化的位置就好了,虚拟dom相当于在js和真实dom中间加了⼀个缓存,利⽤dom diff算法避免了没有必要的dom操作,减少了整个dom的重绘和频繁的渲染,从⽽提⾼性能。
- 局部更新节点数据
- 新旧js对象进行diff,找到差异节点局部刷新。避免了没有必要的dom操作
虚拟 dom 具体实现步骤
- ⽤ JavaScript对象结构表⽰ DOM树的结构;然后⽤这个树构建⼀个真正的 DOM树,插到⽂档当中。
- 当状态变更的时候,重新构造⼀棵新的对象树。然后⽤新的树和旧的树进⾏⽐较,记录两棵树差异。
- 把记录的差异应⽤到先前(步骤1)所构建的真正的DOM树上,视图实现更新。
14. defineProperty数据劫持后如何通知数据和视图更新的
vue的双向绑定是由数据劫持结合发布者-订阅者模式实现的,那么什么是数据劫持?vue是如何进⾏数据劫持的?说⽩了就是通过Object.defineProperty()来劫持对象属性的setter和getter操作,在数据变动时做你想要做的事情。
我们已经知道实现数据的双向绑定,⾸先要对数据进⾏劫持监听,所以我们需要设置⼀个监听器Observer,⽤来监听所有属性。如果属性发⽣变化了,就需要告诉订阅者Watcher看是否需要更新。
因为订阅者是有很多个,所以我们需要有⼀个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进⾏统⼀管理的。
接着,我们还需要有⼀个指令解析器Compile,对每个节点元素进⾏扫描和解析,将相关指令(如v-model,v-on)对应初始化成⼀个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执⾏对应的更新函数,从⽽更新视图。因此接下去我们执⾏以下3个步骤,实现数据的双向绑定:
- 实现⼀个监听器Observer,⽤来劫持并监听所有属性,如果有变动的,就通知订阅者。
- 实现⼀个订阅者Watcher,每⼀个Watcher都绑定⼀个更新函数,watcher可以收到属性的变化通知并执⾏相应的函数,从⽽更新视图。
- 实现⼀个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显⽰在视图上,然后初始化相应的订阅者(Watcher)。
本文固定连接:https://code.zuifengyun.com/2020/02/1608.html,转载须征得作者授权。