博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
50行代码的MVVM,感受闭包的艺术
阅读量:6901 次
发布时间:2019-06-27

本文共 2330 字,大约阅读时间需要 7 分钟。

我们先看一下运行结果

163f3a61871d9c2c?imageslim

name 和 age 被响应式的渲染出来,在 2s 后我们修改了 name 的值,同样能在页面正确更新。

我们来看一下最小化的 MVVM 的源码

class Vue{    constructor(opt){        this.opt = opt        this.observe(opt.data)        let root = document.querySelector(opt.el)        this.compile(root)    }    // 为响应式对象 data 里的每一个 key 绑定一个观察者对象    observe(data){         Object.keys(data).forEach(key => {            let obv = new Observer()             data["_"+key] = data[key]            // 通过 getter setter 暴露 for 循环中作用域下的 obv,闭包产生            Object.defineProperty(data, key, {                get(){                    Observer.target && obv.addSubNode(Observer.target);                    return data['_'+key]                },                 set(newVal){                    obv.update(newVal)                    data['_'+key] = newVal                }            })        })    }    // 初始化页面,遍历 DOM,收集每一个key变化时,随之调整的位置,以观察者方法存放起来        compile(node){        [].forEach.call(node.childNodes, child =>{            if(!child.firstElementChild && /\{\{(.*)\}\}/.test(child.innerHTML)){                let key = RegExp.$1.trim()                child.innerHTML = child.innerHTML.replace(new RegExp('\\{\\{\\s*'+ key +'\\s*\\}\\}', 'gm'),this.opt.data[key])                 Observer.target = child                this.opt.data[key]                 Observer.target = null            }            else if (child.firstElementChild)             this.compile(child)        })    }    }// 常规观察者类class Observer{    constructor(){        this.subNode = []        }    addSubNode(node){        this.subNode.push(node)    }    update(newVal){        this.subNode.forEach(node=>{            node.innerHTML = newVal        })    }}复制代码

【重点分析】接下来梳理一下这段代码的思路,顺便了解一下 MVVM 闭包的艺术:

  • [observe 函数]:首先我们会对需要响应式的 data 对象进行 for 循环遍历,为 data 的每一个 key 映射一个观察者对象
    • 在 ES6 中,for 循环每次执行,都可以形成闭包,因此这个观察者对象就存放在闭包中
    • 闭包形成的本质是 内层作用域中堆地址暴露,这里我们巧妙的用 getter/setter 函数暴露了 for 循环里的观察者
  • [compile 函数]:我们从根节点向下遍历 DOM,遇到 mustache 形式的文本,则映射成 data.key 对应的值,同时记录到观察者中
    • 当遍历到 {
      {xxx}} 形式的文本,我们正则匹配出其中的变量,将它替换成 data 中的值
    • 为了满足后续响应式的更新,将该节点存储在 key 对应的观察者对象中,我们用 getter 函数巧妙的操作了闭包
  • 在页面初次渲染之后,后续的 eventLoop 中,如果修改了 key 的值,实际会通过 setter 触发观察者的 update 函数,完成响应式更新

附上述演示案例的完整代码

  

姓名

{

{name}}

年龄

{

{age}}

复制代码

作者:maodayeyeye
原文发布时间:2018年06月12日
本文来源 如需转载请紧急联系作者
你可能感兴趣的文章
linux内核下载 2.6.32,linux内核升级到2.6.32
查看>>
client linux amd64,linux 下安装minio并配置
查看>>
linux中配置nginx,linux中编译安装和配置nginx
查看>>
Linux循环sql调用,shell中使用SQL实现查询
查看>>
linux中make命令大全,Linux中的命令 make -f 是什么意思
查看>>
qcustomplot在Linux开发板,QCustomplot的使用以及编译动态链接库的过程
查看>>
aes逆字节替换C语言,AES加密算法之字节替换操作
查看>>
2017福建省c语言编程题,[蓝桥杯][2017年第八届真题]九宫幻方-题解(C语言代码)
查看>>
c语言实验九结构体和共用体的区别,[C语言程序设计实验九结构体和共用体答案西北民大电气院.doc...
查看>>
android刷机工具mac版,刷机精灵mac版
查看>>
android+如何封装功能,Android - 如何封装 opengl 流程
查看>>
android c 高级编程源码,Objective-C高级编程
查看>>
android 剪贴板增强工具,剪切板增强工具(ClipboardFusion Pro)
查看>>
opencv android盒子,入门免费阅读_深入OpenCV Android应用开发免费全文_百度阅读
查看>>
html中加入定位按钮,HTML CSS按钮定位
查看>>
android 仿写开发者头条,android高仿今日头条富文本编辑(发布文章)
查看>>
microsoft html 帮助,Microsoft HTML Help 1.4
查看>>
html写顶部固定悬浮菜单栏,JS实现自动固定顶部的悬浮菜单栏效果
查看>>
不能创建对象qmdispatch_automation服务器不能创建对象。如何解决?
查看>>
jenkins的热部署_初体验Jenkins安装并进行Maven项目自动化部署
查看>>