当前位置: 首页 > Web前端 > vue.js

从零实现MVVM模式的Web前端框架的雏形

时间:2023-04-01 00:10:25 vue.js

TNTWeb——腾讯新闻前端团队的全称。群里的小伙伴在Web前端、NodeJS开发、UI设计、手机APP等大前端领域都有实践和积累。目前团队主要支持腾讯新闻各项业务的前端开发。除了业务发展,它还积累了一些前端基础设施,以实现业务效率提升和产品创新。团队倡导开源共建,拥有各类技术人才。团队Github地址:https://github.com/tnfe本文作者ancai,项目地址:https://github.com/ancai/nvm1.前言本文是我自己的一个小实用总结业余时间做的项目,主要介绍现代Web前端框架的设计和实现思路,参考了Vue2.x版本的设计思路。2、MVVM模式web开发的程序员应该熟悉MVC的设计思想,网上有很多相关的文章。M(model)-V(view)-C(Controller)代表了一种程序组织结构模式,实现了数据、视图和逻辑的有效解耦。M代表数据状态,V代表视图界面,??Controller用于处理数据和视图的交互逻辑。后端web框架(如java中的springMVC、Struts2;nodejs中的express、koa等)至今仍在沿用这种设计模式。然而在前端领域,当涉及到用户界面编程时,MVC架构模型已经不再是主流。有几个原因:业务逻辑和UI混合,不利于扩展和复用,无法验证测试的复杂度,增加数据的复杂度。后来微软提出了MVVM架构模型,它与MVC的区别在于VM代替了C,ViewModel(视图模型)代替了controller。主要用于用户界面编程领域,提供双向数据绑定功能。View的变化会自动反映到ViewModel上,Model会通过ViewModel得到通知。当数据模型Model发生变化时,也会通过VM关联到View。MVVM架构模式的出现给前端开发带来了新的活力,前端开发编写单元测试变得更加容易。同时,借助ViewModel这个中间桥梁,开发者无需再关注一些DOM操作的交互细节,程序更加简洁优雅。结合基于组件的编程设计思想,前端模块更易于复用和扩展。ViewModel,一般由框架实现,主要提供双向数据绑定功能。更多关于对比推荐两篇文章:什么是MVVM框架?|MVCvsMVVM:KeyDifferenceswithExamples3.流程架构项目涉及模板、视图、数据、指令和依赖项的管理。从广义上看,框架主要完成模板和数据的双向绑定。利用数据劫持相关技术跟踪数据变化,引入发布-订阅模型完成对属性的依赖管理。另一方面,它涉及解析模板,提取模板中的指令和表达式,将它们与数据相关联,并初始化视图。模板和数据通过观察者连接,让数据变化直接映射到视图;同时,需要监听视图上与输入相关的事件,以便当输入发生变化时,直接映射到数据模型。从工程处理的角度来看,可以分为初始化、数据监控、模板编译和框架函数四个步骤。初始化过程主要是获取调用者传递过来的配置信息,预处理模型数据和模板,将一些关键属性委托给上层。数据监控环节涉及普通JavaScript对象的劫持,以及数组的增强处理。数据属性的依赖注入是通过发布-订阅模型完成的,并与观察者相关联。在模板编译过程中,解析一个类似HTML的模板,提取其中的变量表达式和相关指令,并将watcher与数据模型关联起来。上面给出了项目中的核心类图。Observer实现数据劫持。Dep相当于一个同时关联了Watcher和Observer的发布-订阅者。Compile负责解析模板,进一步提取和获取Directives类并关联Parser和Watcher。Parser用于解析指令以产生视图UI,而Watcher使用Batcher来批量处理更新更改。项目代码的目录结构比较简单。src目录下一共有14个代码文件,代码总行数在千行左右,理解起来不是很难。index.js为入口文件,模板编译相关的处理逻辑放在compile文件夹中,observer.js文件包含数据劫持相关的处理逻辑,value.js包含将字符串类型的属性表达式转换为对象数据处理逻辑,dep.js实现了一个简单的发布-订阅模型来关联数据状态变化和watcher实例。watcher.js中有详细的注释说明调用了哪个链接。另外,整个项目只是简单的使用webpack搭建,打包后的体积也很小。4.数据劫持的实现利用ES5中提供的object.definePropertyAPI重新定义get和set属性访问器来劫持数据。主要增强对普通对象和数组的处理,监听数据变化,通知依赖。第一次访问属性时注入依赖,通常是模板第一次初始化时,获取state属性的表达式,此时注入state属性的依赖,这里的依赖是watcher实例;当数据发生变化时,通过dep-release订阅方式通知watcher实例更新视图状态。5.模板编译模板的编译是在不使用虚拟DOM节点的情况下实现的,直接从原始html模板开始,遍历字符串模板,在里面收集指令。同时解析表达式,获取模型数据的依赖注入,第一次加载时会关联到watcher。对于不同类型的指令,对应不同的分析处理器,分为普通指令、事件指令、双向绑定指令、if/for指令等,其中涉及到if/for指令,需要创建新的执行上下文并关联孩子的环境数据。6.关键代码实现了上面两张图中dependencymanager和watcher的简单实现。dependencymanager可以看作是一种发布-订阅模型设计,即通过Dep类watcher订阅模型数据。当模型数据发生变化时,观察者会知道。有surface图时watcher的简单处理逻辑,当模板编译解析表达式时,会创建一个watcher实例,当访问模型数据的值时,会新建watcher实例注入其中。通过这种方式,watcher实例充当了模板编译和模型数据之间的桥梁。7.总结本项目没有使用虚拟节点(virtualDOMnodes),直接由字符串模板编译成视图部分。有点难懂的部分:属性表达式的抽取和解析,依赖的注入,if和for指令的处理,watchers的实现。作为一个能力薄弱的程序员,我无法像前端技术专家那样去打造一个成熟的前端框架。通过本文的简单讲解,希望能帮助有同样困惑的朋友加深对MVVM和前端框架原理的理解。请自动忽略它。本项目完整源码见最后部分,给出了详细的示例。8.代码示例源代码示例9.TeamTNTWeb-腾讯新闻前端团队,TNTWeb致力于行业前沿技术的探索和团队成员个人能力的提升。针对前端开发者,我们整理了最新的小程序和web前端技术的优质内容,每周更新?,欢迎star,github地址:https://github.com/tnfe/TNT-每周