对vue源码的初步认识和理解
时间:2022-04-22
本文章向大家介绍对vue源码的初步认识和理解,主要内容包括一、mvvm至少包含的内容、二、我的实现、2. 指令的定义、3. vModel的生成、4. 解析dom为vNode、5. 第一次初始化、6. 被解析的dom、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
根据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>
- 快速入门系列--WCF--02消息、会话与服务寄宿
- JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法
- 快速入门系列--深入理解C#
- “家庭贷款”域名Home.loans已经建站为家庭贷款相关的网站
- 微信亿级用户异常检测框架的设计与实践
- 程序员必知的6点编程秘诀,编程三板斧将解决90%问题!
- JavaScript之面向对象学习三原型语法升级
- 腾讯入局物业管理,欲改造传统服务?
- JavaScript之面向对象学习五(JS原生引用类型Array、Object、String等等)的原型对象介绍
- SQL学习之分组数据Group by
- SQL学习之数据列去空格函数
- 采用DIV+CSS布局对SEO优化有何好处?
- Sublime快速入门
- SQL学习之汇总数据之聚集函数
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 微信小程序skeleton骨架屏
- 微信小程序锚点选择导航栏
- vue-ripple-directive点击水波纹
- dubbo学习之源码创建属于自己的dubbo-demo
- Vue4.x配置env开发环境、测试环境、生产环境
- SpringBoot总结之CommandLineRunner
- 详细整理Spring事务失效的具体场景及解决方案
- Vue监听文本框实时输入限制输入长度
- 30 分钟轻松搞定正则表达式基础
- Vant引入CDN实现图片懒加载
- Js时间戳倒计时天时分秒
- 微信小程序引用we-cropper裁切图片
- NodeJs获取get/post传值
- Mybatis源码本地化构建Demo
- NodeJs封装静态web服务器、路由、读取文件获取响应类型