当前位置: 首页 > Web前端 > HTML5

介绍一个让React和Vue抗衡的技术

时间:2023-04-04 23:17:48 HTML5

好吧,我承认我是头条党。React明明是天上掉馅饼,用Vue反其道而行之,给Vue加点东西还是可以和React抗衡的。然而,这正是Vue在过去两年中所做的事情。它不断地添加东西并不断地优化。按照它现在的发展速度,超越React在情理之中。如果我有一项技术,可以让React克服缺点,保持优点,Vue再怎么努力也赶不上?这个技术是ShadowWidget,开源的,入口在这里(github/rewgt)。1、无处可去,就回家。前几天看了一篇文章。一位专家建议,初学者入门人工智能最方便的方法不是模仿AlphaGo开发程序,而是找到十年二十年前的人工智能。领域的几篇重点论文,把经典文章吃透,然后再去编程。了解每项技术是如何产生的,解决了哪些问题,又引发了哪些新问题,梳理出一步步的演进过程,才能更清晰地把握下一步的重点和发展方向。逆向Windows的起源,从Win3.1、3.2、Win95、98、NT等,一直到现在的Window10,如果你是比尔盖茨,你认为砍掉一半的Windows版本会发展吗更好的?尤其是近十年推出了这么多次品,XP之后产生市场价值的就只有Win7和Win10了。这家公司纯粹是为了推产品而推产品,忘记了自己为什么做产品。这一点在IE产品线中体现得更为明显。IE6之后有十几个大版本,只有最近推出的Edge恢复正常(后人总结历史的时候,无疑会把IE6和Edge之间的所有IE都称为垃圾)。对于一个前端开发者来说,他面对的浏览器有两种,一种叫IE,一种叫other。MS自慰了这么多年,突然发现和他一起自慰的小弟一个也没有了。整齐地排成另一个队列,伙伴们把自己远远地甩在了后面。于是收起老板心态,老老实实做一个“不离路”的产品叫Edge。IE产品团队可能不都是低能的,但产品经理绝对是个例外。他从来没有想过开发这个产品给谁用,怎么用。被鄙视的时候,市场地位再强也是没有用的。那么,现在前端开发的初衷是什么?它是由DOM描述符覆盖JS控制的吗?显然不是,早期的网页很简单,前端开发的任务也很纯粹。用“html+CSS”来描述界面节点就够了,再用JS做交互控制。现在情况发生了变化,前端开发应该归类于成熟的、功能齐全的GUI开发。上个世纪末,我们只把Delphi、MFC、WxWidget这些开发称为界面开发。前端实现web开发(相关工具不叫GUI工具)。由于能力不足,开发了各种插件技术,如使用java、ActionScript工具来弥补不足。现在有了HTML5和CSS3,没有插件的网页表现力和平台原生的GUI没有太大区别。网站开发更适合作为GUI开发。随着移动设备的兴??起,java和ActionScript不再有效,尤其是当出现Angular、React、Vue等新兴框架时,可以轻松搞定大规模、复杂的前端开发,“网页开发””应该回到常规的“GUI开发”主线。GUI的发展比较初级,反映本质需求,在浏览器出现之前就已经广泛存在。2、Web可视化发展趋势我用Delphi开发比MFC更早。我在Delphi1.1发布后就开始使用它。在接下来的20年里,我也使用过VB、WxWidget、PythonTk、Qt、C#、XCode等GUI开发工具,总体印象是:Delphi建立的开发方式仍然是最好的,虽然Delphi日渐式微一天,很少有人提到它,现在它已经消失了。但是RAD(RapidApplicationDevelopment)开发模式并没有过时,一些新兴的工具,比如XCode,仍然继承了它的做法。将MFC、Delphi与前端开发工具进行比较,像MFC这样的工具很多,不支持所见即所得可视化设计的,比如Angular、Vue等,应该归入这一类,几乎没有像Delphi,是时候弥补一下了,ShadowWidget是个例外,但是ShadowWidget是新推出的,应用效果有待测试。一般的视觉设计在前端开发中是很难出现的。我猜主要有两个原因:为网页提供可视化设计比传统的GUI工具更难,比如Delpphi、Qt、XCode等传统的GUI工具只需要提供有限的元素。视觉设计封装不同于网页的可视化。它面向各种标签,数量大,变化多端。添加控件属性非常容易,也可以自由扩展。大量使用自定义标签是现代框架的重要设计方法。标注描述类似于命令行,海量命令行转化为可视化设计并不容易。受限于网页技术发展水平在Html5和Css3出现之前,原生网页的表现力非常有限,远远落后于Qt实现GUI效果的能力。在Html5、Css3弥补了这个缺点之后,javascript不适合模块化、工程化、大规模开发的缺点就凸显出来了,于是业界又出现了ES6、ES7、Babel等新东西。借助nodeJS整合工具链,这个过程就完成了,虽然还有一些缺陷。同时,Angular、React、Vue等框架也在前端技术不断涌现的条件下不断尝试最优的开发方式。主流框架仍在快速迭代演进,MVC、MVVM、FRP等方法不断推出,尚未形成共识的开发方法。总之,网页开发正在逐渐从现在的展示方式(编写HTML标签标签,或者使用JSX来定义界面)转向既强调展示又强调可视化的方式。ShadowWidget顺应了这一趋势,恰逢其时。如果发展得太早,估计会像QML一样变得默默无闻。在JS语言和框架还在快速变化的时候,试图规范和简化界面的表达是徒劳的。React核心库虽然只提供了虚拟DOM层面的解决方案,但其强大的函数式风格影响了其工具链上各类工具的定向选择,均已向函数式开发看齐。这也使得React工具的易用性远不如Vue。Vue基于MVVM框架,非常适合可视化形式(即页面运行方式)的界面开发方式。此外,当Vue也引入虚拟DOM、store、action等机制后,React引以为豪的功能也将逐渐在Vue中具备,Vue追赶React指日可待。以上提法是基于我对前端开发场景的理解:静态MVVM优于动态FRP架构。当然,玻璃钢也有自己的优势。如果两者选其一,你宁愿选择MVVM。如果两者都是可选的,至少在整体设计上也应该以MVVM为主,FRP为辅(两者其实是不同层次的,主辅是相对的,下面会有介绍)。让网页支持所见即所得的可视化设计是MVVM框架的最高形式。之前没有类似的工具,主要是技术做不到。ShadowWidget在设计之初就着手解决视觉设计的问题,立足点高于Vue。这个优势就像Vue一样,比React推出的晚,可以从React中学到很多东西。ShadowWidget也是后来推出的,可以吸收Vue的优点。不同的是,支持可视化需要在顶层进行设计,要将既定的MVVM框架改造为支持可视化并不容易。3.回归本源:如何继续享受jQuery?考虑一个应用场景。用户要开发一个网页,主体是展示一些文字和图片,还有少量的交互控制内容,比如输入反馈信息,点击“提交”按钮等。如果使用jQuery开发,代码不到100行。如果用React,会很麻烦,工具链很重。它远不如使用jQuery简单直接。或者您根本不使用任何库或框架。裸写JS就简单多了。在实际开发中,经常会遇到这样的场景,产品开发并不总是处理复杂的页面。裸写JS虽然可以减少麻烦,但往往会失控。有时会和别人对接,或者集成到别人的代码中。别人用React,你就得被同化;复杂,你必须迁移到框架;有时候,为了方便项目的统一维护,上面需要把所有的JS都塞进React里面。ShadowWidget强调实用性而非形式。它推荐的开发方式是:编程尽量使用ES5,使用导入库,然后直接在ES5中编码。按照React官方推荐的方法,定义一个Component类样式如下:classRedFlowerextendsReact.Component{constructor(props){//...}componentDidMount(){//...}render(){//。..}}如果你就这样开始你的编程之旅,你会被React工具链绑架,戴上小红帽,你不要也得有。ShadowWidget内部使用React.createClass()引入Component行为定义,因为直接支持ES5规范代码,不需要Babel翻译。这看起来很傻,但是非常实用。例如:main['.body.top.p.tool']={getDefaultProps:function(){varprops=T.Button.getDefaultProps();//props.attr=value;返回道具;},getInitialState:function(){varstate=this._getInitialState(this);//...返回状态;},$onClick:function(event){alert('clicked');},};不过ShadowWidget并不排斥ES6编程,自定义一个Component类可以使用ES6+语法,只需继承已有的符合ShadowWidget规范的Component类即可,不能继承React.Component,例如:classMyButton_extendsT。Button_{constructor(name,desc){super(name,desc);}getDefaultProps(){varprops=super.getDefaultProps();//props.attr=value;返回道具;}getInitialState(){varstate=super.getInitialState();//。..返回状态;}$onClick:function(event){alert('clicked');}}//转换为React类varAbstractButton=newMyButton_();varMyButton=AbstractButton._createClass({});varjsx=test;varMyButton2=AbstractButton._createClass({$onClick:function(event){alert('anotheronClick');}});varjsx2=test2;注意到了吗?上面的代码并没有直接定义React类,而是加了一层抽象。AbstractButton是类的类。它使用AbstractButton._createClass()实例化为React类。这样的设计,一方面可以让Component定义正常使用类继承,另一方面可以让Component的界面表现和行为定义有选择地分离,这是在线支持可视化设计的基础。4.返璞归真2:别让我一上来就陷入抽象!撇开网页设计的专属属性不谈,任何产品开发都需要设计师首先考虑用户如何操作。UI视觉设计过程是定义用户需求并将其分解为各个设计层次的过程。因此,界面设计是承前启后的,应该在编码之前完成,而不是和编码混合同步,或者先写底层代码,被动跟风。对于网络产品尤其如此。只要不使用网页开发命令行程序,网页就是用户交互最直接的媒介。React的JSX设计方式允许GUI设计与编码混合,并不能保证界面设计的首要性。其主流的Flux工具强化了如何设计数据传输,让开发者一上来就思考如何设计action和store。而不是界面的行为方式。react-route更加极端。鼓励大家在第一步就想好路由,以此为纲进行各种设计,非常不人道。ShadowWidget的第一步是考虑界面如何表现,只有UI设计清楚了,再去做其他的事情,然后第二步和第三步考虑数据如何流转,如何规划路由等等,这样“网页开发”返回对于常规的GUI开发,这是正确的姿势。Vue的易用性优于React,很大程度上是因为MVVM中的组件定义与界面表现一一对应,思路非常直白。ShadowWidget在MVVM的基础上增强了实时可视化能力,以所见即所得的方式缩短了每次闭环迭代的周期,从而使开发更加敏捷。举个具体例子来解释上面的意思。比如在设计一个播放器的时候,有两种思路。第一个是明确界面交互方式,是在界面上设计两个播放按钮来区分连播和单曲播放,还是Share一个按钮(但多了一个“连续播放”的选项框)?你想提供一个暂停按钮吗?暂停按钮是否与播放按钮合并?第二种思路是先确定使用了哪些数据,哪些动作驱动数据。比如要有一个播放器和一个播放列表,必须定义一个state属性来表示是暂停还是播放。驱动它变化的动作有播放、暂停、停止等,还有一个“是否连续播放”的属性,和播放列表一起作为payload附加在播放动作上,播放列表也有addition、删除、修改等动作。虽然两种思维方式都可以达到目的,但选择哪一种完全是工作方法对错的问题,而不是个人风格偏好的问题。第二种思路是错误的,“容易偏离需求”和“失去需求分解的层次感”,至于“设计过程不直观”是次要的、偶然的。很容易偏离要求。比如你为手表设计播放器,添加的“是否连续播放”选项不能放在界面上。如果使用第二种思路,就可以轻松忽略这个限制。另外,设计过程是分层的,从上到下,由粗到细,需求在每一层的设计中逐步分解。上层运行方式的改变会影响下一层的设计。如果以数据和动作作为思考的出发点,很容易失去设计的层次感,没有预先思考界面如何交互,容易延迟上层如何表现对下层设计的影响甚至扭曲。5.引入MVVM并与Flux框架共存以支持可视化设计的第一步是将Component的界面表现与其行为定义分离,即在设计模式中,我们只展示各个Component的可视化特征在可视化设计器中,不是捆绑其行为定义(如onClick事件处理),而是在产品正式运行时,即不处于设计状态时,正常初始化时会捆绑各个Component的行为定义。ShadowWidget视觉设计的输出是“escapetag”,保存在当前的*.html文件中,行为定义记录在js文件中,类似于Delphi的*.frm接口定义文件和*.pas代码实现文档。视觉设计的第二步是引入MVVM架构。ShadowWidget内部使用Object.defineProperty()来定义双源属性,这样comp.duals.attr=value这样的赋值语句就可以自动触发预设的setter函数。之后为双源属性添加监听机制,监听到的duals.attr的值变化会以事件的形式订阅,从而构建联动触发机制。双源属性解决了类似于Vue中的双向数据绑定的需求。ViewModel基于数据流的自动传输。ShadowWidget还增加了$if、$elif、$else、$for等控制指令,使界面按照特定规则自动生成数据驱动,并有触发机制、可计算属性、堆栈调用空间等设计等,使数据传输、组装、状态控制等变得灵活而强大。总之,ShadowWidget的MVVM机制与Vue基本类似,限于篇幅本文不再介绍。支持第三步可视化设计,让MVVM架构配合Flux单向数据流。这里只做简单的说明,以后会写文章介绍。在ShadowWidget中,如果每个Component都没有以编程方式参与行为自定义(具体是指在main[sPath]中定义投影类,或者使用idSetter[sId]实现定义),则视为一个View节点,而所有参与定制的Components都被视为ViewModel,每个ViewModel节点使用的props.attr和duals.attr都属于Model。这是一种通过扩展虚拟DOM节点能力实现的机制,不直接干扰Flux单向数据流机制。作为Store节点,支持双源属性的动作分发(dispatch)和触发(trigger)。视觉设计离不开MVVM架构,React技术栈离不开Flux机制。它的FunctionalReactProgramming概念与可视化编程兼容。MVVM主导上层粗粒度设计,而细粒度和横向连接则由FRP主导。两者的交汇点就是可见的参与行为定制的Component节点,即ViewModel节点。双源属性同时支持MVVM框架和FRP框架。两个框架分别负责“垂直嵌套定义接口”和“水平消息连接”,处理过程非常自然。6、工程开发的必要要求:技术分层和人员分工主流的前端框架都使用NodeJS组装工具链。它们都考虑了标准化和工程化开发的需求,使用NPM包来管理各层库的依赖关系。但是,对于技术分层带来的分工,它们一般都没有在框架层面提供有效的支持。不管Angular,React,还是Vue,都是重框架,不轻。快速启动不轻。基于独立开发产品和解决问题的能力,学习这些框架需要花费大量的时间。回想十年前,前端开发还是一个实习生随便翻翻参考书就能搞定的事情。现在需要一年以上的经验才能被认为是入门级。而且,不同素质的人写出来的代码质量差别很大。前端开发要对人员进行分级管理。这不仅是工程开发的要求,也是产品开发越来越复杂的必然要求。ShadowWidget构建的技术体系将前端开发分为组件(Widget)开发和界面(GUI)开发两部分。前者要求经销商具备完整的技能,后者只需要简单的技能,即:懂得使用html、css、javascript,掌握react入门知识,使用界面可视化设计器快速胜任工作。也就是说,我们预计前端开发者至少可以分为两类,一类是入门级,实习生级,主要工作是用别人开发过的组件搭积木,另一类是高级工程师,前开发人员。一类开发人员开发工件。相信各位老板都喜欢这种分工,可以省钱!专业化分工后,整体开发效率和质量将得到提升。(本文结束)