learn.lianglianglee.com/专栏/前端工程化精讲-完/07 低代码工具:如何用更少的代码实现更灵活的需求.md.html
2022-05-11 19:04:14 +08:00

385 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>07 低代码工具:如何用更少的代码实现更灵活的需求.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/前端工程化精讲-完/00 开篇词 建立上帝视角,全面系统掌握前端效率工程化.md.html">00 开篇词 建立上帝视角,全面系统掌握前端效率工程化.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/01 项目基石:前端脚手架工具探秘.md.html">01 项目基石:前端脚手架工具探秘.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/02 界面调试:热更新技术如何开着飞机修引擎?.md.html">02 界面调试:热更新技术如何开着飞机修引擎?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/03 构建提速:如何正确使用 SourceMap.md.html">03 构建提速:如何正确使用 SourceMap.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/04 接口调试Mock 工具如何快速进行接口调试?.md.html">04 接口调试Mock 工具如何快速进行接口调试?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/05 编码效率:如何提高编写代码的效率?.md.html">05 编码效率:如何提高编写代码的效率?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/06 团队工具:如何利用云开发提升团队开发效率?.md.html">06 团队工具:如何利用云开发提升团队开发效率?.md.html</a>
</li>
<li>
<a class="current-tab" href="/专栏/前端工程化精讲-完/07 低代码工具:如何用更少的代码实现更灵活的需求.md.html">07 低代码工具:如何用更少的代码实现更灵活的需求.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/08 无代码工具:如何做到不写代码就能高效交付?.md.html">08 无代码工具:如何做到不写代码就能高效交付?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/09 构建总览:前端构建工具的演进.md.html">09 构建总览:前端构建工具的演进.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/10 流程分解Webpack 的完整构建流程.md.html">10 流程分解Webpack 的完整构建流程.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/11 编译提效:如何为 Webpack 编译阶段提速?.md.html">11 编译提效:如何为 Webpack 编译阶段提速?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/12 打包提效:如何为 Webpack 打包阶段提速?.md.html">12 打包提效:如何为 Webpack 打包阶段提速?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/13 缓存优化:那些基于缓存的优化方案.md.html">13 缓存优化:那些基于缓存的优化方案.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/14 增量构建Webpack 中的增量构建.md.html">14 增量构建Webpack 中的增量构建.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/15 版本特性Webpack 5 中的优化细节.md.html">15 版本特性Webpack 5 中的优化细节.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/16 无包构建:盘点那些 No-bundle 的构建方案.md.html">16 无包构建:盘点那些 No-bundle 的构建方案.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/17 部署初探:为什么一般不在开发环境下部署代码?.md.html">17 部署初探:为什么一般不在开发环境下部署代码?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/18 工具盘点:掌握那些流行的代码部署工具.md.html">18 工具盘点:掌握那些流行的代码部署工具.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/19 安装提效:部署流程中的依赖安装效率优化.md.html">19 安装提效:部署流程中的依赖安装效率优化.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/20 流程优化:部署流程中的构建流程策略优化.md.html">20 流程优化:部署流程中的构建流程策略优化.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/21 容器方案:从构建到部署,容器化方案的优势有哪些?.md.html">21 容器方案:从构建到部署,容器化方案的优势有哪些?.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/22 案例分析:搭建基本的前端高效部署系统.md.html">22 案例分析:搭建基本的前端高效部署系统.md.html</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/23 结束语 前端效率工程化的未来展望.md.html">23 结束语 前端效率工程化的未来展望.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>07 低代码工具:如何用更少的代码实现更灵活的需求</h1>
<p>在进入到这一课的内容之前先让我们来回顾下,通过脚手架工具生成初始化代码,以及通过 Snippet 工具生成代码片段的方式。两种方案的相同在于,通过简单的输入和选择就能获得预设后的项目代码。这种转化方式对于效率的提升效果是清晰可见的。于是有人就想到,能不能更进一步,将我们日常开发的手写代码过程,都转变为通过使用工具来快速生成呢?于是就有了开发效率篇的最后两节内容:低代码开发和无代码开发。这节课我们先来谈低代码开发。</p>
<h3>什么是低代码开发</h3>
<p><strong>低代码开发</strong>Low-Code Development<strong>LCD</strong>),是一种<a href="https://en.wikipedia.org/wiki/Low-code_development_platform">很早被提出2011</a>的开发模式,开发者<strong>主要通过图形化用户界面和配置</strong>来创建应用软件,而不是像传统模式那样<strong>主要依靠手写代码</strong>。对应的,提供给开发者的这类低代码开发功能实现的软件,称为<strong>低代码开发平台</strong>Low-Code Development Platform <strong>LCDP</strong>)。低代码开发模式的开发者,通常不需要具备非常专业的编码技能,或者不需要某一专门领域的编码技能,而是可以通过平台的功能和约束来实现专业代码的产出。</p>
<p>从定义中我们可以看到,低代码开发的工作方式主要依赖操作图形化的用户界面,包括拖拽控件,以及修改其中可被编辑区域的配置。这种可视化的开发方式,可以追溯到更早的 Dreamwaver 时期。而随着前端项目的日趋复杂,这种方式已不再适应现代项目的需求,于是渐渐被更专业的工程化的开发模式所取代。</p>
<p>但是,快速生成项目代码的诉求从未消失。人们也慢慢找到了实现这个目的的两种路径:</p>
<ul>
<li>一种是在高度定制化的场景中,基于经验总结,找到那些相对固定的产品形态,例如公司介绍、产品列表、活动页面等,开放少量的编辑入口,让非专业开发者也能使用。下一课介绍的<strong>无代码开发</strong>,主要就是面向这样的场景需求。</li>
<li>另一类则相反,顺着早期可视化开发的思路,尝试以组件化和数据绑定为基础,通过抽象语法或 IDE 来实现自由度更高、交互复杂度上限更高的页面搭建流程。这种项目开发方式通常需要一定的开发经验与编码能力,只是和普通编码开发方式相比,更多通过操作可视化工具的方式来达到整体效率的提升,因此被称为<strong>低代码开发。</strong></li>
</ul>
<p>在实际场景中,尤其是商用的低代码平台产品,往往提供的是上面两种开发方式的结合。</p>
<h4>低代码开发的典型应用场景</h4>
<p>低代码开发的一类典型应用场景是在 PC 端中后台系统的开发流程中,原因如下:</p>
<ol>
<li>尽管中后台系统的具体页面布局并不固定,但整体 UI 风格较统一,可以基于统一的 UI 组件库来实现搭建,通过组件拖拽组合即可灵活组织成不同形态功能的页面,因此适用于低代码类型的开发模式。</li>
<li>中后台系统涉及数据的增删改查,需要有一定的编码调试能力,无法直接通过 UI 交互完成,因此不适用无代码开发模式。</li>
</ol>
<p>以中后台系统的开发为目标,低代码开发的方式还可以<strong>细分为以下两种</strong>:基于编写 JSON 的开发方式,和基于可视化操作平台的开发方式,下面我们来依次介绍一下。</p>
<h3>基于编写 JSON 的低代码开发</h3>
<p>当我们去审视一个项目前端部分的最终呈现时,可以发现:</p>
<ol>
<li>一个项目的前端部分本质上呈现的是通过路由连接的不同页面。而前端开发的目标就是<strong>最终输出页面的展示与交互功能</strong></li>
<li>如果学过浏览器基本原理,你会知道:每一个页面的内容在浏览器中,最终都归结为<strong>DOM 语法树DOM Tree+ 样式Style+ 动态交互逻辑Dynamic Logic</strong></li>
<li>在组件化开发的今天,一个规范定义的组件包含了特定功能的 DOM 子树和样式风格。因此页面的内容又可以定义为:<strong>组件树Component Tree+ 动态交互逻辑Dynamic Logic</strong></li>
</ol>
<p>而基于 JSON-Schema 的低代码开发的切入逻辑是:</p>
<ol>
<li>在特定场景下,例如开发中后台增删改查页面时,大部分前端手动编写的代码是模式化的。</li>
<li>页面组件结构模板和相应数据模型的代码组织,可以替换为<strong>更高效</strong>的 JSON 语法树描述。</li>
<li>通过制定用于编写的<strong>JSON 语法图式JSON Schema</strong>,以及封装能够渲染对应 JSON 语法树的运行时工具集,就可以提升开发效率,降低开发技术要求。</li>
</ol>
<p>下图中的代码就是组件语法树示例(完整的示例代码参见 <a href="https://github.com/fe-efficiency/lessons_fe_efficiency/tree/master/07_low_code">07_low_code</a>),我们通过编写一个简单的 JSON 语法树以及对应的编译器,来展示低代码开发的模式。</p>
<p><img src="assets/CgqCHl9MyGOAKUrZAAFHKI-ma8o592.png" alt="Drawing 0.png" /></p>
<h4>编写 JSON 开发的高效性</h4>
<p>编写 JSON 语法树开发的高效性体现在:</p>
<ol>
<li>由于只用编写 JSON ,而隐藏了前端开发所需的大量技术细节(构建、框架等),因此降低了对开发人员的编码要求,即使是非专业的开发人员,也可以根据示例和文档完成相应页面的开发。</li>
<li>由于只用编写 JSON ,大量的辅助代码集成在工具内部,整体上减少了需要生成的代码量。</li>
<li>可以对中后台系统所使用的常用业务组件进行抽象,然后以示例页面或示例组件的方式,供用户选择。</li>
</ol>
<h4>编写 JSON 开发的缺点</h4>
<p>但另一方面,这种方式也存在着一些不足:</p>
<ol>
<li><strong>输入效率</strong>:单从组件结构的描述而言,使用 JSON 描述的代码量要多于同等结构的 JSX 语法(参见示例代码 <a href="https://github.com/fe-efficiency/lessons_fe_efficiency/tree/master/07_low_code">07_low_code</a>),对于有经验的前端开发者而言,通常无法第一时间感受到效率的提升。</li>
<li><strong>学习记忆成本</strong>:由于引入了新的 JSON 语法图式,无论对于前端开发者、后端开发者还是非专业的人员来说,上手的学习成本都不可避免。此外,不同组件存在不同属性,要在实际编写过程中灵活运用,对记忆量也是一个考验。而反复查阅文档又会造成效率的下降(对于这个问题,有个优化方案是利用 IDE Snippets 的选项功能生成对应的语法提示)。</li>
<li><strong>复用性和可维护性</strong>:对于多页面存在可复用业务组件的情况,在 JSON 编写的模式下往往需要手动复制到各页面 JSON 中,牺牲了复用组件的可维护性。此外,对于功能复杂的页面,对应的 JSON 长度也会让维护体验变得不太美好。</li>
<li><strong>问题排查难度增加</strong>:这个问题涉及面向人群,如果是非专业的人员从事 JSON 的开发过程,当遇到问题时,在如何排查上可能造成阻碍,因此通常需要配备额外的专业人员来提供技术支持。</li>
</ol>
<p>针对编写 JSON 过程中的输入效率、记忆成本和可维护性等问题,许多低代码工具进一步提供了可视化操作平台的工作方式。下面再让我们来了解下,这种方式是怎么解决上述问题的。</p>
<h3>基于可视化操作平台的低代码开发</h3>
<p>可视化的低代码操作平台把编写 JSON 的过程变成了拖拽组件和调试属性配置,如下图所示,这样的交互方式对用户来说更直观友好,开发效率也会更高。</p>
<p><img src="assets/CgqCHl9MyHmAdpfQAAdLANM4tuQ134.png" alt="Drawing 1.png" /></p>
<h4>可视化操作平台的基本使用方式</h4>
<p>绝大部分的可视化操作平台都将界面布局分为三个区域:左侧的<strong>组件选择区</strong>,中部的<strong>预览交互区</strong>以及右侧的<strong>属性编辑区</strong>。这三个区域的排布所对应的,也是用户<strong>生成页面的操作流程</strong></p>
<ul>
<li>首先,在左侧面板中选择组件。</li>
<li>然后,拖入中间预览区域,并放置到合适的容器块内。</li>
<li>最后,调试右侧面板中新移入的组件属性。</li>
<li>调试完成后,进行下一个组件的循环操作直到整个页面搭建完成。</li>
</ul>
<h4>可视化操作平台的生产效率影响因素</h4>
<p>通常来说,在组件数量不变的情况下,编写 JSON 的产出效率更大程度上取决于编写页面的开发者的技术熟练度。但在使用可视化操作平台时却并非如此:我们会看到,平台本身的很多方面也会直接影响使用者的产出:</p>
<ul>
<li>首先,平台的<strong>功能完备性</strong>直接决定了用户<strong>产出的上限</strong>:开发者不可能在平台里使用组件区没有显示的组件,也不可能创建编辑区不存在的属性。这就迫使平台开发者需要尽可能完整地陈列所有类型的组件,以及通过定义组件类型描述,来获取所有可以被编辑的属性和方法。包括用户交互和数据对组件的影响,这些都需要平台以合适的使用方式提供给用户。</li>
<li>其次,平台的<strong>逻辑自洽性</strong>决定了用户产出的<strong>质量</strong>:在代码的组织上,不同组件之间不可以任意组合,错误的组合可能导致显示与功能的异常。如果平台只是简单罗列所有组件,而对其中的规则不加以限制,就可能导致用户在使用过程中出现意料外的产出结果。所以,平台开发者需要有一套完整的组件关联关系表,并反映到交互呈现中。</li>
<li>最后,平台提供的<strong>交互易用性</strong>决定了用户的产出<strong>效率</strong>:尽管大部分低代码平台都提供了相似的区域操作逻辑,但真正影响用户使用效率的往往是很多细节的控制。例如,与单纯依靠光标选取组件相比,在侧边栏提供节点树的方式可以更大程度减少误选;与简单陈列所有组件相比,合适的分类,以及当选择特定组件时筛选出可添加的部分组件,更能减少用户搜索的时间,同时减少可能的出错;一些平台提供了操作栈回放的功能,能减少用户误操作后的修复成本,等等。</li>
</ul>
<h3>低代码开发的产品</h3>
<p>低代码开发的产品有很多,其中既包括商用的产品,例如 Kony、OutSystems、Mendix、Appian、iVX国内也包括开源类的产品例如阿里飞冰、百度 Amis、贝壳河图、Vvvebjs、react-visual-editor 等。这里就不一一介绍了,感兴趣的话,你可以进一步搜索了解。</p>
<h3>总结</h3>
<p>这节课我们介绍了低代码开发的概念和它的基本应用场景,也了解了低代码开发的两种基本开发模式:基于编写 JSON 的方式和基于可视化操作平台的方式。</p>
<p>前者对普通的项目开发流程做了抽象,将编写不同功能模块的代码变为只编写组件语法树描述信息,这种方式在一定程度上降低了使用者的技术要求,提升了开发的效率,但是在一些方面仍然不甚理想。而平台化的开发模式相对而言解决了编写 JSON 模式下的一些问题,但是要搭建一个功能完备、使用逻辑自洽和交互性良好的平台也并非易事。</p>
<p>通过这节课的学习,希望能为你提供一种新的项目技术方案,在合适的应用场景下,可以考虑使用低代码工具来提升开发效率。今天的课后思考题是:这节课里讲到的低代码工具主要面向什么样的用户群体?</p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/前端工程化精讲-完/06 团队工具:如何利用云开发提升团队开发效率?.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/前端工程化精讲-完/08 无代码工具:如何做到不写代码就能高效交付?.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997755ce8d3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>