分享更有价值
被信任是一种快乐

Vue.js模版和数据是怎么被渲染成DOM的

文章页正文上

本篇内容介绍了“Vue.js模版和数据是怎么被渲染成DOM的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言Vue.js 一个核心思想是数据驱动。也就是说视图是由数据驱动生成的,我们对视图的修改,不会直接操作 DOM,而是通过修改数据。当交互复杂的时候,只关心数据的修改会让代码的逻辑变的非常清晰,因为 DOM 变成了数据的映射,我们所有的逻辑都是对数据的修改,而不用碰触 DOM,这样的代码非常利于维护。在 Vue.js 中我们可以采用简洁的模板语法来声明式的将数据渲染为 DOM:结果页面上会展示出Hello world!。这是入门vue.js的时候就知道的知识。那么现在要问vue.js的源码到底做了什么,才能让模版和数据最终被渲染成了DOM???从 new Vue() 开始在写vue 项目的时候,会在项目的入口文件 main.js文件里实例化一个vue 。如下:Vue 就是一个用 Function 实现的类。源码如下:在src/core/instance/index.js中当我们在项目中 new Vue({})传入一个对象的时候,其实就是执行的上面的方法,并传入参数为 options ,然后调用了this._init(options)方法。该方法在src/core/instance/init.js文件中。代码如下:由以上代码可知 this._init(options)主要是合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等。重要的部分在代码里做里注释。那么接下来依然从其中一个功能为例进行分析:以initState(vm)为例:为什么在钩子函数里可以访问到 data 里定义的数据?vue 项目中,当定义了 data 就可以在组件的钩子函数 或者 在 methods 函数里都可以访问到data 里定义的属性。这是为什么??分析源码:可以看到this._init(options)方法,在初始化函数部分有一个 initState(vm)函数。该方法实在./state.js中:具体代码如下:在initState方法中判断:如果定义了data,就初始化data;继续看初始化data 的函数:initData(vm)。代码如下:综上:初始化 data 实在./state.js文件里。执行initState() 方法,该方法判断如果定义了data,就初始化data。如果data 是一个function,就执行了getData()方法return data.call(vm, vm)。然后对 vm 上的 data 里定义的属性、vm上的 props 、vm上的methods里的属性进行循环比对,如果在data 上定义的属性,就不能在props与methods在定义该属性。因为不管是data里定义的,在props里定义的,还是在medthods里定义的,最终都挂载在vm实例上了。见proxy(vm, _data, key)。然后通过proxy 方法给vm 上的属性做了Getter 和 Setter 方法的绑定。回到上述的问题,当访问this.msg 实际是访问 vm._data.msg。因此在钩子函数里确实可以访问到 data 里定义的数据了。不得不在说一遍,Vue 的初始化逻辑写的非常清楚,把不同的功能逻辑拆成一些单独的函数执行,让主线逻辑一目了然,这样的编程思想是非常值得借鉴和学习的。其它初始化的内容大家可以自己补充,接下来看挂载vm。在初始化的最后,检测到如果有 el 属性,则调用 vm.$mount 方法挂载 vm,挂载的目标就是把模板渲染成最终的 DOM,那么接下来探究 Vue 的挂载过程吧Vue 实例挂载的实现Vue 中我们是通过 $mount 实例方法去挂载 vm 的。接下来要探究执行$mount(‘#app’)的时候,源码都干了什么???$mount 方法在多个文件中都有定义,如 src/platform/web/entry-runtime-with-compiler.js、src/platform/web/runtime/index.js、src/platform/weex/runtime/index.js。因为 $mount 这个方法的实现是和平台、构建方式都有关系。就选取 compiler 版本的 $mount 分析吧,文件地址在src/platform/web/entry-runtime-with-compiler.js,代码如下:读代码可知,代码首先获取了 vue 原型上的 $mount 方法,将其存在变量mount中,然后重新定义了该方法。该方法对传入的el做了处理,el 可以是个字符串,也可以是DOM 对象。然后调用了 query()方法,该方法在./util/index文件中。主要是调用原生的DOM api querySelector() 方法。最后将el转化为一个DOM 对象返回。上述只贴出了主要的代码部分。源码了还对el进行了判断,判断传入的el 是否为body 或者 html ,如果是,就会在开发环境报一个警告。vue 不可以直接挂载到body 和html上 ,因为会被覆盖,当覆盖了 html 或 body 整个文档就会报错。源码还获取到 $options 判断是否定义render方法。如果没有定义 render 方法,则会把 el 或者 template 字符串最终将编译为render()函数。最后 return mount.call(this, el, hydrating)。此处的mount是vue 原型上的 $mount 方法。在文件./runtime/index。代码如下:其中参数 el 表示挂载的元素,它可以是字符串,也可以是一个DOM 对象。如果是字符串在浏览器环境下会调用 query() 方法转换成 DOM 对象。第二个参数是和服务端渲染相关,在浏览器环境下我们不需要传第二个参数。最后return 的时候调用了mountComponent()方法。该方法定义在src/core/instance/lifecycle.js,代码如下:读代码可知,该方法首先实例化一个渲染Watcher,在它的回调函数中会调用 updateComponent 方法,在此方法中调用 vm._render() 方法先生成虚拟DOM节点,最终调用 vm._update 更新 DOM。最后判断为根节点的时候设置 vm._isMounted 为 true, 表示这个实例已经挂载了,同时执行 mounted 钩子函数。 vm.$vnode 表示 Vue 实例的父虚拟节点,所以它为 Null 则表示当前是根 Vue 的实例。那么vm._render()是怎样生成虚拟DOM节点的呢?_render()渲染虚拟DOM 节点在 Vue 2.0 版本中,所有 Vue 的组件的渲染最终都需要 render()。Vue 的 _render() 是实例的一个私有方法,它用来把实例渲染成一个虚拟DOM节点。它的定义在 src/core/instance/render.js 文件中,代码如下:上述代码 从vue实例的 $options 上获取到 render 函数。通过call()调用了_renderProxy和 createElement()方法,先来探索createElement()方法。createElement()createElement()是在initRender()中。如下:initRender()是在 _init过程中执行了initRender()见 ./init.js 文件中的 initRender(vm)传入vm。在 vue 项目实际开发中,手写 render 函数 案例如下:因为是手写的render函数省去了将 template 编译为 render函数的过程,因此性能更好。接下来看_renderProxy方法:_renderProxy_renderProxy方法,也是在 init 过程中执行的。见文件./init.js中,代码如下:如果当前环境为生产环境 就将 vm 直接赋值给 vm._renderProxy;如果当前环境为开发环境,则执行initProxy()。该函数在./proxy.js文件中,代码如下:首先判断浏览器是否支持 proxy。它是ES6 新增的,用于给目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。如果浏览器不支持 proxy, 就将 vm 直接赋值给 vm._renderProxy;如果浏览器支持 proxy,就执行new Proxy()。综上所述:vm._render 是通过执行 createElement 方法并返回虚拟的DOM 节点。那么什么是虚拟的DOM呢???虚拟的DOM在探究vue 的虚拟DOM 之前,先推荐一个虚拟DOM开源库。有时间,有兴趣的朋友可以去深入了解。它是用一个函数去表示一个应用程序的视图层。view.js 是借鉴它实现了虚拟DOM。从而大大的提升了程序的性能。接下来我们就来看vue.js是怎么做的。vnode 的定义在 src/core/vdom/vnode.js文件中,如下:虚拟DOM 是个js对象,是对真实DOM 的一种抽象描述,比如标签名、数据、子节点名等。因为虚拟DOM只是用来映射真实DOM的渲染,所以不包含操作DOM的方法操作DOM的方法。因此更加的轻量,更加的简单。因为虚拟DOM 的创建是通过createElement方法,那这个环节又是如何实现的呢???createElementVue.js 利用 crea免费云主机、域名teElement 方法创建 DOM节点,它定义在 src/core/vdom/create-elemenet.js文件中,代码如下:createElement 方法是对 _createElement 方法的封装,它允许传入的参数更加灵活,在处

相关推荐: node的express有哪些作用

这篇文章主要讲解了“node的express有哪些作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“node的express有哪些作用”吧! node的express可以方便、快速的创建Web网站的服务器或AP…

文章页内容下
赞(0) 打赏
版权声明:本站采用知识共享、学习交流,不允许用于商业用途;文章由发布者自行承担一切责任,与本站无关。
文章页正文下
文章页评论上

云服务器、web空间可免费试用

宝塔面板主机、支持php,mysql等,SSL部署;安全高速企业专供99.999%稳定,另有高防主机、不限制内容等类型,具体可咨询QQ:360163164,Tel同微信:18905205712

主机选购导航云服务器试用

登录

找回密码

注册