vuejs源码学习笔记一(看懂vue源码)

  • 1、深入浅出Vue.js–变化侦测
  • 2、Vue学习系列一 —— MVVM响应式系统的基本实现原理
  • 3、.vue文件怎么写js代码
  • 4、认识Vue.js+Vue.js的优缺点+和与其他前端框架的区别
  • 5、vue入门 | 使用vue.js2.0 + ElementUI开发后台管理系统详细教程(一)
  • 6、如何学习vuejs

侦测状态变化,重新渲染页面。

拉(通知状态改变,然后暴力比对哪些节点需要重新渲染): Angular脏检查、React虚拟dom

推(明确知道哪些状态改变,细粒度,通知绑定这个状态的依赖节点更新): Vue

但,粒度越细,每个状态绑定的依赖越多,追踪开销就越大。从Vue2.0开始引入虚拟dom,绑定依赖到组件层面,而不是节点层面。 状态改变,通知到组件,组件内部再使用虚拟dom进行比对。

追踪变化 Object.defineProperty 和 Proxy

收集依赖

当数据发生变化的时候,需要通知使用了该数据的地方。所以在gettter中收集依赖,在setter中触发依赖。

为了减少耦合,封装Dep类,专门管理依赖

收集的依赖window.target,到底是啥?依赖是用到数据的地方,可能是模板,可能是用户写的一个watch,需要抽象出一个类集中处理多种情况,收集依赖阶段只收集这个类的实例,通知也只通知它,它再负责通知其他地方 — Watcher。

递归侦测所有key

封装一个Observer类用于将data中的所有属性(包括子属性)都转化成getter/setter的形式。

getter/setter只能追踪一个属性是否被修改,但无法追踪新增和删除属性,所以另外提供了vm. delete两个api。ES6之前。

侦测Object变化是通过getter/setter实现的,但是如果用Array原型上的方法改变数组,就无法侦测了。同setter追踪,如果可以在用户使用Array原型上的方法改变数组时,得到通知,就可以侦测变化。

我们可以用一个拦截器arrayMethods去覆盖Array.prototype,在拦截器中发送变化通知, 再执行原本的功能。改变数组自身内容的7个方法: [‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’, ‘sort’, ‘reverse’]

拦截器arrayMethods不能直接覆盖Array.prototype,会污染全局的Array。我们的拦截操作只需要针对那些被侦测了变化的数据生效,也就是说拦截器只覆盖那些响应式数组的原型。将一个数据转化成响应式,需要用到Observer。

ES6用Object.getPropertyOf和Object.setPropertyOf替代了 proto 。

每次访问数组的值,就会触发getter。所以Array在getter里收集依赖,在拦截器中触发依赖。

依赖列表dep存储在Observer中,因为getter和拦截器中都可以访问到Observer实例。

getter中访问:

拦截器中访问:

这样,就可以通过数组值的 ob 属性访问到Observer实例上的dep,调用改变数组内容的方法时,通知依赖。同时,收集依赖中的observe函数中通过 ob 来判断,数据是否已经被Observer转换成了响应式。

侦测数组中元素变化

侦测新增元素变化

可以新增数组元素的方法为:push、unshift 和splice,可以取出新增元素,使用observeArray方法使其变成响应式的。

Array的变化侦测是通过拦截原型上方法实现的,所以对直接给数组某一项赋值,或者通过设置length改变数组,是侦测不到的。所以可以用api或方法代替。

expOrFn: a.b.c or 函数

options: { deep, immediate }

用于观察一个表达式或computed函数在Vue实例上的变化。回调函数调用时,会从参数得到newValue和oldValue。返回一个取消观察函数,用来停止触发回调。

deep: watch对象内部值的变化,都会触发回调

immediate: 立即以表达式的当前值触发回调

所有vm.$开头的属性,都是写在Vue.prototype上的。

原理

teardown 首先需要先在Watcher中记录自己被收录进了哪些Dep中,当unwatch时,遍历自己的记录列表,从dep依赖列表中把自己删除。

deep实现原理:除了要触发当前这个被监听数据的收集依赖之外,需要把其所有子值都触发一遍收集依赖。当子数据发生变化时,可以通知当前Watcher。

在taget上设置一个属性,如果target是响应式的,被创建的属性也是响应式的,并触发视图更新。主要用来避免vue侦测不到新增加属性的限制。

用于删除target对象上的key属性。如果对象是响应式的,需要确保删除能触发更新试图。主要为了避免直接使用delete无法被侦测到变化的限制。

MVVM是Model-View-ViewModel的简写。它模式是MVC—MVP—MVVM的进化版。

Model负责用JavaScript对象表示,View负责UI界面显示,两者做到了最大限度的分离。

而把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的界面修改同步回Model更新数据。

脏值检查 : angular.js 是通过脏值检测的方式来比对数据是否有变更而决定是否更新视图。

