讲解项目:教育培训(education-training) 模板项目
简介
本项目的一个教育培训服务APP。提供在线浏览机构信息、名师风采和课程预约订购等功能。
项目前端使用了 avm.js 多端开发技术 ,可同时编译为 Android & iOS App 以及微信小程序; 后端使用 APICloud 数据云3.0 云函数自定义接口。
技术要点
本项目在开发过程中,在“能拆就拆”的思想下,对项目进行细粒度的组件化拆解。 可以从中了解到组件拆分逻辑和一些操作技巧,对自定义组件进行巩固。
效果图
开发详情
TabBar 的组织
如果有留意到 APICloud 官方的 github 上前几个模板项目源码的同学们已经对 TabBar 的实现很熟悉了。
通过在项目根目录下定义 app.json 来创建一个 Tabbar 的主页结构。 在这个文件中,可以定义一些主页结构的具体参数。 包括每个 Tab 页面的路径、名称和底部导航图标资源信息。
如果需要适配小程序的原生 Tabbar 结构,这将是最佳的选择。 如果项目没有小程序的适配计划,也可以使用原有的 FrameGroup 来更加深度自定义相关切换行为和逻辑。
网络请求 req.js
一般项目的数据都是需要和服务器进行通讯获得。通过本地请求库拿到相关数据并进行处理和渲染到界面。 为了统一方便进行请求(会话、缓存和异常等),将在 req.js 中来处理相应的逻辑。 具体封装方式和实现可以根据个人团队喜好或者是接口通讯规则来开发,本项目中的逻辑仅供参考。
tab页-0 入口主页
主页结构非常简单,分为四个部分。
1、头部导航栏
2、头部轮播图
3、中部分类滑动栏
4、下部名师卡片滑动栏
5、底部 关于我们 富文本
自定义组件:a-header 头部导航栏
头部的导航栏很容易被忽视。这里我们自定义了一个 a-header 基础组件。具体实现是在 components/a-header.stml中。
在这个组件中, template 部分定义了具体的 UI 结构。
<template>
(isApp() &&
<safe-area class="a-header">
...
</safe-area>
)
</template>
其中 ( condition && ) 这种书写方式可以用来实现 v-if 的效果。 condition 就是一个布尔值,具体求值是来自一个函数。 因为小程序和 WEB 中不需要这个头部,只有 APP端才需要渲染。 可以在相关函数中定义具体的渲染依据,实现“条件渲染”的效果。
a-header 组件的职责就是为了显示头部导航栏,最重要的要素就是“标题”文本、左右侧的按钮和事件。
通过自定义参数 title 和 leftIcon 等传入相关配置。进而在模板中获值渲染。 还有一些场景参数,通过对 leftIcon 的不同类型和取值来实现是否需要返回按钮的实现。
在组件的方法中有两个点击事件:
methods: {
onClickLeft()
{
if (this.props.onClickLeft) {
this.props.onClickLeft();
} else {
api.closeWin();
}
}
,
onClickRight()
{
this.props.onClickRight && this.props.onClickRight();
}
}
这两个方法用于响应头部导航栏的左右点击。 左侧点击有一个内部判断:看看是否有传入自定义事件,有的话,执行传入的事件; 反之,执行默认逻辑:关闭窗口。
右侧点击的事件没有默认逻辑,只需要判断是否自定义右侧逻辑即可。
头部幻灯片
头部导航的图片信息来自网络请求数据:
function getHomeData() {
GET('i_alls/home').then(data => {
this.data.homeData = data;
api.setPrefs({
key: 'course_category', value: data.course_category
});
})
}
获取到数据以后使用一个 swiper 组件来展示这个轮播图:
<swiper autoplay circular class="main__swiper" style="margin: 10px 0;"
v-if="homeData.banners">
<swiper-item v-for="(item,index) in homeData.banners" class="main__swiper--item">
<img :src="item.cover" class="main__swiper--img"/>
</swiper-item>
</swiper>
使用可以滚动的 scroll-view 组件来渲染分类菜单和名师团队两处结构:
<scroll-view class="main__menu" scroll-x v-if="homeData.course_category"
:style="'height:'+(api.winWidth/4+20)+'px;'">
<view class="main__menu--item" v-for="item in homeData.course_category" @click="goto(item)"
:style="'width:'+api.winWidth/4+'px;'">
<img :src="item.image" class="main__menu--item-img"/>
<text class="main__menu--item-text">{
{
item.name }}</text>
</view>
</scroll-view>
<a-section title="名师团队" v-if="homeData.teacher_teams" class="main__teachers">
<scroll-view class=