根据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. haproxy4-acl配置

    访问控制设定: 匹配后可进行那些操作: Use _backend :   当符合条件时使用特定的backend后端, Use_backend  <backend> [{if | unles ...

  2. selenium使用遇到的问题(selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH.)

    1.安装pip3 install selenium 2.使用browser=webdriver.Chrome()时报错 :selenium.common.exceptions.WebDriverExc ...

  3. qt之数据库对照片的存取

    需要确保数据库连接上 QOCI为驱动 //oracle 数据库连接 //需要在执行文件目录添加 oci.dll oraociei11.dll QSqlDatabase db = QSqlDatabas ...

  4. 《团队作业第三、第四周》五小福团队作业--Scrum 冲刺阶段--Day7

    <团队作业第三.第四周>五小福团队作业--Scrum 冲刺阶段--Day7 一.项目燃尽图 二.项目进展 [20172301郭恺第七天的进展] 第七天完成的任务: 代码整合,界面调整为相对 ...

  5. SQL功能分类

    DDL  数据定义语言:创建表 ,库,列 DML 数据操作语言:用来操作数据库中的记录 DQL 数据查询语言 :用来查询数据 DCL 数据控制语言:定义访问权限和安全级别 —————————————— ...

  6. myeclipse中配置自己安装的Tomcat

    myeclipse中配置自己安装的Tomcat 在myeclipse中配置好jdk,Tomcat之后,如果是web项目需要部署运行,但在部署时发现配置好的Tomcat没有显示,只显示了myeclips ...

  7. oracle中文乱码问题解决

    中文乱码问题解决:1.查看服务器端编码select userenv('language') from dual;我实际查到的结果为:AMERICAN_AMERICA.ZHS16GBK2.执行语句 se ...

  8. linux-Vim命令合集

    Vim命令合集 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filena ...

  9. 第三次作业(ABC类代码优化及感悟)

    这次作业与林杰同学合作完成,不重复发布了. 可以直接去林杰同学的博客看.http://www.cnblogs.com/linlinlin/p/4836707.html

  10. 在线生成透明ICO图标神器

    此神器的链接为:http://ico.duduxuexi.com/ 大家可以将这个网址收藏好,本人亲测十分好用!对我们的ios,安卓以及windows开发都有极大的好处.