基于React开发范式的思考:写在Lesx发布之际

例子:lesx-example
webpack loader: lesx-loader

一些背景

现在前端框架已经呈现出React、Angular、Vue三足鼎立的局势,对于三者的对比以及技术选型的思考与争论也被讨论了非常多,比如知乎上的这个问题:react.js,angular.js,vue.js学习哪个好?,对于这个问题我们不再做过多赘述。但不管怎么样,现在github上star数最多、npm上安装量最大的还是React,阿里巴巴很多团队的技术栈也是基于React的。此篇文章也是基于React的开发范式来进行讨论的。

JSX的模板范式没有选择HTML模板,而是完全基于JS的,同时提供了一种JSX的语法糖,方便用户的开发。这样做是有几种考虑的,首先React是跨平台跨终端的,不仅可以在Web browser中运行,还可以基于RN在移动端APP、服务端基于SSR来运行,基于虚拟DOM的实现让他可以轻松地做到以上几点,另外,完全基于JS的开发可以不用掌握类似Vue/angular的指令式的语法,而是更多的偏向于使用纯js的语法开发范式,一次学习终身受益,而不用每次在开发的过程中还要去查看API文档。

但是,React的这种开发模式也带来了一个额外的问题,就是jQuery时代尊崇的UI与逻辑分离的最佳实践在JSX时代又有了极大的后退。于是我们一直在思考,能不能有一种模式,既能享受像Vue那样UI、展示(样式)与逻辑分离,方便维护与可扩展,又能享受React JSX的语法带来的便利呢?

Lesx的诞生

基于上面的思考,于是有了Lesx这个构建式的框架

构建式的框架并不是我们的首创,但是这个概念不知道是不是我们第一次正式提出来。业界已经有的AOT(Ahead Of Time)、非侵入式的框架比较知名的是svelte,他的开发范式跟Lesx比较相似,但是他并不是基于React或者哪个框架的,而是自己研发了一套底层组件机制,对于模板代码的解析也是基于自己实现的一套AST解析实现,语法类似于Handlebars。基于React的开发范式跟Lesx比较相似的还是react-templates,他称自己是:Lightweight templates for React。他只是把React Class的render部分抽了出来,DSL会被编译成React.createElement,然后生成一个函数作为React Class的render方法。同时,react-templates里还增添了很多类似vue的指令的功能,比如:rt-ifrt-repeat等,这样的框架的问题就是问题解决的并不是很彻底,抽出render部分的同时,我们还是需要对React创建部分需要大量的代码书写;同时,对于JSX语法扩展指令的模式增添了开发者的学习成本,后面开发中也需要不断地去查看文档如何使用这些指令,这是我们极不推崇的。

在这样的背景下,我花了两天时间,早起晚睡、憋屎憋尿的完成了基于React做到UI、展示(样式)与逻辑分离的构建式开发框架:Lesx的初版。

基于Lesx的开发模式

Lesx作为webpack的loader存在,使用类似Vue的单文件的开发范式,方便开发者的代码组织与开发:

index.lesx:

<style>a {color: red;}
</style><template><div><a onClick={this.func}>点我</a>{console.log(this.props)}<If condition={ this.props.valid }><div>{this.state.name}</div></If><Button type="primary" onClick={() => {alert('I am an antd button!');$setState({name: 'new name'});}}>antd button</Button><My /></div>
</template><script>module.exports = {props: {valid: true},state: {name: 'xiangzhong.wxz'},func({setState,}) {alert('I am a function!');setState({name: 'new name'});}};
</script>

很明显的,他有几个特点:

UI、样式与逻辑分离

lesx文件有style/template/script三个标签,内部分别存放他们对应的内容代码。

style部分我们默认使用跟css完全兼容同时有更多便利性语法的Sass语言,后面马上也会支持Less语法。

tenplate部分则完全是React的jsx语法,同时由以下几个扩展:

  • 我们基于babel插件jsx-control-statements提供了便利性的控制流标签,比如:IfFor等等,语法非常简单,一次学习终生高效!当然,有的同学可能会不认可这种标签扩展控制流的模式,此时你也可以继续使用你熟悉的三元运算符、数组map等方式来实现逻辑与展示控制,但是我们相信,标签控制符是更清晰、更容易维护的开发模式;
  • 你可以在DSL里面使用一些辅助性全局变量:

    • $setState: this.setState的简便写法,通过改变state值来触发UI渲染;
    • $getRef: React通过组件ref属性获取组件的简便写法;
    • $getProps: 获取React属性的简便性方法,相当于:this.xxx;

