响应式

Object.defineProperty

Object.defineProperty(obj, prop, descriptor)  // 对象、属性、描述符

  Object.defineProperty是es5新加的给对象属性设置描述符的方法,可以用来监听属性值的变化

 var obj ={};
var _name ='张三'
Object.defineProperty(obj,'name',{
get:function () {
return _name;
},
set:function (value) {
_name=value;
}
})

  调用方式:

obj.name ="里斯";
alert(obj.name);

模拟Vue响应式(data的属性代理到vm上)

 var vm= {};
var data= {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
};
var i;
for (i in data){
if(data.hasOwnProperty(i)){
(function(i){ // 独立函数作用域
Object.defineProperty(vm,i,{ //将data对象的属性代理到vm
get: function () {
return data[i];
},
set:function (newVal) {
data[i]=newVal;
}
})
}(i))
}
}
vm.items[0].message='张三'
console.log(vm.items); 

模板解析

  1. 本质:字符串
  2. 有逻辑: 例如v-if、v-for 等
  3. html模版是静态的,Vue模板是动态
  4. 模板必须转换成JS函数(render函数),进而转换成html渲染页面

with

  //模板
function UserInfo() {
this.name = "kobe bryant";
this.age = "28";
this.gender = "boy";
}
var people=new UserInfo();
function fn(){
with(people)
{
var str = "姓名: " + name + "\n";
str += "年龄:" + age + "\n";
str += "性别:" + gender;
alert(str);
}
}
fn();

render 函数

<div class="main" :class="bindClass">
<div>{{text}}</div>
<div>hello world</div>
<div v-for="(item, index) in arr">
<p>{{item.name}}</p>
<p>{{item.value}}</p>
<p>{{index}}</p>
<p>---</p>
</div>
<div v-if="text">
{{text}}
</div>
<div v-else></div>
</div>

Vue 源码将HTML string 转换成AST

模版转换成js

with(this){
return _c( 'div',
{
/*static class*/
staticClass:"main",
/*bind class*/
class:bindClass
},
[
_c( 'div', [_v(_s(text))]),
_c('div',[_v("hello world")]),
/*这是一个v-for循环*/
_l(
(arr),
function(item,index){
return _c( 'div', //_c创建标签
[_c('p',[_v(_s(item.name))]), //_v 创建文本; _s 转换成字符串
_c('p',[_v(_s(item.value))]),
_c('p',[_v(_s(index))]),
_c('p',[_v("---")])]
)
}
),
/*这是v-if*/
(text)?_c('div',[_v(_s(text))]):_c('div',[_v("no text")])],
2
)
}

其中,this 即使Vue构造函数对象(假定为vm),item即this.item,也是data中的item  

针对于上一篇的随笔:浅谈Jquery和常用框架Vue变化,我们来解析一下它的render模板

<div id="example-1">
<input v-model="title" />
<button v-on:click="add">udto list</button>
<ul>
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
</div>

  模板render解析

with (this) {
// noinspection JSAnnotator
return _c('div', {attrs: {"id": "example-1"}}, [ //div
_c('input', { //input
directives: [{
name: "model",
rawName: "v-model",
value: (title),
expression: "title"
}],
domProps: {"value": (title)}, //model 往 view
on: {
"input": function ($event) {
if ($event.target.composing) return;
title = $event.target.value //view 往 model
}
}
}), _v(" "), //换行
_c('button',
{
on: {
"click": add //绑定 methods add
}
},
[
_v("udto list") //文本子节点
]
), _v(" "), //换行
_c('ul',
_l((items), function (item) { // <li v-for="item in items"> _l v-for
return _c('li',
[
_v("\n " + _s(item.message) + "\n ") //item 对应 vm.item 即 data中的item
]
)
}))
])
}

渲染

从上面例子可以看出,vue通过借鉴改造snabbdom,h函数返回的vNode,vm._c返回的也是vNode,从Vue源码中也验证了这一点,从下面Vue源码看出Vue是通过updateComponent 完成render渲染

  

var prevVnode = vm._vnode; //旧的vnode,initial render 第一次渲染 vnode 没有存在,装载在容器中,全部渲染
// updates
vm.$el = vm.__patch__(prevVnode, vnode); //第二次 新旧vNode对比