原理是,拷贝一份 copy_viewModel 在内存中,用户操作导致 viewModel 发生改变的行为时,框架都会把 copy_viewModel 和最新的 viewModel 进行深度比较,一旦发现有属性发生变化,则重新渲染与之绑定的DOM节点。

最简单的方式就是通过 setInterval() 定时轮询检测数据变动,angular触发时进入脏值检测。但只限 指定的事件 (如:用户点击,输入操作,ajax请求,setInterval,setTimeout等…),否则需手动调用 apply 函数去强制执行一次脏检查。

数据劫持 : vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter , getter 在数据变动时发布消息给订阅者,触发相应的监听回调,而产生更新数据和视图。

原理图告诉我们,data属性定义了getter、setter对属性进行劫持,当属性值改变是就会notify通知watch对象,而watch对象则会重新触发组件呈现功能,继而更新view上的DOM节点树。

反之,view上输入数据时,也会触发data变更,也会触发订阅者watch更新,这样子model数据就可以实时更新view上的数据变化。这样一个过程就是vue的数据双向绑定了。

vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过 Object.defineProperty() 来实现对属性的劫持,达到监听数据变动的目的。

Object.defineProperty 是ES5一个方法,可以直接在一个对象上定义一个新属性,或者修改一个已经存在的属性,并返回这个对象,对象里目前存在的属性描述符有两种主要形式: 数据描述符 和 存取描述符 。

数据描述符 是一个拥有可写或不可写值的属性。

存取描述符 是由一对getter-setter函数功能来描述的属性。

描述符必须是两种形式之一;不能同时是两者。即:有值和可写,或者可get和set

属性描述符包括:

我们已经知道怎么实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器 Observer ,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者 Watcher 看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器 Dep 来专门收集这些订阅者,然后在监听器 Observer 和订阅者 Watcher 之间进行统一管理的。接着,我们还需要有一个指令解析器 Compile ,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者 Watcher ,并替换模板数据或者绑定相应的函数,此时当订阅者 Watcher 接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。

因此接下去我们执行以下4个步骤,实现数据的双向绑定:

深入响应式原理

剖析Vue原理实现双向绑定MVVM

《响应式系统的基本原理》.js

JavaScript实现MVVM之我就是想监测一个普通对象的变化

单个组件里面可以使用 import $ from ‘jquery’ 引用

当前你得使用npm把jquery 安装了。 把jquery 用export default 导出来(就是在jquery.js的最后一行写上 export default $), 然后使用import $ from ‘jquery的文件地址’

至于 script标签里面怎么写

import $ from ‘jquery’

export default {

  data: function() {

    return {

      testData: 1 // 这个对象里面定义所有的变量 这些变量可以 在html直接和dom绑定

    }

  },

  mounted: function() {

    // 生命周期函数, 有好几个 执行的顺序都不一样,可以根据场景 选择不同的生命周期函数 这块一般是初始化数据的地方

  },

  methods: { // 这里写所有的方法, 这些方法可以在 方法内部使用this.方法名调用,也可以在html 中使用@时间名 = ‘函数名()’调用

    init() {  

      // 实例方法

      // 使用this.变量可以访问data中的变量

      console.log(this.testData)

    }

  }

}

首先,我们先了解什么是MVX框架模式?

MVX框架模式:MVC+MVP+MVVM

1.MVC:Model(模型)+View(视图)+controller(控制器),主要是基于分层的目的,让彼此的职责分开。

View通过Controller来和Model联系,Controller是View和Model的协调者,View和Model不直接联系,基本联系都是单向的。

用户User通过控制器Controller来操作模板Model从而达到视图View的变化。

2.MVP:是从MVC模式演变而来的,都是通过Controller/Presenter负责逻辑的处理+Model提供数据+View负责显示。

在MVP中,Presenter完全把View和Model进行了分离,主要的程序逻辑在Presenter里实现。

并且,Presenter和View是没有直接关联的,是通过定义好的接口进行交互,从而使得在变更View的时候可以保持Presenter不变。

MVP模式的框架:Riot,js。

3.MVVM:MVVM是把MVC里的Controller和MVP里的Presenter改成了ViewModel。Model+View+ViewModel。

View的变化会自动更新到ViewModel,ViewModel的变化也会自动同步到View上显示。

这种自动同步是因为ViewModel中的属性实现了Observer,当属性变更时都能触发对应的操作。

MVVM模式的框架有:AngularJS+Vue.js和Knockout+Ember.js后两种知名度较低以及是早起的框架模式。

Vue.js是什么?

看到了上面的框架模式介绍,我们可以知道它是属于MVVM模式的框架。那它有哪些特性呢?

其实Vue.js不是一个框架,因为它只聚焦视图层,是一个构建数据驱动的Web界面的库。

Vue.js通过简单的API(应用程序编程接口)提供高效的数据绑定和灵活的组件系统。