后面我们还会做一些其他的更高级的便利性扩展,比如:接入axios的异步操作,React的forceUpdate便利性机制等等。

script部分是用于书写前端逻辑处理的地方,你可以使用ES6的语法,做各种的数据处理,只需要最后把一个对象交给module.exports变量即可,这个对象可以包含如下内容:

  • state: React Component的state初始值,可以是对象也可以是函数;
  • props: React props初始值,可以是对象也可以是函数;
  • React组件的生命周期钩子函数: 比如:componentDidMount等,会被自动挂在到最终生成的React Component Class里面去;
  • 其他任意的属性或方法: 均会被挂在到React Component实例(this)上去,而且,对于方法部分会被自动绑定到this作用域(this.xxx.bind(this)) 。

对于异步处理部分,默认可以直接调用this.axios.xxx的方法来实现,并支持ES7:async/await语法:

module.exports = {async getData(reqArg = {}) {const res = await this.axios.post('url/post', reqArg);return res;}
};

同时,支持异步请求库可配置,可以在loader的配置里配置自己的异步请求库,此时会替换掉默认的axios。但这一块功能暂时还没有加入,承诺在接下来的一周之内会加上去。目前可以通过组件props传递的方式来使用异步,比如:

import App from './index.lesx';
import axios from 'axios';console.log('App:', App);render(<Appaxios={axios}components={{My,}}
/>, document.querySelector('#root'));

然后在lesx文件的script里面就可以这样用:

module.exports = {props: {valid: true},state: {id: 1001,},async getData(reqArg = {}) {const res = await this.props.axios.post('url/post', reqArg);return res;},clickHandler({setState,}) {const {id,} = this.state;const userData = this.getData({id,});setState({name: userData.name,});}
};

开发的极大便利:

UI库是我们在开发中重度依赖的部分,特别是对于像React这种完全组件化的开发框架来说,有个好用的UI框架简直是如虎添翼,会让我们的开发效率得到极大地提升!所以,我们的开发框架默认集成了国内最优秀的React UI库:antd,当然了,你也可以通过loader的配置来更改UI库,比如可以使用material-ui等。

在配置了UI库之后,无需做任何工作就可以直接在template标签里面使用该UI库的任意组件了,比如使用Button组件:

<script><Button type="primary" onClick={() => {alert('I am an antd button!');$setState({name: 'new name'});}}>antd button</Button>
</script>

Lesx不仅会自动帮你打包你使用到的组件,同时,还会自动帮你把组件的样式引入;另外,基于babel的插件:babel-plugin-import,我们做到了按需打包,只会把你用到的组件给打包进来,保证打包后的文件的最小体积。

开发者不需要书写React的组件生成代码

因为我们把React Component生成的过程全部放在了AOT里实现,所以开发者无需写React组件生成、UI库组件引入的操作,其实,开发者甚至不需要知道React的存在,也甚至更不需要学习React,唯一需要做的就是在渲染js文件中做一些组件引入以及渲染执行的操作,但是就这一块的成本其实是极低的。

目前前端的资源是极度缺乏的,整个互联网都缺前端,所以,我们在考虑如何释放前端人力这个方案的时候,我们是否可以考虑如何降低前端的上手成本,让后端同学可以上手前端开发,做到网后端开发赋能呢?其实Lesx的开发范式一开始就是为这个方向考虑的,在满足降低前端开发成本、降低前端开发复杂度、提高代码可维护性的同时,也可以很方便的提供给后端,让后端同学可以轻松上手前端开发,从而达到合作共赢的状态。对于前端人手紧缺的公司可以考虑这个方案的落地,也许会起到意想不到的效果。

同时,为了可扩展性,我们做了一些额外的处理。除了可以给Lesx DSL转成的Component传递属性然后可以在Lesx文件使用之外,当我们确实需要第三方或者自己之前基于React原生模式开发的组件需要拿过来直接使用的时候,我们提供了components属性,将任意的第三方组件放在conponents属性对象中,既可以直接在DSL中使用,如下:

