簡單地說快應用是國內的十大主流手機廠商好比小米、華爲、ov 等聯合推出的一種新型應用。無需安裝,秒開,體驗媲美原生。還提供了像原生應用同樣的入口:應用商店,搜索頁等。javascript
接下來會教你們如何搭建、啓動、預覽和調試快應用項目。和官方文檔相似,這裏我增長了一些我在這過程當中遇到的坑及解決方法。css
官方說需安裝 6.0 以上版本的 NodeJS,推薦 v6.11.3,但我本機 NodeJS 是 v9.3.0,暫時沒發現異常就沒切到 6.0。html
hap-toolkit 是快應用的開發者工具,幫助開發者經過命令行工具輔助開發工做的完成,主要包括建立模板工程,升級工程,編譯,調試等功能。相似 vue-cli。前端
npm install -g hap-toolkit
複製代碼
安裝以後查看下版本號看是否安裝成功。vue
hap -V
複製代碼
運行以下命令會在當前目錄下建立 <ProjectName>
目錄做爲項目的根目錄。java
hap init <ProjectName>
複製代碼
這個項目已經包含了項目配置與示例頁面的初始代碼,項目根目錄主要結構以下。node
├── sign rpk 包簽名模塊
│ └── debug 調試環境
│ ├── certificate.pem 證書文件
│ └── private.pem 私鑰文件
├── src
│ ├── Common 公用的資源和組件文件
│ │ └── logo.png 應用圖標
│ ├── Demo 頁面目錄
│ | └── index.ux 頁面文件,可自定義頁面名稱
│ ├── app.ux APP 文件,可引入公共腳本,暴露公共數據和方法等
│ └── manifest.json 項目配置文件,配置應用圖標、頁面路由等
└── package.json 定義項目須要的各類模塊及配置信息
複製代碼
npm install
複製代碼
編譯webpack
npm run build
複製代碼
編譯生成的 dist
目錄裏纔是最終產物:rpk
文件。ios
這一步可能會遇到報錯(我就遇到了)。git
Cannot find module '.../node_modules/hap-tools/webpack.config.js'
複製代碼
主要是由於建立項目後就有一個 node_module
文件夾了,裏面有一個 hap-tools
包。若是 npm install
安裝依賴,高版本的 npm
可能會把 node_module
原有的包清空再安裝依賴,這時只要再手動安裝下 hap-tools
就好了
npm install hap-tools
複製代碼
若是要監聽源碼變化自動編譯,能夠運行 watch 命令。
npm run watch
複製代碼
到這一步一個 hello world 的快應用就打包好了,下面須要在手機上把它跑起來。
首先須要安裝手機調試器。
只安裝這個快應用調試器會發現上面的按鈕都是灰色不可點擊的,這時還須要安裝平臺預覽版調試器,總之快應用文檔上的手機調試器都要安裝才能調試。
安裝好調試器後就把快應用安裝包安裝到手機上就能夠了。
須要啓動一個本地 HTTP 服務器。
npm run server
複製代碼
若是命令行中的二維碼掃了沒反應,能夠把那個地址在瀏覽器中打開在掃碼試試(我就是這樣),由於命令行中的二維碼可能繪製的有問題。
把 rpk
文件傳到手機上安裝便可。
快應用調試器右上角能夠設置服務器地址,運行如下命令每次改了代碼就能夠點擊在線更新就能夠更新了,不用每次都掃碼或本地安裝。
npm run server
npm run watch
複製代碼
能夠手機上預覽,也可使用 chrome devtools 調試界面,還能夠查看調試日誌。手機上預覽上面說了,其餘調試按官方步驟來就行了。
可能的坑:在用chrome devtools調試的時候可能打不開調試界面,或者調試界面空白。這時需檢查:
以一個列表頁和詳情頁爲例說明快應用的代碼,數據來源迅雷影評。
在 manifest.json
中配置路由後就能夠寫代碼了,生成的模板有例子。注意不能配置動態路由。
注意用到的系統接口要先在 manifest.json
的 feature
中聲明。看 manifest 的文檔瞭解具體的配置項。
{
"package": "com.xunlei.movie",
"name": "迅雷影評",
"versionName": "1.0.0",
"versionCode": "1",
"minPlatformVersion": "101",
"icon": "/Common/logo.png",
"features": [
{ "name": "system.prompt" },
{ "name": "system.router" },
{ "name": "system.shortcut" },
{ "name": "system.fetch" },
{ "name": "system.webview" }
],
"permissions": [
{ "origin": "*" }
],
"config": {
"logLevel": "debug",
"designWidth": 640
},
"router": {
"entry": "List",
"pages": {
"List": {
"component": "index"
},
"Detail": {
"component": "index"
},
"About": {
"component": "index"
}
}
}
}
複製代碼
列表使用了快應用的list組件,這個組件是Native組件,對長列表滾動性能更好,list組件還有一個onscrollbottom事件,方便下拉加載。
image組件和前端的img標籤相似,可是alt屬性不一樣,alt是用來顯示佔位圖的,只能是本地圖片,在圖片沒加載出來前顯示。
list-item組件中的type是必填的,要實現DOM片斷的複用,要求相同type屬性的DOM結構徹底相同;因此設置相同type屬性的list-item是優化列表滾動性能的關鍵。
<template>
<list class="list-main" onscrollbottom="loadData">
<list-item class="list-item" type="review" for="{{item in list}}">
<image class ="art-pic" src="{{item.img}" alt="../Common/assets/img/default.png">
</image>
<text class="art-title">{{item.title}}</text>
</list-item>
<!-- 加載更多,type屬性自定義命名爲loadMore -->
<list-item type="loadMore" class="load-more" show="{{hasMore}}">
<progress type="circular" class="round"></progress>
<text>加載更多</text>
</list-item>
</list>
</template>
複製代碼
快應用的網絡請求是用fetch方法,是callback的形式,不方便調用,官方給了一個封裝成promise的例子,能夠用async/await的方式調用。
將封裝好的fetch方法在app.ux中導出就能夠全局使用了,因爲我使用的接口都返回json,因此直接就在這一層解析了。實際開發時要注意JSON.parse的報錯處理。
// app.ux
const natives = {
/** * 網絡請求 * @param options * @return {Promise} */
async fetch (options) {
const p1 = new Promise((resolve, reject) => {
options.success = function (data, code) {
data = JSON.parse(data.data)
resolve({ data, code })
}
options.fail = function (data, code) {
reject({ data, code })
}
nativeFetch.fetch(options)
})
return p1
}
}
// 注入到全局
const hookTo = global.__proto__ || global
hookTo.natives = natives
export default {
natives
}
複製代碼
路由跳轉
<template>
<list>
<list-item onclick="{{goDetail(item.id)}}" for="item in list"></list-item>
</list>
</template>
<script> import router from '@system.router' export default { goDetail (id) { router.push({ uri: '/Detail', params: { id } }) } } </script>
複製代碼
詳情頁只是加載了一個 webview, 用列表頁傳過來的 id 去請求影評詳情,影評正文是存在 cdn 上的一個地址。使用 web
組件前需在 manifest.json
中聲明使用 webview 接口。
<!-- Detail/indev.ux -->
<template>
<!-- template裏只能有一個根節點 -->
<div>
<web src="{{review.body_url}}" id="web"></web>
</div>
</template>
<script> import api from '../Common/api/index.js' export default { data: { id: '', // 列表頁傳過來的id review: {} }, onMenuPress() { this.$app.showMenu() }, onInit () { this.getReview() }, async getReview () { try { let data = await api.getReview(this.id) this.review = data.cinecism_info || {} this.$page.setTitleBar({ text: this.review.title }) } catch (error) { console.log(error) } } } </script>
複製代碼
快應用與前端開發的最大的區別就是 html 和 css 部分,由於快應用是用原生的方式實現的,但沒有實現html的全部標籤,並且與 html 相同的標籤在用法上也有一些差異。
快應用中不少 html 都不能用,好比沒有 p,h1~h2 等,由於它只是模擬了部分 html 標籤,最終會轉化成原生組件。
並且快應用中的組件嵌套子組件是有限制的,不是全部的組件都能嵌套子組件,若是嵌套不正確編譯的時候會報錯。好比下面就是不正確的寫法:
<!--錯誤-->
<a href="">
<image src="http://pic.com/1.jpg"></image>
</a>
複製代碼
只能使用 a、span、text、label 放置文本內容
圖片組件是 image 不是 img,用法與 img 相似,只是 alt 的含義不一樣,在快應用中 alt 是指圖片沒加載出來前的佔位圖,只能是本地地址。
<image src="http://pic.com/1.jpg" alt="1.jpg"></image>
複製代碼
表單組件、video 組件等與前端一致,還有一些快應用特有的組件,好比星級評分組件、進度條組件、list 組件等。
與傳統 web 頁面不一樣,px 是相對於項目配置基準寬度的單位,已經適配了移動端屏幕,其原理相似於 rem。基準寬度能夠在 mainifest.json 中配置。
基本語法都能用,ES6 也能夠用,項目中已經安裝了 babel 依賴。一些瀏覽器特有的 API 可能不一樣。好比數據存儲用的是快應用的接口 storage。
因爲咱們團隊主要是用 Vue 技術棧開發,因此比較下快應用在語法上和 Vue 的共同點和差別之處。快應用看起來和 Vue 相似,其實仍是有很大的差異。
<!--左邊是 vue 語法 右邊是快應用語法-->
v-for => for
v-show => show
v-if => if
template => block
slot => slot
複製代碼
manifest.json
配置的,在實例中的用法與 vue-router 一致// vue
import child from './childComponent'
// 快應用
<import name="child" src="./childComponent"></import>
複製代碼
$on
$off
$emit
,監聽原生組件的事件寫法不一樣<!--vue-->
<div v-on:click="handleClick"><div>
<div @click="handleClick"><div>
<!--快應用-->
<div onclick="{{handleClick()}}"><div>
複製代碼
寫 demo 的時候仍是遇到了很多坑,主要是 html 和 css 部分。像咱們公司前端和重構是分開的,重構只負責寫 html + css,前端負責寫邏輯調接口等雜七雜八的事情,快應用和小程序這種形式對重構來講很麻煩,不能寫一份代碼處處用了。
還有就是詳情頁顯示影評正文的時候遇到了一個問題。咱們影評的正文是存在 cdn 上的一堆 html 標籤,無樣式,可能有一些和快應用不兼容的標籤,因此用 webview 的方式加載頁面。可是不知道怎麼向 webview 中注入 css ,因此頁面是亂的。
總的來講,快應用這種形態對用戶來講仍是很好的,在下載 APP 前就能夠體驗到應用的一些功能。快應用的快在於它進行了不少原生的優化,也在於它小,小到用戶感受不到,這也註定它不能作的很複雜。
做者:珈藍
校對:前端小透明