Vue.js的特性如下:

1.轻量级的框架

2.双向数据绑定

3.指令

4.插件化

Vue.js与其他框架的区别?

1.与AngularJS的区别

相同点:

都支持指令:内置指令和自定义指令。

都支持过滤器:内置过滤器和自定义过滤器。

都支持双向数据绑定。

都不支持低端浏览器。

不同点:

1.AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观。

2.在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢。

Vue.js使用基于依赖追踪的观察并且使用异步队列更新。所有的数据都是独立触发的。

对于庞大的应用来说,这个优化差异还是比较明显的。

2.与React的区别

相同点:

React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用。

中心思想相同:一切都是组件,组件实例之间可以嵌套。

都提供合理的钩子函数,可以让开发者定制化地去处理需求。

都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载。

在组件开发中都支持mixins的特性。

不同点:

React依赖Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM会对渲染出来的结果做脏检查。

Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作DOM。

如何使用Vue.js?

1.安装

(1)script

如果项目直接通过script加载CDN文件,代码示例如下:

script src=””/script

(2)npm

如果项目给予npm管理依赖,则可以使用npm来安装Vue,执行如下命令:

$npm i vue –save-dev

(3)bower

如果项目基于bower管理依赖,则可以使用bower来安装Vue,执行如下命令:

$bower i vue –save-dev

项目首页由顶部导航栏,左侧导航栏,中间内容区构成,如图

在app.vue引入element-ui,然后就可以在其他任何页面中使用了

将app.vue改为以下内容

最近VueJs确实火了一把,自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新手来说,如何高效快速的学习Vue2.0呢。既然大家会看这篇文章,那么肯定是vue的学习者了,或是遇到的瓶颈,或者刚刚开始学,不知道如何快速起步,本篇文章将带领大家在最短的时间内构件一个学习Vue的学习路线Vuejs的作者尤雨溪尤大也写过一篇关于新手学习vue路径的文章新手向:Vue 2.0 的建议学习顺序百度vuejs搜索的是vue1的文档,推荐大家直接上2.0,毕竟1和2还是有区别的。vue2.0文档地址Vue2.0Vue基础对于没有接触过es6和webpack的童鞋来说,不建议直接用官方的脚手架vue-cli构件项目。先按文档顺序最少学习完组件那一章。直接在html文件中引入vue.js开始学习,了解vue的基础指令和语法。vue的生命周期很重要,了解这点以后可以免去很多问题。学完这些可以做一些练手的小项目,比如万年不变的todolist。。。现在可以开始学习使用vue-cli构件项目了,学习组件化之前,推荐先看一下es6关于模块的介绍。阮一峰《ECMAScript6》 Module光会这些还是不够的,还得会一些npm基础,知道如何用git-bash来安装依赖,会一些常用的命令。这方面的知识可以参阅npm入门文档看完这些就可以试着将之前的写的demo用搭建的vue-cli来实现。附上我写的一个入门小demovue-demo-search多看看组件那里,看看如何在vue-cli中怎么实现组件化,说白了,vue玩的就是组件。到这里vue基础篇就结束了。你还可以有条件的参阅剩下的官方文档里面的进阶篇,如果时间有限,就直接进入vue-router Vue-router和之前一样,推荐直接用html+js过一遍文档对路由导航钩子得好好看一看。看完文档就可以上手vue-cli,一般新手在这几天都会死活跑不出来。偷笑最直接的方法就是去github上搜一些关于vue-router2.0的demo,看如何构件路由,如何构件项目目录。我这里有一个传送门如果能跑出来,就可以做一些小项目了,比如写一个知乎日报啊偷笑,这些demo在github上很多。可以结合一些组件库写demo,这样可以更加了解组件化。比如饿了么团队的Element、mint-ui Vuex什么是vuex?Vuex 是一个专门为 Vue.js 应用设计的 状态管理模型 + 库。它为应用内的所有组件提供集中式存储服务,其中的规则确保状态只能按预期方式变更。说白了就是控制应用的一些全局状态。状态改变了,对应的视图也会改变。在学习Vuex时,会有一些ES6特性,当遇到这些时,最好不要一带而过,去好好看一看这些es6特性。比如在学习Action时可以看看ES6新增的Promise和参数解构。实践的方法一样是先看别人别人写的代码,比如官方的购物车实例的应用结构。把之前写的demo优化一下,有些地方可以用用vuex。vuex主要是用来对不同组件间进行通信,它构建了一个Vue实例的全局数据与方法,这些数据与方法可以在该Vue实例的所有组件中getter与setter。

原创文章,作者:TNKE7,如若转载,请注明出处:https://www.506064.com/n/126286.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
TNKE7的头像TNKE7
上一篇 2024-10-03 23:07
下一篇 2024-10-03 23:07

相关推荐

发表回复

登录后才能评论