We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
这是我小伙伴面试遇到的题目,突然想起我从vue1.5用到vue2.5,有两年的都是已vue为伴,虽然断断续续看过vue的源码,但是没有想过遇到该面试题时候,该怎么答?
以下为我第一时间想到的回答:
说起vue是如何实现其双向绑定功能的,就一定要提到ES5中提供的Object.defineProperty方法,能够为对象的属性设置get和set方法,在属性进行读取以及修改的时候可以执行框架的代码。在该框架代码里面会有一个Dep对象(就是一个收集依赖的对象),当属性被读取的时候,会触发get方法里面的注入代码,当有watcher(观察者)存在的时候,Dep就会收集这些watcher(观察者)。而在属性被修改赋值的时候,会触发set方法里面注入的代码,其发现属性值被修改后,会通知Dep里面收集到watcher(观察者),由其去执行相应的代码。
ES5
Object.defineProperty
get
set
而watcher的存在是通过vue提供的$watcher方法来生成watcher对象,而渲染函数render就是首先被定义为一个watcher,并且还是其回调。在渲染函数render执行的过程中,会触发到相应属性的get方法,从而被每一个触发到的属性的Dep收集起来。以此,当这些属性发生修改的时候,触发set方法,就是触发了Dep收集到的watcher的回调,从而再次渲染。当然,这里需要解决包括watcher对象以及dep对象重复收集,以及渲染函数重复执行的问题。这vue在dep收集每个watcher时候,都会检查其id是否重复,从而避免重复收集。而在通知Dep收集的watcher对象,让其重新渲染的操作是异步的,它们会被放到一个队列里面,当然在执行前会根据watcher的id进行查重。这个队列是调用vue提供的$nextTick方法来执行,原理就是把这些任务放到mirctack或marctack中执行,当执行栈外空才去执行,提供性能。
而谈到模板渲染,在vue1.x起,很多vue使用者就使用template,当时读vue1.x的时候,发现采用大量的正则表达式是去处理template字符串,把tag,属性,事件提取出来,而最终从这些信息变成dom的没去了解。而到了vue2.x,虽然还是经常使用template,但是会通过vue-loader方法把template变成render方法,就是调用了$createElemt的Vnode方法,这个方法会把目标元素先变为一个VNode,在第一次渲染时,会调用dom提供的生成dom的方法,依据Vnode树,一个个生成出来。而在数据发生改变时候,render会执行,生成新的Vnode树,而这时这些MVVM其提供性能措施就主要这这里,框架会对比新旧Vnode的差异,然后仅根据这些差异修改现有的dom结构。而对比两个Vnode的差异就是各大框架的性能瓶颈了,而vue里基于github上一个开源的库snabbbar,在原有的基础上,根据vue控件的需要在vnode的各个钩子里面注入框架的方法。
snabbbar
这是第一反应,想到的。比不上那些边看文档,源码的回复。 迟点会更新个论文基本的答案。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
vue是如何实现双向绑定和模板渲染的
前言
以下为我第一时间想到的回答:
说起vue是如何实现其双向绑定功能的,就一定要提到
ES5
中提供的Object.defineProperty
方法,能够为对象的属性设置get
和set
方法,在属性进行读取以及修改的时候可以执行框架的代码。在该框架代码里面会有一个Dep对象(就是一个收集依赖的对象),当属性被读取的时候,会触发get
方法里面的注入代码,当有watcher(观察者)存在的时候,Dep就会收集这些watcher(观察者)。而在属性被修改赋值的时候,会触发set
方法里面注入的代码,其发现属性值被修改后,会通知Dep里面收集到watcher(观察者),由其去执行相应的代码。而watcher的存在是通过vue提供的$watcher方法来生成watcher对象,而渲染函数render就是首先被定义为一个watcher,并且还是其回调。在渲染函数render执行的过程中,会触发到相应属性的get方法,从而被每一个触发到的属性的Dep收集起来。以此,当这些属性发生修改的时候,触发set方法,就是触发了Dep收集到的watcher的回调,从而再次渲染。当然,这里需要解决包括watcher对象以及dep对象重复收集,以及渲染函数重复执行的问题。这vue在dep收集每个watcher时候,都会检查其id是否重复,从而避免重复收集。而在通知Dep收集的watcher对象,让其重新渲染的操作是异步的,它们会被放到一个队列里面,当然在执行前会根据watcher的id进行查重。这个队列是调用vue提供的$nextTick方法来执行,原理就是把这些任务放到mirctack或marctack中执行,当执行栈外空才去执行,提供性能。
而谈到模板渲染,在vue1.x起,很多vue使用者就使用template,当时读vue1.x的时候,发现采用大量的正则表达式是去处理template字符串,把tag,属性,事件提取出来,而最终从这些信息变成dom的没去了解。而到了vue2.x,虽然还是经常使用template,但是会通过vue-loader方法把template变成render方法,就是调用了$createElemt的Vnode方法,这个方法会把目标元素先变为一个VNode,在第一次渲染时,会调用dom提供的生成dom的方法,依据Vnode树,一个个生成出来。而在数据发生改变时候,render会执行,生成新的Vnode树,而这时这些MVVM其提供性能措施就主要这这里,框架会对比新旧Vnode的差异,然后仅根据这些差异修改现有的dom结构。而对比两个Vnode的差异就是各大框架的性能瓶颈了,而vue里基于github上一个开源的库
snabbbar
,在原有的基础上,根据vue控件的需要在vnode的各个钩子里面注入框架的方法。这是第一反应,想到的。比不上那些边看文档,源码的回复。
迟点会更新个论文基本的答案。
The text was updated successfully, but these errors were encountered: