根据vue的官网介绍,可以得知vue是一个mvvm框架,且是响应式的。为了更深入了理解其内涵,本人以及理解实现了一个简单的mvvm学习的demo。下面分享给大家,欢迎大家一起讨论。

一、mvvm至少包含的内容

  1. 指令集合,如:text、model等
  2. 数据模型,与视图交互的数据
  3. 组件的支持:也就是部分html代码的动态更新

二、我的实现

1. 变量的定义与watch的实现

var directives = {}; //指令集合
var vNodes = new Array(); //解析的Dom集合 var dataModel = {
name:"name",
title: "title"
}; //数据Model var Watch = {
isInit: false,
watchs: new Array(),
run: function(newValue, expOrfn){
var self = this;
if(!self.isInit){
expOrfn.call(vModel);
}
this.watchs.map(function(data,index){
data.nodes.map(function(d,i){
if(self.isInit){
d.directive.init(newValue, d, data); //绑定初始化值, 以及初始化一些事件
}else{
d.directive.update(newValue, d, data); //只更新值,此时run的调用来值value-set
}
});
}); self.watchs = [];
},
push:function(watch){
this.watchs.push(watch);
}
} //任务管理

说明:

  1. Watch的push方法,用于依赖的添加,然后run来执行所以依赖,执行完成后,需要清理当前依赖的集合。在vue中依赖的收集是在dep中完成的,而watch提供的任务管理(不知道理解是否正确)

2. 指令的定义

directives.text = {
init: function(value, vNode){
vNode.elm.textContent = value;
},
update: function(value, vNode){
vNode.elm.textContent = value;
}
}
//需要响应事件的怎么办
directives.model ={
init: function(value, vNode, _watch){
vNode.elm.value = value; //判断自己发生的改变,不应该再改变自己
vNode.elm.addEventListener('keyup',function(evt){
vNode.model[_watch.key] = vNode.elm.value;
});
},
update:function(){ }
}

说明:

  1. 由于是demo学习示例,所以只定义了简单的text和model两个指定,text:用于数据的显示,而model用于input(输入框)的响应

3. vModel的生成

//转换vModel,暂支持一级
var properties = Object.getOwnPropertyNames(dataModel);
var vModel = {}, formSetting = false;
for( var index in properties){
(function refreshData(_index){
var key = properties[_index];
var property = Object.getOwnPropertyDescriptor(dataModel, key);
var setter = property.set;
var getter = property.get;
var _val = property.value;
var _getter = function(){
var val = getter ? getter.call(vModel) : _val;
//收集依赖,与watch要分开
Watch.push({
key: key,
nodes: vNodes.filter(function(data,index){
return data.modelKey == key ? true : false;
}),
getter: _getter
});
return val;
};
Object.defineProperty(vModel, key, {
configurable: true,
enumerable: true,
set: function(value){
if(setter){
setter.call(vModel, value);
}
//处理依赖
Watch.run(value, _getter);
//this.value = value;
},
get: _getter })
})(index);
}

说明:

  1. vModel是根据dataModel生成的,也就是自定义了每个属性的get和set方法,在es6中也可以用proxy实现(是否说对了)。
  2. 在属性set的时候,会先调用get方法来收集依赖。方便值改变后,能将所影响的内容都修改掉。

4. 解析dom为vNode

//解析vNodes
var app = document.getElementById('app');
app.childNodes.forEach(function(data,index){
if(data.nodeType != 1) return;
var hv = data.getAttribute('data-hv');
var hvs = hv.split(',');
hvs.forEach(function(item,row){
var keyValue = item.split(':'); //vNode对象上一定要有model,这是方便vNode相应时候的找vModel
vNodes.push({
directive: directives[keyValue[0]],
modelKey: keyValue[1],
model: vModel,
elm: data
});
});
});

说明:

  1. 这里说解析为vNode很是牵强,因为此只是收集了dom上data-hv指定的指令,并将对就的指令、元素、vModel等组成一个对象存储在vNodes中,以供vModel各属性的get方法收集依赖时引用。

5. 第一次初始化

//调用所有的get一次
Watch.isInit = true;
var _keys = Object.getOwnPropertyNames(vModel);
_keys.map(function(key,data){
var data = vModel[key];
Watch.run(data);
});
Watch.isInit = false;

说明:

  1. 将初始化的vModel的值渲染到Dom上,这里是主动执行每个的get,然后运行watch.run方法。
  2. 此处设计和实现本人感觉与vue的思路不对,如有高人看见,麻烦提点与指引。