Vue 整个工作流程

  1.  将模板解析成Js,即render函数
  2. 监听模板,通过MVVM响应式绑定model,并完成监听
  3. render函数渲染成Virtual Node
  4. 初次渲染完成DOM节点的创建,再次渲染新旧Vittual Node对比

源码地址

https://github.com/10086XIAOZHANG/VirtualDOMDemo  

浅析Vue原理(部分源码解析)的更多相关文章

  1. 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试

    机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ...

  2. Spring-Session实现Session共享实现原理以及源码解析

    知其然,还要知其所以然 ! 本篇介绍Spring-Session的整个实现的原理.以及对核心的源码进行简单的介绍! 实现原理介绍 实现原理这里简单说明描述: 就是当Web服务器接收到http请求后,当 ...

  3. Spring MVC工作原理及源码解析(三) HandlerMapping和HandlerAdapter实现原理及源码解析

    1.HandlerMapping实现原理及源码解析 在前面讲解Spring MVC工作流程的时候我们说过,前端控制器收到请求后会调⽤处理器映射器(HandlerMapping),处理器映射器根据请求U ...

  4. Redux异步解决方案之Redux-Thunk原理及源码解析

    前段时间,我们写了一篇Redux源码分析的文章,也分析了跟React连接的库React-Redux的源码实现.但是在Redux的生态中还有一个很重要的部分没有涉及到,那就是Redux的异步解决方案.本 ...

  5. LinkedList原理及源码解析

    简介 LinkedList是一个双向线性链表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度, ...

  6. ORB原理与源码解析

    转载: http://blog.csdn.net/luoshixian099/article/details/48523267 CSDN-勿在浮沙筑高台 没有时间重新复制代码,只能一股脑的复制,所以代 ...

  7. Spring核心框架 - AOP的原理及源码解析

    一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置A ...

  8. 【Spring】Spring IOC原理及源码解析之scope=request、session

    一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存 ...

  9. RocketMQ原理及源码解析

    RocketMQ原理深入: 一.定义: RocketMQ是一款分布式.队列模型的消息中间件,有以下部分组成: 1.NameServer: 一个几乎无状态的节点,可集群部署,节点之间无任何信息同步 2. ...

随机推荐

  1. 怎样修改织梦网站的favicon图标

    现在很多的网站浏览器栏上都有favicon图标,比如百度,大家用织梦做好网站后,可能发现自己的网站favicon图标默认的不好看,如何修改织梦网站的favicon导航图标呢,很多人肯定有过困惑,小编遇 ...

  2. numpy用法介绍-未完待续

    简介 NumPy(Numerical Python简称) 是高性能科学计算和数据分析的基础包 为什么使用? 标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元 ...

  3. 怎么区分odd和even

    odd [ɒd] 和even ['iːv(ə)n] 一个表示奇数.一个表示偶数 经常混淆. 一个记住的好方法: odd是3个字母,单数,所以表示奇数 even是4个字母,所以表示偶数

  4. 【Jmeter】参数Parameters和Body Data

    在做接口并发测试的时候,才发现Jmeter中的Parameters和Body Data两种参数格式并不是简单的一个是xx=xx,另外一个是json格式的参数 先看一个接口 [post] /api/xx ...

  5. Redux学习笔记--异步Action和Middleware

    异步Action 之前介绍的都是同步操作,Redux通过分发action处理state,所有的数据流都是同步的,如果需要一步的话怎么办? 最简单的方式就是使用同步的方式来异步,将原来同步时一个acti ...

  6. Django后台注册

  7. Ubuntu14.04下如何安装Python爬虫框架Scrapy

    按照官方文档的说明,安装scrapy 需要以下程序或者库: (1).Python 2.7 (2).lxml. Most linux distributions ships PRepackaged ve ...

  8. JS 和 Jq 获取客户端各种屏幕宽度和高度

    //javascript 网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.clientHeight 网页可见区域宽: documen ...

  9. jemter 使用if控制器,选择需要的内容

    背景:需要根据人员传入的变量,来选择运行的环境,调用不同的参数,进行拼接,使用到if控制器 取到的数据,调用的就是test1的数据

  10. 总结PHP删除字符串最后一个字符的三种方法

    一.前言 从数据库中select()读取一对多的信息时,经常需要将取出的数组用某个特定的字符分割,然后拼接成字符串. 常见的语法格式: foreach ($arr as $key => $val ...