vue学习笔记

1.vue data属性里面的getter和setter

data的每个属性都有两个相对应的get和set属性。

ES5的对象原型有两个新的属性__defineGetter__和__defineSetter__,专门用来给对象绑定get和set。可以这样书写:


vue双向绑定原理是由数据劫持结合发布者-订阅者模式实现的。

vue的数据劫持是通过Object.defineProperty()来对对象的setter和getter属性进行操作,在数据进行变动时,进行你想要的操作。

语法:Object.defineProperty(obj,prop,descriptor)

            参数:

                obj:要在其上定义属性的对象。

                prop:要定义或修改的属性名称。

                descriptor:将被定义或修改的属性描述。

            返回值:

                  被传递给函数的对象。

也就是说他可以控制一个对象属性的一些特有操作,比如读写或是否可枚举等,这里组要看set和get。

2.vue.js计算属性computed(getter,setter)

在Vue中,computed的属性可以被视为是data一样,可以读取和设置,因此在computed中可以分成getter和setter,一般情况下没有setter,computed预设只有getter,也就是只能读取,不能改变设值。

vue.js计算属性默认只有getter,因为是默认值所以我们也常常忽略不写,如下代码:

完整写法:

计算属性getter的出发时间:

如果我们改变上边代码里的2个输入框的值firstName或则lastName,都会触发computed以及updated(),也就是说会执行:console.log('computed')和console.log('updated');

需要注意的是,不是说我们更改了getter里使用的变量,就会触发computed的更新,前提是computed里的值必须要在模板里面使用才行。如果把上面代码中的p标签注释掉,就算改变input的值也不会触发computed。

2.vue生命周期。

1new Vue{

         router,

         store,

          //components: { App } vue1.0的写法

            render: h => h(App) vue2.0的写法

}).$mount('#app')

1.首先需要了解这是 es 6 的语法,表示 Vue 实例选项对象的 render 方法作为一个函数,接受传入的参数 h 函数,返回 h(App) 的函数调用结果。

2.其次,Vue 在创建 Vue 实例时,通过调用 render 方法来渲染实例的 DOM 树。

3.最后,Vue 在调用 render 方法时,会传入一个 createElement 函数作为参数,也就是这里的 h 的实参是 createElement 函数,然后 createElement 会以 APP 为参数进行调用,关于 createElement 函数的参数说明参见:Element-Arguments。


先了解一下vue的虚拟dom:

Vitual DOM是一种虚拟dom技术,本质上是基于javascript实现的,相对于dom对象,javascript对象更简单,处理速度更快,dom树的结构,属性信息都可以很容易的用javascript对象表示:

Virtual DOM并没有完全实现DOM,最主要还是保留了Element之间的层次关系和一些基本属性。你给我一个数据,我根据数据生成一个全新的Virtual DOM,然后跟我上一次生成的Virtual DOM去diff,然后通过patch方法挂载。

我们可以通过javascript对象表示的树结构来构建真正的DOM树,当数据发声变化时,可以直接修改这个javascript对象,接着对比修改后的对象,记录下需要对页面做的dom操作,然后将其应用到真正的DOM树,实现视图的更新。

VNode生成最关键点是通过render函数,由2种生成方式,第一种是直接在vue对象的option种添加render字段。第二种是写一个模板或指定el跟元素,它会首先转换成模板,经过html语法解析器生成一个ast抽象语法树,对语法树做优化,然后把语法树转换成代码片段,最后通过代码片段生成function添加到option的render字段中。

    ast语法优化过程,主要做了2件事:

        1.会检测出静态的class名和attributes,这样它们在初始化渲染后永远不会再被对比了。

        2.会检测出最大的静态子树,并且从渲染函数中萃取出来。这样在每次重渲染时,它们会直接重用相同的vnode,同时跳过比对。

creteelment方法的功能是给一个Vnode对象添加若干个Vnode,因为整个Vritual DOM是一种树状结构,每个节点都可能会有若干子节点。然后创建一个Vnode对象,如果是一个reserved tag(html,head等一些合法的html标签)则会创建普通的DOM Vnode,如果是一个component tag(通过vue注册的自定义component),则会创建Component Vnode对象,它的VnodeComponentOptions不为null。