6. 被解析的dom

<div id="app">
<span data-hv="text:title"></span>
<span data-hv="text:title"></span>
<input data-hv="model:title" />
</div>

对vue源码的初步认识和理解的更多相关文章

  1. VUE 源码学习01 源码入口

    VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...

  2. Vue源码后记-其余内置指令(3)

    其实吧,写这些后记我才真正了解到vue源码的精髓,之前的跑源码跟闹着玩一样. go! 之前将AST转换成了render函数,跳出来后,由于仍是字符串,所以调用了makeFunction将其转换成了真正 ...

  3. Vue源码后记-钩子函数

    vue源码的马拉松跑完了,可以放松一下写点小东西,其实源码讲20节都讲不完,跳了好多地方. 本人技术有限,无法跟大神一样,模拟vue手把手搭建一个MVVM框架,然后再分析原理,只能以门外汉的姿态简单过 ...

  4. 大白话Vue源码系列(01):万事开头难

    阅读目录 Vue 的源码目录结构 预备知识 先捡软的捏 Angular 是 Google 亲儿子,React 是 Facebook 小正太,那咱为啥偏偏选择了 Vue 下手,一句话,Vue 是咱见过的 ...

  5. 大白话Vue源码系列(02):编译器初探

    阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...

  6. 大白话Vue源码系列(03):生成AST

    阅读目录 AST 节点定义 标签的正则匹配 解析用到的工具方法 解析开始标签 解析结束标签 解析文本 解析整块 HTML 模板 未提及的细节 本篇探讨 Vue 根据 html 模板片段构建出 AST ...

  7. 大白话Vue源码系列(03):生成render函数

    阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...

  8. 大白话Vue源码系列(04):生成render函数

    阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...

  9. 大白话Vue源码系列(05):运行时鸟瞰图

    阅读目录 Vue 实例的生命周期 实例创建 响应的数据绑定 挂载到 DOM 节点 结论 研究 runtime 一边 Vue 一边源码 初看 Vue 是 Vue 源码是源码 再看 Vue 不是 Vue ...

随机推荐

  1. Paxos协议超级详细解释+简单实例

    转载自:  https://blog.csdn.net/cnh294141800/article/details/53768464 Paxos协议超级详细解释+简单实例   Basic-Paxos算法 ...

  2. 小程序即时聊天(仅页面功能,未接websocket)

    我们都知道小程序是不能直接操作dom的,所以做即时通讯聊天功能的时候也就不能像之前做的一样:点击发送的时候,拼接一个节点到页面上.话不多说,以下是效果和代码: -------------------- ...

  3. hadoop hdfs ha 模式

    这是我自己在公司一个搭建公司大数据框架是自己的选项,在配置yarn ha 出现了nodemanager起不来的问题于是我把yarn搭建为普通yarn 如果有人解决 高yarn的nodemanager问 ...

  4. BZOJ5465 : [APIO 2018] 选圆圈

    假设最大的圆半径为$R$,以$2R$为大小将地图划分为一个个格子,那么每个圆只需要检查圆心在附近$9$个格子内部的所有圆. 在当前圆的半径不足$\frac{R}{2}$时重构网格,那么最多重构$O(\ ...

  5. http 缓存学习.

    mark 一下 HTTP 缓存机制一二三 http://web.jobbole.com/92773/ 彻底弄懂HTTP缓存机制及原理 https://www.cnblogs.com/chenqf/p/ ...

  6. 记录一次DataTable排序的问题

    //dt.DefaultView.Sort = "字段名 方式"; 最开始用的上面的没好用,改成底下转换了一下就好用了0.0 DataView dv = new DataView( ...

  7. console.log

    其实,console.log 不仅仅有一下应用 console.log() 这个应该是最常用的 console.error() 输出错误信息 会以红色显示 console.assert(bool,”i ...

  8. vue图片上传到七牛云

    代码: <template> <div class="upload-info"> <div> <el-upload class=" ...

  9. hadoop伪分布式搭建

    安装好jdk 减压hadoop压缩包 cd /home/hadoop/hadoop-2.7.3/etc/hadoop vi hadoop-env.sh 文件末尾处添加 jdk环境变量 export J ...

  10. conda 查看已有环境

    conda info -e # conda environments: # dlcv /Users/enzhao/suanec/libs/anaconda2/envs/dlcv py36 /Users ...