当前位置: 首页 > Web前端 > vue.js

都2020年了,为什么Vue还这么火?

时间:2023-03-31 22:42:36 vue.js

作为中国程序员游雨溪开发的前端框架,它的出身曾为国人带来过荣耀。更重要的是,Vue比其他前端框架更易用,还可以与第三方库或现有项目集成,还可以为单页应用提供驱动。现在的行业俚语:会Vue前端的不是合格的前端工程师!之前很多朋友可能已经知道,Vue.js实现响应式的核心是使用ES5的Object.defineProperty,这也是Vue.js不兼容IE8及以下浏览器的原因。我们先对其进行一个直观的认识。知道。Object.definePropertyObject.defineProperty方法会直接在一个对象上定义一个新的属性,或者修改一个对象已有的属性,并返回这个对象。我们先看一下它的语法:obj是要在其上定义属性的对象;prop是要定义或修改的属性的名称;descriptor是要定义或修改的属性描述符。核心是描述符,它有很多可选的键值,具体可以参考它的文档。这里我们最关心的是get和set。get是为属性提供的getter方法,当我们访问该属性时会触发getter方法;set是为一个属性提供的setter方法,当我们修改属性的时候触发setter方法。一旦一个对象有了getter和setter,我们就可以简单地称这个对象为反应对象。那么Vue.js将哪些对象变成响应式对象呢?接下来,我们从源码层面进行分析。initState在Vue的初始化阶段,当_init方法执行时,会执行initState(vm)方法,定义在src/core/instance/state.js中。initState方法主要初始化props、methods、data、computed、wathcer等属性。这里重点分析props和data,后面会详细分析其他属性的初始化。initPropsprops初始化的主要过程是遍历定义好的props配置。遍历过程主要做了两件事:一是调用defineReactive方法将每个prop对应的value变成reactive类型,通过vm._props.xxx可以访问定义的props中对应的属性。对于defineReactive方法,我们后面会介绍;另一种是通过proxy将vm._props.xxx的访问代理到vm.xxx,后面会介绍。initDatadata初始化的主要过程是做两件事,一是遍历定义的data函数返回的对象,通过proxy将每个值vm._data.xxx代理到vm.xxx;另一种是调用observe方法,观察整个数据的变化,让数据也有响应,可以通过vm._data.xxx访问定义的数据返回函数中的相应属性,后面会介绍observe。可以看出,props和data的初始化都将它们变成了响应式对象。在这个过程中,我们接触到了几个函数。接下来,我们将对它们进行详细分析。Proxy首先介绍代理。proxy的作用是将props和data上的属性代理给vm实例。这就是为什么,例如,我们定义了以下道具,但我们可以通过vm实例访问它。我们可以通过say函数中的this.msg来访问我们在props中定义的msg。这个过程发生在代理阶段:代理方法的实现很简单,通过Object.defineProperty将对target[sourceKey][key]的读写变成了对target[key]的读写。所以对于props来说,vm._props.xxx的读写就变成了vm.xxx的读写,而对于vm._props.xxx我们可以访问props中定义的属性,所以我们可以通过vm。xxx访问了props中定义的xxx属性。同样,对于data,vm._data.xxxx的读写就变成了vm.xxxx的读写,而对于vm._data.xxxx我们可以访问data函数返回的对象中定义的属性,所以我们可以通过vm.xxxx访问data函数返回的对象中定义的xxxx属性。observe的作用是监听数据的变化。它的定义在src/core/observer/index.js中:observe方法的作用是给非VNode对象类型的数据添加一个Observer。如果已添加,则直接返回。否则,在满足某些条件时实例化一个Observer对象实例。接下来我们看一下Observer的作用。ObserverObserver是一个类,其作用是为对象的属性添加getter和setter,用于依赖收集和分发更新:Observer构造函数逻辑很简单,先实例化Dep对象,后面会介绍,然后执行def函数将自己的实例添加到数据对象值的__ob__属性。def的定义在src/core/util/lang.js中:def函数是一个很简单的Object.defineProperty的封装,这就是为什么我在开发的时候在data上输出object类型的数据,你会发现该对象有一个额外的__ob__属性。回到Observer的构造函数,接下来会判断value,对数组调用observeArray方法,否则对纯对象调用walk方法。可以看到observeArray遍历了数组,再次调用了observe方法,而walk方法遍历了对象的key,调用了defineReactive方法,那么我们来看看这个方法做了什么。defineReactivedefineReactive的作用是定义一个响应式对象,并为对象动态添加getters和setters。它的定义在src/core/observer/index.js中:defineReactive函数首先初始化Dep对象的实例,然后获取obj字符的属性描述,然后递归调用子对象上的observe方法,即确保无论obj的结构多么复杂,它的所有子属性也都可以成为响应式对象,这样我们就可以访问或修改obj中深度嵌套的属性,也可以触发getter和setter。最后使用Object.defineProperty为obj的属性键添加getter和setter。至于getters和setters的具体实现,我们后面会介绍。为了总结本节,我们介绍了响应式对象。核心是使用Object.defineProperty为数据添加getter和setter。目的是在我们访问和写入数据时自动执行一些逻辑:getter依赖于collection,setter所做的是调度更新。