function patch(oldVnode, vnode, hydrating, removeOnly, parentElm, refElm){

创建好Vnode,下一步就是要把虚拟dom渲染成真正的dom,是通过patch来实现。patch支持3个参数,其中oldNode是一个真实DOM或则一个Vnode对象,它表示当前的VNode,vnode是VNode对象类型,它表示待替换的VNode,hydration是bool类型,它表示是否直接使用服务器端渲染的DOM元素,下面流程图表示patch的运行逻辑:

patch运行逻辑看上去比较复杂,有2个方法createElm和patchVnode是生成dom的关键.

createElm方法会根据vnode的数据结构创建真实的DOM节点,如果vnode有children,则会遍历这些子节点,递归调用createElm方法,InsertedVnodeQueue是记录子节点创建顺序的队列,每创建一个DOM元素就会往这个队列中插入当前的VNode,当整个VNode对象全部转换成为真实的DOM树时,会依次调用这个队列中的VNode hook的insert方法

1.了解vue的$mount所作的工作大体分为3部:

    1.如果你的option里面没有render函数,那么,通过complieToFunctions将HTML模板编译成可以生成VNode的Render函数。

    2.new一个Watcher实例,触发updateComponent方法。

    3.生成vnode,经过path,把vnode更新到dom上。

从上面的代码中可以看到,首先判断option里面有没有render函数,没有的话,进一步判断有没有template,没有的话就用dom元素的outerHTML。得到template以后干了什么呢?如下图:

我们可以看到,调用了complieToFunction将template转成render函数。这里面有两个过程:

将template解析成ast语法树。

通过ast语法树生成render函数。

下一步就开始mountConmponet了。

从上图可以看出,程序声明了一个updateComponent 方法,这个是将要被Watcher实例调用的更新组件的方法。


vm:当前的vm实例。

updateComponent 这个非常重要,用来在后面将vnode更新到dom上。

noop无意义的函数。

null option选项没有则为null。

true主要是用来判断是哪个watcher。因为computed计算属性和如果你要在options里面配置watch了同样也是使用了 new Watcher ,加上这个用以区别这三者。

if(isRenderWatcher) {

     vm._watcher = this;

}

可以看到,如果声明这个watcher的上下文是用来渲染视图的,也就是说在mountComponent这里调用new Watcher的时候,才会把this赋值给_watcher。然后把 watcher push到 _watchers 里面,目的是等到组件销毁时顺便把watcher也销毁掉。

接下来,就是赋值给 getter , this.getter = expOrFn 。还记得刚才传过来的 updateComponent 函数么,没错,就是这个赋值给我 getter 。然后我们就到了:

我们可以看到,首先它执行的是 pushTarget(this) ,pushTarget(this) 代码如下:

也就是说如果当前有 Dep.target 的话,就把target放到 targetStack 里面,如果没有的话,就设为当前的target,也就是这个watcher。 接着,就是执行了它的 getter 属性,也就是刚刚传入 updateComponent 函数。


官方vue生命周期图:

从图可以看出在vue整个的生命周期中会有很多的钩子函数,提供给我们在vue生命周期不同的时刻进行操作。没一个组件或则实例都会经历一个完整的生命周期,总共分为三个阶段:初始化、运行中、销毁。

    1.实例、组件通过new Vue()创建出来之后会初始化事件和生命周期,然后会执行beforeCreted钩子函数,这个时候数据还没有挂载,只是一个空壳,无法访问到数据和真实的dom,一般不做操作。

    2.挂载数据,绑定事件等等,然后执行creted函数,这个时候已经可以只用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其它钩子函数,一般可以在这里做初始数据的获取。

    3.接下来开始找实例或则组建对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会。

    4.接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom。

    5.当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制就会重新构建虚拟dom树利用diff算法进行对比后重新渲染。

    6.当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom。

    7.当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等

    8.组件的数据绑定、监听...去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以

先列出所有的钩子函数,再一一详解:

    *beforeCreate

    *created

    *beforeMount

    *mounted

    *beforeUpdate

    *updated

    *beforeDsetroy

    *destroyed

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容

  • vue学习笔记 安装 Vue 提供一个官方命令行工具,可用于快速搭建大型单页应用。只需几分钟即可创建并启动一个带热...
    EL_PSY_CONGROO阅读 1,054评论 0 5
  • vue对比jquery vue:mvvm 数据驱动影响视图 适用于复杂数据jquery:mvc 视图塞入数据 ...
    34sir阅读 3,004评论 1 2
  • 序言:乱七八糟一锅粥! 基于Vue.js 教程、介绍— Vue.js 心得: 在vue中,推荐始终使用 kebab...
    苦苦修行阅读 647评论 0 1
  • .$data .#$el $data表示vue实例中data的值$el表示vue实例中el的值,注意 el效果等...
    李诺哦阅读 828评论 0 0
  • 狮子座人常有个人英雄主义情结,希望永远在关系中处于主角,以“为你好”、“我说的都是对的”的借口,“管教”身边人,让...
    星群公社阅读 905评论 0 2