vue mvvm原理与简单实现 -- 上篇
Object.defineProperty介绍--
let obj = {};
Object.defineProperty(obj,'school',{
configurable : true, // 属性能否被删除
//writable : true, // 属性能否被修改
enumerable : true, // 属性能否枚举
//value : 'zfpx', // 设置属性值 set : function(value){
console.log(value); // obj.school赋值时, 调用set() 方法
},
get : function(){
return 'zfpx'; // 获取 obj.school 的值时,调用 get() 方法
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<body>
<div id="app">
<p>{{a.a}}</p>
<div>{{b}}
<div>{{b}}</div>
</div>
</div>
</body>
<!-- mvvm 双向数据绑定
vue 数据劫持+发布订阅模式
不兼容低版本 Object.defineProperty -->
<script> (function(window,document){
function ZF(options = {}){
this.$options = options; // 将所有的属性挂载在 $options 上
let data = this._data = this.$options.data;
this.observe(data);
for(let key in data){ // 把data属性通过Object.defineProperty的方式定义属性
// 数据代理
// this代理了this._data
Object.defineProperty(this,key,{
enumerable : true, // 可枚举
get: function(){
return this._data[key];
},
set: function(newVal){ // 更改值的时候
this._data[key] = newVal;
}
});
}
this.Compile(options.el,this);
}
// 编译
ZF.prototype.Compile = function(el,vm){
vm.$el = document.querySelector(el);
let fragment = document.createDocumentFragment();
while(child = vm.$el.firstChild){ // 将app中的内容 移入内存中
fragment.appendChild(child);
}
// 循环每一层
Array.from(fragment.childNodes).forEach(function(node){ let text = node.textContent;
let reg = /\{\{(.*)\}\}/; if( reg.test(text)){
let arr = RegExp.$1.split('.');
let val = vm;
console.log(node.childNodes)
console.log(arr)
arr.forEach(function(k){
val = val[k];
})
// 替换
node.textContent = text.replace(/\{\{(.*)\}\}/,val)
}
//node.textContent.textContent(12) })
vm.$el.appendChild(fragment);
}
// 观察对象给对象增加ObjectDefineProperty;
ZF.prototype.observe = function(data){
//console.log(data)
return new Observe(data); }
function Observe(data){
for(let key in data){ // 把data属性通过Object.defineProperty的方式定义属性
let val = data[key];
// 递归
if(typeof val === 'object'){
Observe(val);
}
Object.defineProperty(data,key,{
enumerable : true, // 可枚举
get: function(){
return val;
},
// 数据劫持
set: function(newVal){ // 更改值的时候
if(newVal === val){
return;
}
if(typeof newVal === 'object'){
Observe(newVal);
}
val = newVal; //
}
});
}
}
window.ZF = ZF; })(window,document); let zf = new ZF({
el : "#app",
data : {a:{a:'是a'},b:'是b'},
}) </script>
</html>
vue mvvm原理与简单实现 -- 上篇的更多相关文章
- vue 实现原理及简单示例实现
目录 相关html代码,用于被解析绑定数据 observer代码 Dep代码 Watcher 代码 Compile 代码 vue 简要构造函数 创建vue实例 结语 主要理解.实现如下方法: Obse ...
- 对Vue中的MVVM原理解析和实现
对Vue中的MVVM原理解析和实现 首先你对Vue需要有一定的了解,知道MVVM.这样才能更有助于你顺利的完成下面原理的阅读学习和编写 下面由我阿巴阿巴的详细走一遍Vue中MVVM原理的实现,这篇文章 ...
- mvvm实现一个简单的vue
vue,基于mvvm模式下的一个前端框架 mvvm模式下简单的实现数据代理,数据劫持 1.是用Object.defineProperty 实现数据代理 2.使用发布订阅者模式,配合 Object.de ...
- vue运行原理
Vue工作原理小结 本文能帮你做什么? 1.了解vue的双向数据绑定原理以及核心代码模块 2.缓解好奇心的同时了解如何实现双向绑定 为了便于说明原理与实现,本文相关代码主要摘自vue源码, 并进行了简 ...
- 直播课(1)如何通过数据劫持实现Vue(mvvm)框架
19.6.28更新: 这篇博客比较完善:将每一部分都分装在单独的js文件中: 剖析Vue原理&实现双向绑定MVVM 半个月前看的直播课,现在才自己敲了一遍,罪过罪过 预览: 思路: 简单实现V ...
- vue 编译原理 简介
来源 tinycompile 关于vue的内部原理其实有很多个重要的部分,变化侦测,模板编译,virtualDOM,整体运行流程等. 之前写过一篇<深入浅出 - vue变化侦测原理> 讲了 ...
- 总结Vue第一天:简单介绍、基本常用知识、辅助函数
总结Vue第一天:简单介绍.基本常用知识.辅助函数 中文官网:https://cn.vuejs.org/v2/guide/syntax.html 遇到不熟悉的可以先看一下官网,然后再看一下一些别人写的 ...
- vue 快速入门 系列 —— 侦测数据的变化 - [vue api 原理]
其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue api 原理] 前面(侦测数据的变化 - [基本实现])我们已经介绍了新增属性无法被侦测到,以及通过 delete 删除数据也不会 ...
- HBase笔记:对HBase原理的简单理解
早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...
随机推荐
- CodingPlus Blog Update Info
CodingPlus更新啦! 我就是记录一下!您想知道现在的博客是第几代的吗?您想知道CodingPlus博客的发展历程吗?来,让我们一起看看! V3.5 最新版了! V3.5.0 很多人看到自然觉得 ...
- final 和 static之间的区别和联系
关键字final和关键字static两者的含义并不相似,但是笔者常常使用一段时间后就会忘记它们之间的区别,因为它俩总是相伴着出现.当只出现其中一个时,就对其代表的含义不甚清晰了.故而特地将相关知识点记 ...
- MacOs使用CleanMyMac X清除可清除空间
写在前面 本文介绍如何使用CleanMyMac X清除可清除的空间 可以看到,可清除的空间达到了125.79GB,虽然说不影响系统的使用,但是在使用时间机器进行备份的时候,仍然会将可清除空间当成备份的 ...
- 【spring boot】SpringBoot初学(3)– application配置和profile隔离配置
前言 github: https://github.com/vergilyn/SpringBootDemo 说明:我代码的结构是用profile来区分/激活要加载的配置,从而在一个project中写各 ...
- Pycharm有必要改的几个默认设置项
最近在用Pycharm学习Python的时候,总有两个地方感觉不是很舒服,比如调用方法的时候区分大小写(thread就不会出现Thread,string就不会出现String)等,这让我稍稍有点不舒服 ...
- PAT (Basic Level) Practice (中文)1066 图像过滤 (15 分)
图像过滤是把图像中不重要的像素都染成背景色,使得重要部分被凸显出来.现给定一幅黑白图像,要求你将灰度值位于某指定区间内的所有像素颜色都用一种指定的颜色替换. 输入格式: 输入在第一行给出一幅图像的分辨 ...
- jmeter测试出现端口占用
原文地址:https://www.cnblogs.com/deepSleeping/p/12067654.html Jmeter测试会出现端口占用情况 这边在这里做个记录,每次都要百度查询,刚好需要整 ...
- poj1042题解
h [1,16] hours all_v=h*12 intervals n [2,25] lakes fi inital intervals fi-di*v v [0,all_v) 题意,做每件事情的 ...
- Ubuntu 16 服务器配置PHP+MySQL+Apache环境
一.获取软件包资源并进行资源更新 apt是Ubuntu上默认的软件包管理器,使用它可以很容易进行各种软件安装,而且会自动帮你安装可能需要的依赖关系. 另一个强大的软件管理工具是 dpkg,可以用于安装 ...
- 【Unity|C#】基础篇(21)——常用类