本項目中前端採用 APICloud AVM 多端開發技術進行企業app開發,要點包括 TabLayout 佈局、swiper 輪播圖、rich-text 富文本、scroll-view 滾動視圖、下拉刷新等。前端
項目後端則是使用的 APICloud 數據雲 3.0 自定義雲函數來構建的。node
使用APICloud 多端技術進行企業app開發,實現一套代碼多端運行,支持編譯成 Android & iOS App 以及微信小程序。項目源碼在 https://github.com/apicloudcom/company-display 倉庫的 widget 目錄下。git
使用步驟:github
- 使用 APICloud Studio 3 做爲開發工具。
- 下載本項目源碼。
- 在開發工具中新建項目,並將本源碼導入新建的項目中,注意更新,config.xml 中的 appid 爲你項目的 appid。
- 使用 AppLoader 進行真機同步調試預覽。
- 或者提交項目源碼,併爲當前項目雲編譯自定義 Loader 進行真機同步調試預覽。
- 雲編譯 生成 Android & iOS App以及微信小程序源碼包。
若是以前未接觸過 APICloud 開發,建議先了解一個簡單項目的初始化、預覽、調試和打包等操做,請參考APICloud 多端開發快速上手教程。web
網絡請求接口封裝
在 utils/model.js 中,爲每個網絡請求接口封裝了對應方法,如首頁獲取輪播圖接口 Model.getbannersList,這些方法最終會調用 Model.request 方法,在 Model.request 方法中對整個項目的請求進行統一管理,包括處理傳入參數、拼裝請求 url、設置請求頭等,最後調用 api.ajax 方法發起請求。ajax
使用示例:json
// 經過 import 引入 import {Model} from "../../utils/model.js" // 調用 Model 對象方法 Model.getbannersList({}, (res) => {});
TabBar 和導航欄的實現
首頁使用了 TabLayout 佈局來實現 TabBar 和導航欄,在 config.xml 裏面配置 content 字段,值爲 json 文件路徑,在 json 文件中配置 TabBar、導航欄和頁面信息。小程序
// config.xml <content src="config.json" />
config.json 文件內容以下,設置了 navigationBar 的背景色和標題文字顏色,設置了 tabBar 每項的 icon 和文字,以及每項對應的頁面。後端
{ "name": "root", "hideNavigationBar": false, "navigationBar": { "background": "#fff", "color": "#000", "hideBackButton": true }, "tabBar": { "scrollEnabled": false, "background": "#fff", "shadow": "#f1f1f1", "color": "#5e5e5e", "selectedColor": "#333333", "preload": 0, "frames": [{ "name": "page1", "url": "pages/index/index.stml", "title": "首頁" }, { "name": "page2", "url": "pages/case/case.stml", "title": "案例" }, { "name": "page3", "url": "pages/join/join.stml", "title": "加盟代理" }], "list": [{ "iconPath": "images/toolbar/home@no_selected.png", "selectedIconPath": "images/toolbar/home@selected.png", "text": "首頁" }, { "iconPath": "images/toolbar/case@no_selected.png", "selectedIconPath": "images/toolbar/case@selected.png", "text": "案例" }, { "iconPath": "images/toolbar/join@no_selected.png", "selectedIconPath": "images/toolbar/join@selected.png", "text": "加盟代理" }] } }
從上面的企業app開發效果圖中咱們能夠看到」加盟代理「頁面隱藏了導航欄,而其它頁面沒有隱藏。」加盟代理「頁面路徑爲 pages/join/join.stml,咱們參照微信小程序的語法,在同目錄下放置了 join.json 文件,在裏面配置 navigationStyle 字段爲 custom。微信小程序
{ "navigationBarTitleText": "加盟代理", "backgroundColor": "#FFFFFF", "navigationStyle":"custom" }
在首頁 index.stml 的 apiready 方法裏面則監聽了 tabBar 每項的點擊事件,在 App 端,咱們須要在點擊事件裏面動態設置頁面顯示、隱藏導航欄。
// index.stml api.addEventListener({ name:'tabitembtn' }, function(ret){ var hideNavigationBar = ret.index == 2; api.setTabLayoutAttr({ hideNavigationBar: hideNavigationBar, animated: false }); api.setTabBarAttr({ index: ret.index }); });
首頁輪播圖
首頁路徑爲 pages/index/index.stml,裏面輪播圖使用 swiper 組件實現,使用 v-for 指令循環 swiper-item,bannersList 爲定義的數組類型的屬性,在首頁的 apiready 方法裏面,咱們經過調用 getbannersList 方法發起網絡請求,獲取輪播圖片列表數據後賦值給 bannersList 屬性。這裏監聽了 swiper-item 的 click 事件,點擊後須要跳轉到詳情頁面。
<view style={'height:'+swiperHeight+'px;'} class="swiper-box"> <swiper class="swiper" autoplay indicator-dots indicator-color="rgba(255,255,255,0.2)" indicator-active-color="rgba(51,51,51,1)"> <swiper-item v-for="(item_,index_) in bannersList" data-index={index_} onclick="bindBanner"> <image src={item_.image} class="banner-image" mode="aspectFill"></image> </swiper-item> </swiper> </view>
輪播圖的寬度跟隨屏幕寬度變化,高度則經過計算屬性 swiperHeight 來動態計算獲得。
computed:{ swiperHeight(){ return api.winWidth*0.42; } }
rich-text 富文本的使用
APICloud這個企業app開發項目是信息展現類型,運營人員會在管理後臺直接編輯提交富文本信息,所以在項目中不少地方使用了 rich-text 來展現信息,好比在首頁中,產品展現和關於信息部分就是使用的 rich-text,若是沒爲 rich-text 設置高度,其高度就爲裏面內容的高度。
<view class="goods"> <rich-text v-if={{product_description}} nodes={product_description} /> </view> <view class="about"> <rich-text v-if={{about_us}} nodes={about_us} /> </view>
rich-text 用於展現 HTML String 片斷,在從服務器獲取到 HTML String 後,咱們調用 $util.fitRichText 方法處理了一下 HTML String,在 fitRichText 方法中爲 img 標籤加了最大寬度的限制,以防止圖片寬度過大致使顯示溢出。
// util.js fitRichText(richtext, width){ var str = `<img style="max-width:${width}px;"`; var result = richtext.replace(/\<img/gi, str); return result; }
下拉刷新、滾動到底部加載更多
在」案例「頁面(pages/case/case.stml),經過 scroll-view 實現了案例列表展現,同時實現了下拉刷新、滾動到底部加載更多功能。
<scroll-view class="main" scroll-y enable-back-to-top refresher-enabled refresher-triggered={refresherTriggered} onrefresherrefresh={this.onrefresherrefresh} onscrolltolower={this.onscrolltolower}> <view> <view class="item" data-id={item.id} onclick={this.openCaseInfo} v-for="(item, index) in caseList"> <image src={item.cover_img} class="item-img"></image> <text class="item-title">{{item.title}}</text> </view> </view> <view class="footer"> <text class="loadDesc">{loadStateDesc}</text> </view> </scroll-view>
下拉刷新使用了 scroll-view 默認的下拉刷新樣式,使用 refresher-enabled 字段來開啓下拉刷新,爲 refresher-triggered 字段綁定了 refresherTriggered 屬性來控制下拉刷新狀態,須要注意的是,在刷新的事件回調方法裏面,咱們須要主動設置 refresherTriggered 的值爲 true,在數據加載完成後再設置爲 false,這樣綁定的值有變化,刷新狀態才能通知到原生裏面。
onrefresherrefresh(){ this.data.refresherTriggered = true; this.loadData(false); }
滾動到底部監聽了 scroll-view 的 scrolltolower 事件,在滾動到底部後自動加載更多數據,加載更多和下拉刷新都是調用 loadData 方法請求數據,經過 loadMore 參數來進行區分,作分頁請求處理。
loadData(loadMore) { if (this.data.loading) { return; } this.data.loading = true; var that = this; var limit = 10; var skip = loadMore?that.data.skip+1:1; let params = { data:{ values:{ status: 1, skip: skip, limit: limit } } } Model.getCasesList(params, (res) => { if (res && res.status == 0) { let items = res.data.items; that.data.haveMoreData = items.length == limit; if (loadMore) { that.data.caseList = that.data.caseList.concat(items); } else { that.data.caseList = items; } that.data.skip = skip; } else { that.data.haveMoreData = false; } that.data.loading = false; that.data.refresherTriggered = false; }); }
scroll-view 滾動到指定元素
在」加盟代理「頁面(pages/join/join.stml),最外層是一個 scroll-view,裏面有分類列表、分類內容兩項,點擊分類列表裏面某項後會自動滾動到對應的分類內容處,讓分類內容可見。
<scroll-view class="main" scroll-y scroll-into-view={viewId} scroll-with-animation enable-back-to-top refresher-enabled refresher-threshold="90" refresher-triggered={refresherTriggered} onrefresherrefresh={this.onrefresherrefresh}> <!-- 分類列表 --> <view class="cate"> <view class="cate-item" v-for="(item,index) in list" data-id={item.id} onclick="onitemclick"> <image src={item.image} class="cate-img"></image> <text class="cate-word">{item.title}</text> </view> </view> <!-- 分類內容 --> <view class="content"> <view class="content-item" v-for="(item,index) in list" id={'content'+item.id}> <text class="content-title">{item.title}</text> <rich-text nodes={item.content} /> </view> </view> </scroll-view>
滾動到指定視圖經過 scroll-view 的 scroll-into-view 屬性實現,這裏綁定了 viewId 屬性,在分類列表項的點擊事件 onitemclick 裏面,改變 viewId 屬性的值,這個值是分類內容裏面某項的 id,這樣就實現了滾動到指定視圖。
onitemclick(e) { var id = e.currentTarget.dataset.id; this.data.viewId = 'content' + id; this.data.viewId = null; }
平臺差別化處理
在多端開發中,不免會遇到不一樣平臺差別化的地方,須要在運行期間作判斷處理,爲此在 utils/util.js 中封裝了 isApp 方法,裏面經過 api.platform 屬性判斷當前運行環境。
// util.js isApp(){ if (api.platform && api.platform == 'app') { return true; } return false; }
例如在 pages/web/web.stml 中,咱們使用 v-if、v-else 指令,經過區分平臺使用不一樣的組件來加載 web 連接。
<view class="main"> <frame v-if="$util.isApp()" class="web-view" name="web" url={api.pageParam.link}></frame> <web-view v-else class="web-view" src={api.pageParam.link}></web-view> </view>
本文只是簡單介紹了用APICloud AVM多端工具進行企業app開發須要注意的問題,想要熟練掌握開發技巧,仍是須要開發者本身經過源碼不斷實踐哦!