(精华)2020年7月19日 vue 手写vue底层源码
发布日期:2021-06-29 15:08:03
浏览次数:3
分类:技术文章
本文共 5597 字,大约阅读时间需要 18 分钟。
MYvue.js 主要作用监听属性变化
class MYvue { constructor(options) { this.$options = options; this.$data = options.data; //数据劫持 this.observe(this.$data); this.$el = options.el; //包含Watcher创建 new Complie(options.el, this) } //数据劫持 observe(data) { if (!data || typeof data != 'object') { return; } Object.keys(data).forEach((key) => { //让数据可观测 //this.$data.test 改变 this.defineReactive(data, key, data[key]); //this.test 代理改变 this.proxyData(key); }) } //让数据可观测 defineReactive(obj, key, value) { var dept = new Dep(); //value值为对象递归遍历 this.observe(value); Object.defineProperty(obj, key, { get() { //属性被读取了,将来需要添加订阅 console.log('我被读取了'); //将Dep.target(当前的watcher对象存入Dep的deps) Dep.target && dept.addDep(Dep.target) return value; }, set(newVal) { if (newVal == value) { return; } value = newVal; console.log(key + '属性更行了,他更新的值是' + newVal); //如果我被改变, 我将来会在这里通知的 dept.notify(); //变化的数据,让watcher的update方法执行 }, enumerable: true, configurable: true }) } //代理data中的属性到vue实例上 proxyData(key) { Object.defineProperty(this, key, { get() { return this.$data[key] }, set(newVal) { this.$data[key] = newVal; } }) }}//Dep 用来管理wather,管理者的角色class Dep { constructor() { //存放所有的依赖(watcher),一个watcher对应一个属性 this.deps = []; } //收集订阅者 addDep(sub) { this.deps.push(sub); } //通知订阅更新 notify() { this.deps.forEach((sub) => { //你要更新了 sub.update() //update是watchr里面的一个函数 }) }}//监听器对象class Watcher { constructor(vm, key, cb) { // vm :Vue实例化对象 // key: 需要监听的属性 // cb: 是Watccher绑定的更新函数 this.vm = vm; this.key = key; this.cb = cb; Dep.target = this;//this指Watcher本身 this.vm[key] // 触发getter ,添加依赖 Dep.target = null; } update() { console.log('你的属性要更新了'); this.cb.call(this.vm, this.vm[this.key]); }}
Complie.js 把属性变化重新渲染html
class Complie { constructor(el, vm) { //遍历节点 this.$el = document.querySelector(el); this.$vm = vm; //编译 if (this.$el) { //转换内容为片段fragment this.$fragment = this.node2Fragment(this.$el); //执行编译 this.replaceTemplate(this.$fragment) //将编译完的html结果追加到$el this.$el.appendChild(this.$fragment); } } node2Fragment(el) { // createDocumentFragment 用来创建虚拟dom节点 var frag = document.createDocumentFragment(); let child; //讲el中所有的元素搬家到frag while (el.firstChild && (child = el.firstChild)) { frag.appendChild(child); } return frag; } //对el立面的内容进行替换 // 对el里面的内容进行替换 replaceTemplate(frag) { // console.log('frag.childNodes',frag.childNodes); var childNodes = Array.from(frag.childNodes); if (childNodes.length == 0) return; childNodes.forEach(node => { let txt = node.textContent; let reg = /\{\{(.*?)\}\}/g; // 正则匹配{ {}} // 只读属性 Node.nodeType 表示的是该节点的类型 // nodeType 属性可用来区分不同类型的节点,比如 元素, 文本 和 注释。 // 即是文本节点又有大括号的情况{ {}} if (node.nodeType === 3 && reg.test(txt)) { // console.log(RegExp.$1); // 匹配到的第一个分组 如: a.b, c let arr = RegExp.$1.split('.'); let valTest = this.$vm; arr.forEach(key => { valTest = valTest[key]; // 如this.a.b }); // 用trim方法去除一下首尾空格 node.textContent = txt.replace(reg, valTest).trim(); // 监听变化,第二步加的 // 给Watcher再添加两个参数,用来取新的值(newVal)给回调函数传参 new Watcher(this.$vm, RegExp.$1, newVal => { //这里是有属性改变的时候会更新数据 node.textContent = txt.replace(reg, newVal).trim(); }); } // v-modle数据的双向绑定 if (node.nodeType === 1) { // 元素节点 let nodeAttr = Array.from(node.attributes); // 获取dom上的所有属性,是个类数组 nodeAttr.length > 0 && nodeAttr.forEach(attr => { let name = attr.name; // v-model type let exp = attr.value; // c text if (name.includes('v-')) { node.value = this.$vm[exp]; // this.c 为 2 } // oninput .onclick node.addEventListener('input', e => { let newVal = e.target.value; // 相当于给this.c赋了一个新值 // 而值的改变会调用set,set中又会调用notify,notify中调用watcher的update方法实现了更新 this.$vm[exp] = newVal; }); }); } // 如果还有子节点,继续递归replaceTemplate if (node.childNodes && node.childNodes.length) { this.replaceTemplate(node); } }); }}
使用
Document { { song}}
主打歌为{
{ album.theme}}作词人为{ { singer}}等人。qq
转载地址:https://codeboy.blog.csdn.net/article/details/107440519 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月10日 16时54分28秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
TKDE 2020 | 综述:基于知识图谱的推荐系统
2019-04-29
休息时间!哪些业余活动能提升开发人员的技能?
2019-04-29
把人脑“森林”上传到计算机:人类脑计划只是一个科幻野心?
2019-04-29
智力测试:如何超越动物之智?
2019-04-29
事关人类生存?为什么要探寻AI系统的可解释性?
2019-04-29
安全工程师必知:常见Java漏洞有哪些?
2019-04-29
数据科学中的计量经济学技术
2019-04-29
突破边界:数据科学、数据工程和技术的未来
2019-04-29
一切有迹可循!优秀程序员的9个早期迹象
2019-04-29
在后台的python:众多程序员无法攻克的难题
2019-04-29
未来战争:装载AI的美国空军侦察机已经试飞……
2019-04-29
屡战屡败:为什么你会觉得学习编程很难?
2019-04-29
想成为数据工程师,你需要做哪些准备?
2019-04-29
巨人的阴影之下:爱因斯坦的科学家妻子从未实现过梦想……
2019-04-29
JavaScript的类出现了什么问题?
2019-04-29
注意这个数据科学错误,避免30多个小时的无用功……
2019-04-29
“狙击”特斯拉:电动汽车后起之秀的最后一战
2019-04-29
软件测试的未来:2021年需要关注的15大软件测试趋势
2019-04-29
几何机器学习:如何在基础科学领域成为现实??
2019-04-29
六大基本AI术语:如何做好人工智能咨询服务?
2019-04-29