学习总结:1.Vue第一次渲染的过程。在第一次渲染之前,首先初始化Vue,初始化实例成员和静态成员。初始化完成后,调用Vue的构造函数newVue(),在构造函数中调用_init()方法。这个方法相当于我们整个Vue的入口都在_init方法中,最后调用了$mount。总共有两个$mount。第一个定义在entry-runtime-with-compiler.js文件中,也就是我们的入口文件$mount,这个$mount()的核心作用是帮助我们将模板编译成render函数,但是它会首先判断当前是否传入了render选项,如果没有就获取我们的template选项,如果template选项没有的话,他会把el中的内容作为我们的模板,然后将模板编译成render函数.它使用compileToFunctions()函数帮助我们将模板编译成渲染函数。当render函数被编译时,它会将render函数存储在我们的options.render中。然后将调用src/platforms/web/runtime/index.js文件中的$mount方法。这种情况下会先重新获取el,因为如果是runtime版本,是不会经过entry-runtime-with-compiler的。js入口,所以如果是runtime版本,我们会在runtime/index.js的$mount()中重新获取el。接下来,调用在src/core/instance/lifecycle.js中定义的mountComponent()。在mountComponent()中,会先判断渲染选项。如果没有render选项,但是我们传入了模板,而且是当前在开发环境中,就会发出警告。目的是如果我们当前使用的是runtime版本的vue,而我们没有传入render,而是传入了一个template,它会告诉我们runtime版本不支持编译器。接下来会触发beforeMount生命周期中的钩子函数,也就是在挂载开始之前。然后定义updateComponent()。在这个函数中,调用了vm._render和vm._update。vm._render的作用是生成虚拟DOM。vm._update的作用是将虚拟DOM转化为真实DOM挂载到页面上面创建一个Watcher对象。创建Watcher时,会传递updateComponent函数。这个函数最终在Watcher内部被调用。get方法将在Watcher内部使用。Watcher创建时,会触发生命周期中挂载的钩子函数。在get方法中会调用updateComponent()完成挂载,最后返回Vue实例。2.vue响应式原理。Vue响应式的关键点是数据劫持/发布-订阅模式。更多介绍请参考Vue官网深入响应式原理部分。这里主要总结一下内部代码的实现。首先找出入口在哪(src/core/instance/init.js)initState(vm)-->initData(vm)-->observe()//初始化Vue实例的状态,初始化_props,methods,_data,computed,watch导出函数initState(vm:Component){vm._watchers=[]constopts=vm.$optionsif(opts.props)initProps(vm,opts.props)if(opts.methods)initMethods(vm,opts.methods)if(opts.data){initData(vm)//看这里}else{observe(vm._data={},true/*asRootData*/)}if(opts.computed)initComputed(vm,opts.computed)if(opts.watch&&opts.watch!==nativeWatch){initWatch(vm,opts.watch)}}//将数据属性注入Vue实例函数initData(vm){letdata=vm.$options.data//初始化_data,组件中的data是一个函数,调用函数返回结果,否则直接返回数据data=vm._data=typeofdata==='function'?getData(数据,虚拟机):数据||{}//...//响应式处理observe(data,true/*asRootData*/)}终于进入正题observe(value)响应式入口导出函数observe(alue:any,asRootData:?boolean){//判断value是否为对象if(!isObject(value)||valueinstanceofVNode){return}让ob:Observer|void//如果value有__ob__(observerobject)属性end(表示响应处理已经完成)if(hasOwn(value,'__ob__')&&value.__ob__instanceofObserver){ob=value.__ob__}elseif(shouldObserve&&!isServerRendering()&&(Array.isArray(value)||isPlainObject(value))&&Object.isExtensible(value)&&!value._isVue){//创建一个观察者对象ob=newObserver(value)}if(asRootData&&ob){ob.vmCount++}returnob//返回观察者对象}数据劫持exportclassObserver{value:any;//观察对象dep:Dep;//依赖对象vmCount:数量;//Instancecounterconstructor(value:any){this.value=valuethis.dep=newDep()this.vmCount=0//初始化实例的vmCount为0def(value,'__ob__',this)//将实例挂载到观察者对象的__ob__属性上//数组的响应式处理if(Array.isArray(value)){...//为数组中的每个对象创建一个观察者实例this.observeArray(value)}else{//遍历对象中的每一个属性并转化为setter/getterthis.walk(value)}}walk(obj:Object){//获取被观察对象的每一个属性constkeys=Object.keys(obj)//遍历每个属性并将其设置为响应式数据for(leti=0;i
