对vue源码的初步认识和理解
根据vue的官网介绍,可以得知vue是一个mvvm框架,且是响应式的。为了更深入了理解其内涵,本人以及理解实现了一个简单的mvvm学习的demo。下面分享给大家,欢迎大家一起讨论。
一、mvvm至少包含的内容
- 指令集合,如:text、model等
- 数据模型,与视图交互的数据
- 组件的支持:也就是部分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);
}
} //任务管理
说明:
- 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(){
}
}
说明:
- 由于是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);
}
说明:
- vModel是根据dataModel生成的,也就是自定义了每个属性的get和set方法,在es6中也可以用proxy实现(是否说对了)。
- 在属性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
});
});
});
说明:
- 这里说解析为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;
说明:
- 将初始化的vModel的值渲染到Dom上,这里是主动执行每个的get,然后运行watch.run方法。
- 此处设计和实现本人感觉与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源码的初步认识和理解的更多相关文章
- VUE 源码学习01 源码入口
VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...
- Vue源码后记-其余内置指令(3)
其实吧,写这些后记我才真正了解到vue源码的精髓,之前的跑源码跟闹着玩一样. go! 之前将AST转换成了render函数,跳出来后,由于仍是字符串,所以调用了makeFunction将其转换成了真正 ...
- Vue源码后记-钩子函数
vue源码的马拉松跑完了,可以放松一下写点小东西,其实源码讲20节都讲不完,跳了好多地方. 本人技术有限,无法跟大神一样,模拟vue手把手搭建一个MVVM框架,然后再分析原理,只能以门外汉的姿态简单过 ...
- 大白话Vue源码系列(01):万事开头难
阅读目录 Vue 的源码目录结构 预备知识 先捡软的捏 Angular 是 Google 亲儿子,React 是 Facebook 小正太,那咱为啥偏偏选择了 Vue 下手,一句话,Vue 是咱见过的 ...
- 大白话Vue源码系列(02):编译器初探
阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...
- 大白话Vue源码系列(03):生成AST
阅读目录 AST 节点定义 标签的正则匹配 解析用到的工具方法 解析开始标签 解析结束标签 解析文本 解析整块 HTML 模板 未提及的细节 本篇探讨 Vue 根据 html 模板片段构建出 AST ...
- 大白话Vue源码系列(03):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(04):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(05):运行时鸟瞰图
阅读目录 Vue 实例的生命周期 实例创建 响应的数据绑定 挂载到 DOM 节点 结论 研究 runtime 一边 Vue 一边源码 初看 Vue 是 Vue 源码是源码 再看 Vue 不是 Vue ...
随机推荐
- Paxos协议超级详细解释+简单实例
转载自: https://blog.csdn.net/cnh294141800/article/details/53768464 Paxos协议超级详细解释+简单实例 Basic-Paxos算法 ...
- 小程序即时聊天(仅页面功能,未接websocket)
我们都知道小程序是不能直接操作dom的,所以做即时通讯聊天功能的时候也就不能像之前做的一样:点击发送的时候,拼接一个节点到页面上.话不多说,以下是效果和代码: -------------------- ...
- hadoop hdfs ha 模式
这是我自己在公司一个搭建公司大数据框架是自己的选项,在配置yarn ha 出现了nodemanager起不来的问题于是我把yarn搭建为普通yarn 如果有人解决 高yarn的nodemanager问 ...
- BZOJ5465 : [APIO 2018] 选圆圈
假设最大的圆半径为$R$,以$2R$为大小将地图划分为一个个格子,那么每个圆只需要检查圆心在附近$9$个格子内部的所有圆. 在当前圆的半径不足$\frac{R}{2}$时重构网格,那么最多重构$O(\ ...
- http 缓存学习.
mark 一下 HTTP 缓存机制一二三 http://web.jobbole.com/92773/ 彻底弄懂HTTP缓存机制及原理 https://www.cnblogs.com/chenqf/p/ ...
- 记录一次DataTable排序的问题
//dt.DefaultView.Sort = "字段名 方式"; 最开始用的上面的没好用,改成底下转换了一下就好用了0.0 DataView dv = new DataView( ...
- console.log
其实,console.log 不仅仅有一下应用 console.log() 这个应该是最常用的 console.error() 输出错误信息 会以红色显示 console.assert(bool,”i ...
- vue图片上传到七牛云
代码: <template> <div class="upload-info"> <div> <el-upload class=" ...
- hadoop伪分布式搭建
安装好jdk 减压hadoop压缩包 cd /home/hadoop/hadoop-2.7.3/etc/hadoop vi hadoop-env.sh 文件末尾处添加 jdk环境变量 export J ...
- conda 查看已有环境
conda info -e # conda environments: # dlcv /Users/enzhao/suanec/libs/anaconda2/envs/dlcv py36 /Users ...