前言
提示:为什么要用amis?
在经历了十几年的发展后,前端开发变得越来越复杂,门槛也越来越高,要使用当下流行的 UI 组件库,你必须懂 npm、webpack、react/vue,必须熟悉 ES6 语法,最好还了解状态管理,比如 Redux,如果没接触过函数式编程,光入门都很费劲,而入门之后会发现它还有巨大的 生态,相关的库有 2347 个,很多功能相似,挑选成本高。
然而前端技术的发展不会停滞,等学完这些后可能会发现大家都用 Hooks 了、某个打包工具取代 Webpack 了……
这些都是官方的说明了。。。我为什么要用这个呢?
因为公司需要,公司需要生成报表实现配置什么组件,我就生成什么,当然主要还是查询以及报表
一、简介
amis 是一个低代码前端框架,它使用 JSON 配置来生成页面,可以减少页面开发工作量,极大提升效率。
有时候其实只想做个普通的增删改查界面,用于信息管理,类似下面这种:
这个界面虽然用 Bootstrap 及各种前端 UI 库也能做出个大概,但仔细观察会发现它有大量细节功能,比如:
可以对数据做筛选
有按钮可以刷新数据
编辑单行数据
批量修改和删除
查询某列
按某列排序
隐藏某列
开启整页内容拖拽排序
表格有分页(页数还能同步到地址栏,不过这个例子中关了)
有数据汇总
支持导出 Excel
「渲染引擎」那列的表头有提示文字
鼠标移动到「平台」那列的内容时还有放大镜符号,可以展开查看更多
如果往下拖动还有首行冻结来方便查看表头(因为文档页面的限制,这个功能在这里看不出来)
全部实现这些需要大量的代码。
二、amis 的其它亮点
1. 提供完整的界面解决方案:其它 UI 框架必须使用 JavaScript 来组装业务逻辑,而 amis 只需 JSON 配置就能完成完整功能开发,包括数据获取、表单提交及验证等功能,做出来的页面不需要经过二次开发就能直接上线;
2. 大量内置组件(100+),一站式解决:其它 UI 框架大部分都只有最通用的组件,如果遇到一些稍微不常用的组件就得自己找第三方,而这些第三方组件往往在展现和交互上不一致,整合起来效果不好,而 amis 则内置大量组件,包括了富文本编辑器、代码编辑器、diff、条件组合、实时日志等业务组件,绝大部分中后台页面开发只需要了解 amis 就足够了;
3. 支持扩展:除了低代码模式,还可以通过 自定义组件 来扩充组件,实际上 amis 可以当成普通 UI 库来使用,实现 90% 低代码,10% 代码开发的混合模式,既提升了效率,又不失灵活性;
4. 容器支持无限级嵌套:可以通过嵌套来满足各种布局及展现需求;
5. 经历了长时间的实战考验:amis 在百度内部得到了广泛使用,在 5 年多的时间里创建了 3.8 万页面,从内容审核到机器管理,从数据分析到模型训练,amis 满足了各种各样的页面需求,最复杂的页面有超过 1 万行 JSON 配置。
三、amis 不适合做什么?
使用 JSON 有优点但也有明显缺点,在以下场合并不适合 amis:
大量定制 UI:JSON 配置使得 amis 更适合做有大量常见 UI 组件的页面,但对于面向普通客户(toC)的页面,往往追求个性化的视觉效果,这种情况下用 amis 就不合适,实际上绝大部分前端 UI 组件库也都不适合,只能定制开发。
极为复杂或特殊的交互:
有些复杂的前端功能,比如 可视化编辑器,其中有大量定制的拖拽操作,这种需要依赖原生 DOM 实现的功能无法使用 amis。
但对于某些交互固定的领域,比如图连线,amis 后续会有专门的组件来实现。
四、amis 使用方法
JS SDK,可以用在任意页面中
React,可以用在 React 项目中
SDK 版本适合对前端或 React 不了解的开发者,它不依赖 npm 及 webpack,可以像 Vue/jQuery 那样外链代码就能使用。
下载方式:
github 的 releases,文件是 sdk.tar.gz。
使用 npm i amis 来下载,在 node_modules\amis\sdk 目录里就能找到。
新建一个 hello.html 文件,内容如下:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>amis demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1"
/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<link rel="stylesheet" href="sdk.css" />
<link rel="stylesheet" href="helper.css" />
<link rel="stylesheet" href="iconfont.css" />
<!-- 这是默认主题所需的,如果是其他主题则不需要 -->
<!-- 从 1.1.0 开始 sdk.css 将不支持 IE 11,如果要支持 IE11 请引用这个 css,并把前面那个删了 -->
<!-- <link rel="stylesheet" href="sdk-ie11.css" /> -->
<!-- 不过 amis 开发团队几乎没测试过 IE 11 下的效果,所以可能有细节功能用不了,如果发现请报 issue -->
<style>
html,
body,
.app-wrapper {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="root" class="app-wrapper"></div>
<script src="sdk.js"></script>
<script type="text/javascript">
(function () {
let amis = amisRequire('amis/embed');
// 通过替换下面这个配置来生成不同页面
let amisJSON = {
type: 'page',
title: '表单页面',
body: {
type: 'form',
mode: 'horizontal',
api: '/saveForm',
body: [
{
label: 'Name',
type: 'input-text',
name: 'name'
},
{
label: 'Email',
type: 'input-email',
name: 'email'
}
]
}
};
let amisScoped = amis.embed('#root', amisJSON);
})();
</script>
</body>
</html>
这里我使用的Vue,因为这个框架是基于react组件去渲染的,所以安装依赖就可以了!!
Vue中引用React组件:
npm i -S vuera
npm install --save react react-dom
下面的代码就不给了,有封装接口
五、amis 使用过程中的坑
1.配置初始化接口api
1.1Service 功能型容器
amis 中部分组件,作为展示组件,自身没有使用接口初始化数据域的能力,例如:Table、Cards、List等,他们需要使用某些配置项,例如source,通过数据映射功能,在当前的 数据链 中获取数据,并进行数据展示。
而Service组件就是专门为该类组件而生,它的功能是::配置初始化接口,进行数据域的初始化,然后在Service内容器中配置子组件,这些子组件通过数据链的方法,获取Service所拉取到的数据
但是你会发现用api,source的时候组件无法渲染,需要用v-if 一开始做判断然后nextTick再次渲染才能展示,这个和组件封装的关系,这也是自己试了好久才发现的
1.2
一般写项目不要用里面自带的接口返回状态,一般和后端沟通好规范一套出来,重新去映射里面的状态返回
"api":{
"method":"post",
"url":"/customer",
"data":{
"pageNum":"${page}",
"pageSize":"${perPage}",
"type":"${type}",
"orderBy":"${orderBy}",
"orderDir":"${orderDir}",
"keywords":"${keywords}",
"startTime":"${startTime|JSON}",
"startTime2":"${startTime2}",
"startTime3":"${startTime3}"
},
"adaptor":"(payload, response)=>{return {...response,status: response.retcode===00?0:response.retcode}}"
},
2.日期时间选择器
默认的日期返回value 今天 竟然是"-1days,+0days",和给的官方文档不一样,反正有很多类似的坑在里面
3.json函数返回
这就不得不提有一个问题,返回的参数里面有adaptor函数,后端返回只能解析成字符串返回,前端做eval处理
4.数据映射
级联下拉的使用
{
"className":"searchLabel",
"name":"tree",
"type":"tree-select",
"label":"树懒加载",
"labelField":"org",
"valueField":"orgId",
"source":{
"method":"post",
"url":"/tree",
"data":{
"patientId":"0000"
},
"adaptor":"(payload, response)=>{return {...response,status: response.retcode===00?0:response.retcode}}"
},
"deferApi":{
"method":"post",
"url":"/tree",
"data":{
"patientId":"${orgId}"
},
"adaptor":"(payload, response)=>{return {...response,status: response.retcode===00?0:response.retcode}}"
}
}
里面的坑还有很多,有时候找原因需要凭自身经验去自己去发现,还是要多实践