import React, { Component } from 'react';
import { render } from 'react-dom';
import My from './My';
import App from './index.lesx';console.log('App:', App);render(<Appcomponents={{My,}}
/>, document.querySelector('#root'));

在上面我们引入了自己开发的My组件,并放在了Lesx DSL转成的App组件的components属性里,于是可以在lesx文件中像下面这样使用:

<style>{ /** style代码 */ }
</style><template><div><a onClick={this.func}>点我</a><My /></div>
</template><script>{ /** 逻辑代码 */ }
</script>

其实,基于这种开发范式针对不同的场景可以有不同的代码组织模式。如果你的界面不是很复杂,或者是比较典型的中后台应用场景(增删改查这种),你可以完全基于一个.lesx文件开发完你所有的页面逻辑,更多的则是依赖于第三方的UI库来为你的开发提供便利,说白了就是更多的依赖于组件搭积木式的开发范式,这个时候template就是开发的重点所在,而scriptstyle只是起到了添砖加瓦的便利性的开发,这个时候Lesx的职责就是页面级别的代码组织方式;如果是比较复杂的应用,比如SPA应用,这时我们可以基于Lesx来开发自己的一个个的React组件,然后加入vanex、dva等数据流管理框架来方便对大量数据的操作,最后通过react-router等router组件进行统一组织,然后进行渲染。这个时候Lesx的职责就不一样了,变成了组件级别的代码组织。

怎么样,有没有那么一点点的打动你的心呢?^_^ 如果有的话,不妨去体验下Lesx,相信会带给你不一样的开发体验。

例子:lesx-example
webpack loader: lesx-loader

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac共享单个磁盘_如何与您的所有设备共享酒店的单个Wi-Fi连接

mac共享单个磁盘Many hotels still limit you to one or two Wi-Fi devices per room–a frustrating limitation, especially when traveling with someone else. Connection restrictions can apply anywhere you have to log into a Wi-Fi network via a portal instead of …

Python FastApi:快速建立docker容器/挂载共享文件夹/导入导出

一、目的 a.快速把原有fastapi代码部署到docker&#xff0c;让docker在server运行。 b.不涉及docker深入设置。 c.使用python第三方lib少或简单。 二、步骤 ps:请提前安装docker 1.新建Dockerfile&#xff0c;放入到项目根目录 a.Dockerfile没有后缀. b.准备好requireme…

PHP-FPM 与 Nginx 的通信机制总结

PHP-FPM 介绍 CGI 协议与 FastCGI 协议 每种动态语言&#xff08; PHP,Python 等&#xff09;的代码文件需要通过对应的解析器才能被服务器识别&#xff0c;而 CGI 协议就是用来使解释器与服务器可以互相通信。PHP 文件在服务器上的解析需要用到 PHP 解释器&#xff0c;再加上对…

Android——监听事件总结

各种监听事件 1.按钮 Button&#xff08;1&#xff09;点击监听btn_1.setOnClickListener(new View.OnClickListener() { &#xff08;2&#xff09;长按监听btn_1.setOnLongClickListener(new View.OnLongClickListener() { 2.单选框 RadioGroupradio_gp.setOnCheckedChangeLi…

ChatGPT 大智近妖,从宇宙人生到手搓光刻机,从哄女朋友到写年终总结我们聊得非常开心,反而让人越来越忧心...

都说 ChatGPT 要干掉程序员&#xff0c;清理搜索引擎&#xff0c;取代Stack Overflow&#xff0c;还能消灭人类&#xff0c;这些有些言过其实了。ChatGPT 的定位是一个人工智能助理&#xff0c;它说&#xff0c;它的主要目的是通过回答用户的问题&#xff0c;为用户提供帮助。在…

如何在Windows Defender中安排扫描

Windows Defender automatically performs background scans during your PC’s idle moments, but doesn’t include an easy way to schedule a full scan. There is a way to do it, though. Windows Defender在PC空闲时自动执行后台扫描&#xff0c;但是没有包括安排完整扫…

复习深入笔记02:魔法方法/cookie,session,token/异常

魔法方法 对象生成 1.先调用__new__方法&#xff0c;生成空对象。控制对象生成。 2.当执行“对象类名&#xff08;namelqz&#xff09;”&#xff0c;触发类的__init__()

