terribleness
terribleness
上一节我们分析了“Vue的编译过程:template、AST、Render过程”,通过这一步之后,Vue把template模板编译成了render可移植性函数。 这一节我们分析“Vue的虚拟节点:VNode、patch算法”。这一部分的目的是把render函数生成vnode虚拟节点,在更新时找到最小变化的dom结点,生成新的dom树。 我们看到’web/runtime.js’文件中,如下  vm.options.render存储了执行生成的render函数生成,接下来就是执行$mount函数了,我们把这一节分为两部分“Vnode”和“patch”,Vnode部分是分析render如何生成虚拟dom树,patch部分是如何获得新的dom。 Vnode 如上图我们进入’lifecycle.js’中查看mountComponet函数如下:  红框这句就包含了vnode和path两部分,其中vm._render是生成vnode的,vm._update是包含patch的。我们先查看vm._render函数内容。如下:  我们看到红框这句vnode = render.call(vm._renderProxy,vm.$createElement),我们先来看看render函数,如下:  其实render生成vnode的过程就是执行render函数,其中_c,_v,_s都是第一节“Vue扩展实例方法”定义好的,我们现在分别看看_c,_v,_s函数的内容,在’instance/render.js’函数中。  ### _s函数内容就是转换字符串过程 在’shared/utils’中能找到工具方法,如下:  ### _v函数是生成一个vnode结点 在’core/vdom/vnode.js’能找到方法,如下:  Vnode的内容时什么嗯,我们继续看。Vnode结构就是实际上一个html中元素可能存在的属性集合。如下:  ### _c就是生成一个vnode树 在第一个参数是html标签内容,第二个参数是vnode数组。所有最终生成的vnode树结构如下: ...
第三节Vue双向数据绑定:Observe、Watcher、Depd的关系”,关键是Object.defineProperty的set和get方法构造了订阅-发布模型。其中属性set方法的是在data、props、watch、computed等中赋值时发布更新,get方法是在编译template模板生成render函数后自动调用了get方法产生订阅watcher。 ## 那么template模板是如何编译成render函数的呢? 这一节我们主要分析Vue中编译过程:template、AST(抽象语法树)、render过程。 我们看到源代码中’instance/init.js’文件中,如下:  这个_init函数已经出现很多次了,我们上一篇文章,主要是分析了其中initState(vm)方法中如何构建双向数据绑定的,而Vue中的编译过程我们主要是看到最后一句 wm.$mount(vm.$options.el),在第一篇文章中,Vue扩展实例方法我们提到过Vue.prototype.$mount,在’runtime/index.js’文件中,如下:  那么如果编译过的template就会调用这个$mount函数去渲染页面,但是如果没有编译过的template呢,我们需要先看到’web/entry-runtime-with-compiler.js’文件,这里面会先去做template编译过程再调用$mount函数,如下:  第一个红框是先保存之前的$mount函数,也就是在’runtime/index.js’中定义的Vue.prototype.$mount函数,第三个红框是使用这个保存下来的mount函数继续执行,那么第二个红框就是我们这节需要分析的重点了,这就是Vue的编译过程。 我们进入到compileToFunctions函数中,如下:  再进入createCompiler中,如下:  这个createCompiler是createCompilerCreator函数的返回值,但是参数是一个baseCompile函数。进入createCompilerCreator函数中。  我们看到createCompilerCreator返回了一个createCompiler函数。这里有点绕,但是思路清晰一点,实际上是上上图中 function baseCompile函数实际在做编译工作,参数是vue的实例化的参数options,而上图中createCompiler函数中前一部分实际上是对options参数做了一个替换工作。所以实际编译工作看到baseCompile(template,finalOptions)这句话,对了这里要插入一句template的来历,因为一些面试题中提到,Vue实例化过程中,el属性和template和render都有内容时,实际渲染的html是以哪个为准?这个问题我们看到’entry-runtime-with-compiler.js’这个文件,$mount函数部分如下:  这段话的目的就是去确认template实际内容时以el、template、render函数中哪一个为准? 1、首先判断render函数是否存在,如果存在则以render函数为准,直接渲染 2、如果render函数不存在,则检查template模板是否存在,如果存在template则编译template模板成为render函数 3、如果template不存在,则取得el标签中innerHTML作为template模板,再生成render函数 4、如果el不存在,则生成一个空的div标签。 言归正传,我们回到baseCompile函数中,看编译template成render函数过程。  函数第一句const...
前面两篇讲述了**Vue运行时---第一步扩展实例方法(点击链接)**和**Vue运行时---第二步扩展静态方法(点击链接)**,今天第三节解读## Vue中双向数据绑定的原理。 我们先回到’instance/index’文件中,如下图  ## 我们第一节已经说到 initMixin(Vue)只做了一件事,就是给Vue扩展了实例方法_init  接下来我们进入Vue比较重要的环节,比如我们举一个例子,  定义了data和template,我们这节就要搞清楚data值变化和template生成的html是如何相应变化的。如图一,new Vue之后,进入function Vue构造函数,执行this._init(options),这节其实也就是主要要搞清楚_init 方法,我们现在看到图二中_init 方法,  1、 我们先看到第一个红框处,mergeOptions是方法是用来合并options参数的,第一句resolveConstructorOptios(vm.constructor)将得到第二节中说道buildInComponents默认参数,并用传入的options取代默认参数。 2、 initLifecycle(vm) 我们找到’instance/lifeCycle’文件如下:  我们可以看到是初始化工作,第一句options.parent在buildInComponent中没有,如果自己传递了那么vm.$parent就是你传递额parent参数。如果没有传递那么vm.$parent就是null而且vm.$vm就是vm本身。接着又设置vm.$refs ={},vm._watch = null,vm._inactive = null,vm._directInactive = false,vm._isMounted...
我们上一节讲了**### Vue运行时---第一步扩展实例方法(链接)**。回到’core/index’文件中,接着往下面看initGlobalAPI(Vue)方法,该方法为Vue绑定静态方法。  我们进入’./global-api/index’找到initGlobalAPI定义如下:  1、先看第一部分扩展了Vue.util工具方法warn、extend、mergeOptions、defineReactive Vue.util = { warn, extend, mergeOptions, defineReactive } 2、接着扩展了Vue.set 、Vue.delete、Vue.nextTick这三个方法。 3、定义了Vue.options为空对象 4、ASSET_TYPES是一个数组,包含[conponent、directive、filter],于是forEach之后Vue扩展了Vue.options.conponents、Vue.options.directives、Vue.options.filters。 5、定义Vue.options._base 等于 Vue构造函数本身 6、接下来extentd(Vue.options.components,buildInComponents),这一句就是要去用默认的components对象去覆盖Vue.options.components对象,所以经过这一句之后,Vue.options.components的内容变为了buildInComponents的内容,如下:  上面这数据name、props、created、destroyed、watch、render就很熟悉了,再一般写Vue的时候会用到几个属性。 继续看第二张图扩展Vue的静态方法,最后initUse(Vue)、initMixin(Vue)、initExtend(Vue)、initAssetsRegisters(Vue)这四个方法。 ## initUse(Vue)  我们看到就一个方法Vue.use,具体里面做了哪些事情,我们后面具体讲。 ##...
Vue.js发布分为三个版本: 1、 **完整版**:同时包含编译器和运行时的版本。 2、 **编译器**:用来将模版字符串编译成为JavaScript渲染函数的代码。 3、 **运行时**:用来创建Vue实例、渲染并处理虚拟DOM等代码。基本上就是出去编译器的其他一切。 我们先阅读运行时版本,了解Vue的创建过程。之后再阅读编译器版本,看编译其如何将html模版编译成为javascript代码。其实我们在使用vue-cli开发时,每当我们使用npm run build打包时,vue-loader会自动将template标签内的html模版编译成javascript代码,用户访问网站的js文件内,只会执行运行时版本,因为已经编译完成了。 下载Vue.js 2.4.4版本,源码中,发布运行时版本的入口是entry-runtime.js,这个文件中直接导入runtime文件夹中index.js文件。  runtime/index.js是Vue针对Web平台添加一些特定方法,其中最重要的就是Vue.protorype.$mount方法了,我们看到runtime/index.js中第一句 import Vue from ‘core/index’,core文件夹就是Vue核心代码了(如下图)。  **1、’core/index’中第一句import Vue from ‘./instance/index’,是扩展Vue的实例方法。 2、initGlobalApi(Vue),是扩展了Vue的静态方法。** 最后返回了,扩展了实例方法和静态方法的Vue函数。 ## **扩展实例方法** 进入’./instance/index’,代码很简单(如下图),  首先定义了真正的function...
i saw your source code in Themeablebrowser.java getImage function,as follow code: is = cordova.getActivity().getAssets().open(file.getPath()); but with cordova-plugin-code-push,the wwwImage path change like "/data/data/com.dj/files/codepush/deploy/versions/319858b6658fef2c3feef68a9575dcceba9d6a6ae04c07dbfbc4b89e017447bb/www" so, I mean your code can not get...
//allow setAcceptThirdPartyCookies in android5.0+,such as set-cookie in response headers //should add in ThemeableBrowser.java at line 803 // Enable Thirdparty Cookies on >=Android 5.0 device if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);...