比特熊故事汇独家 | .NET 感恩专场

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;15分钟)大家好&#xff01;我是爱吃、爱玩、更爱学习技术&#xff0c;IT界新晋小红人&#xff0c;开发者的好朋友——比特熊&#xff01;比特熊&#xff1a;本期故事汇是.NET专场&#xff0c;今天一次性邀请到DOTNET领…

Ubuntu Core 给物联网提供更多安全支持

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; Canonical 是 Ubuntu 的一个桌面环境&#xff0c;该公司目前在云服务业务赚到了钱。因为 Ubuntu Core 为嵌入式设备带来了 Ubuntu 18.04 长期支持(LTS)代码库。Ubuntu Core 的镜像大小为 260MB&…

semantic ui要装什么才能使用

作者&#xff1a;呆呆笨笨链接&#xff1a;https://www.zhihu.com/question/32233356/answer/196799506来源&#xff1a;知乎著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。本答案将以两种方式讲解如何从零开始使用 Semantic-UI&#xff0c;…

用户帐户控制设置_创建快捷方式以避免用户帐户控制弹出式快捷方式

用户帐户控制设置There are numerous applications which, when launched, result in a UAC (User Account Control) warning being displayed. There are reasons why this security measure is a good idea, but it can also be extremely irritating. ElevatedShortcut lets…

rest_framework01:前后端分离\规范\简单例子(查询某本书)

web 开发模式 RESTful规范 1 数据的安全保障 url链接一般都采用https协议进行传输 注&#xff1a;采用https协议&#xff0c;可以提高数据交互过程中的安全性 2 接口特征表现 用api关键字标识接口url&#xff1a; https://api.baidu.comhttps://www.baidu.com/api注&#xff…

.NET Core如何通过SSL访问MongoDB?

【.NET Core】| 总结/Edison Zhou大家好&#xff0c;我是Edison。最近有一个ASP.NET Core通过SSL证书访问MongoDB的需求&#xff0c;但是在网上发现资料很少&#xff0c;于是调查了一番&#xff0c;做了如下的笔记&#xff0c;希望对你有用。背景在实际场景中&#xff0c;开发环…

在pom.xml中配置nexus上传地址

2019独角兽企业重金招聘Python工程师标准>>> <distributionManagement> <repository> <id>thirdparty</id> <url>http://&#xff5b;nexusIP地址&#xff5d;:8081/nexus/content/repositories/thi…

网页背景平铺_在大约十秒钟内为网页创建无缝平铺背景

网页背景平铺Creating a background image for your webpage (or desktop background) isn’t challenging at all. In fact, even a newbie Photoshop user can bash one out in about ten seconds. Here’s the simplest of simple methods with surprising, great results. …

9月11日学习内容整理:正则表达式,re模块

一、正则表达式&#xff1a;正则是很大的一个知识点&#xff0c;不会仅仅是下面这些东西 1、概念&#xff1a;正则表达式就是一种对字符串匹配的规则&#xff0c;注意是只对字符串&#xff0c;正则表达式和python没啥关系&#xff0c; 2、表达式&#xff1a; &#xff08;1&…

MongoDB的安装与使用

MongoDB是一款NoSql数据库。NoSql数据库叫非关系型数据库&#xff0c;NoSql的全名Not only sql。是为了解决高并发、高可用、高可扩展&#xff0c;以及大数据存储等一系列问题而产生的数据库解决方案。NoSql&#xff0c;它不能替代关系型数据库&#xff0c;只能作为关系型数据库…

linux 基准测试_如何对Linux系统进行基准测试:3个开源基准测试工具

linux 基准测试Linux’s command-line utilities can do anything, including perform benchmarks – but using a dedicated benchmarking program is a simpler and more foolproof process. These utilities allow you to perform reproducible tests across different syst…

.NET 7 新增的 IParsable 接口介绍

.NET 7 是一个新版本的 .NET&#xff0c;它新增了一个名为 IParsable 的接口。这个接口可以帮助开发人员更容易地在代码中解析字符串。IParsable 接口包含两个方法&#xff1a;Parse 和 TryParse。Parse 方法用于将一个字符串解析为指定类型的值。如果解析失败&#xff0c;则会…

spring+springMvc+struts的SSH框架整合

1.建立一个web项目 2.导入SSH框架所需jar包 3.配置web.xml文件 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns"http://java.sun.com/xml/ns/javaee" xsi:sc…