前言
Ionic是目前較為流行的Hybird App解決方案,在Ionic開發過程中會遇到很多常見的開發問題,本文嘗試對這些問題給出解決方案。
一些常識與技巧
list
有延遲,可以在ion-content
處使用overflow-scroll="true"
嘗試- 在
<i>
上用ng-click
上是沒效果的 <label>
標簽內的事件會在整個label
內被觸發,點哪都觸發- 快捷修改背景色
style=""
- 能用
ng-if
就用ng-if
,ng-if
的效率比ng-show
和ng-hide
高 - 直接在
ion-list
中的ion-item
中並不能觸發ng-click
事件,可以在item中的元素上再套一層div - 可以用
ng-class="{'important': post.important}"
配合css 根據列表元素顯示不同的效果 - 獲取日期用
$filter
,var postdate = $filter('date')(date, 'yyyy-MM-dd HH:mm:ss');
- 列表中的元素不能寫成
id : 4
,應寫成id : "4"
,注意在創建id變量的時候也需要轉成string,如var id = InfoListService.getListLength()+1+"";
- 使用
$log
進行log輸出,為什么用$log
而不是console.log呢?可以看看這個 - 在安卓上的體驗比較差,動畫有延遲?可以試試ionic集成的crosswalk
controllers
和services
的文件名可能會重合,但是他們意義差不多,可以將controllers
中的文件名小寫,對應的services
中的文件名大寫進行區分,或者加后綴xxxControler
,xxxService
- 安裝cordova插件的時候用
ionic plugin add ...
的方式添加,這樣會在package.json
中添加這個插件的條目,如果有人clone了你的項目想在本地運行,可以用ionic state restore
它會根據cordovaPlugins
條目安裝對應的插件。如果直接用cordova plugin add
安裝則不會更新package.json
。 -
上傳base64編碼的時候如果提示413錯誤,是因為文件過大導致的,可以在nodejs中設置bodyparser的文件限制:
var bodyParser = require('body-parser');app.use(bodyParser.json({limit: '50mb'}));app.use(bodyParser.urlencoded({limit: '50mb', extended: true})); -
img 中 base64編碼的圖片無法顯示?在源碼中發現angular添加了unsafe標簽?需要在白名單中添加
data:image
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|content|file|assets-library):|data:image\//); -
有時候pm2運行有問題,重啟一下即可
- 在ios設備上運行
ionic run ios --device
問題列表
- 如何在某個界面中去掉導航欄?
- 如何在ionic中加載本地圖片?
- 如何在ionic中嵌入網頁代碼?
- 如何將template加載到某個tab或某個sidemenu項目下?
- 運行serve命令時ionic報錯?
- 用docker跑ionic的時候,不能把地址綁定到0.0.0.0怎么處理?
- 加載頁面的時候會看到雙括號一閃而過?
- 更新了數據,如何讓界面更新呢?
- 如何實現IonicView中card上面有一列分割線的效果?
- controller.js和service.js文件越來越大怎么辦?
- 如何尋找優秀的范例代碼?
- 如何顯示相對時間?
- 發布應用的時候如果遇到翻譯錯誤即MissingTranslation怎么辦?
- 如何在列表右下方添加時間等信息?
- 如何回到上一頁面?
- 如何關閉應用?
- 在安卓設備上如何讓title居中?
- 如何讓在sidemenu中的headerbar能夠顯示頭像等其他信息?
- ionic的subheader擋住了內容區域怎么辦?
- 對於需要添加數據的list,在添加數據后頁面不能及時刷新造成卡頓怎么辦?
- ionic如何處理回退按鈕?例如詢問用戶是否真的要退出應用
- ionic如何實現對每個請求都添加認證信息或認證失敗自動重新登錄?
- ionic如何實現搜索框內的全部清除按鈕?
如何在某個界面中去掉導航欄?
如果某個界面上不想要導航欄,可以簡單地在最頂端的標簽中添加hide-nav-bar="true"
如何在ionic中加載本地圖片?
對於css文件夾中的樣式文件中如果要調用本地的圖片的話,從該css文件所在的文件夾開始算,例如www/css/style.css
要加../
,否則在瀏覽器中可以正常顯示,在設備上不行,結構如下所示:
.login-page {
background:url(../img/signup_bg.png);
background-size: cover;
background-repeat: no-repeat;
}
|
但是對於在頁面中定義的圖片路徑,從www
路徑開始算,否則瀏覽器中可顯示,但設備上不行,img文件夾和index.html在一級,如:
<img src="img/commander.jpg">
|
如何在ionic中嵌入網頁代碼?
使用ng-bind-html
這個類,不過它會過濾原始html的標簽,我們可以引入$sce
模塊,用$sce.trustAsHtml()
方法信任我們獲取的網頁
如何將template加載到某個tab或某個sidemenu項目下?
<ion-nav-view name="menuContent">
可以指定name
,然后在子狀態中使用該name
,ionic就知道該把該狀態的template渲染到哪邊了。例如:
// signup page
.state('auth.signup', {
url: '/signup',
views: {
'auth-signup': {
templateUrl: 'templates/auth-signup.html',
controller: 'SignUpCtrl'
}
}
})
另有一個tabs中聲明該auth-signup:
<ion-tab title="Sign Up" icon-on="ion-ios-personadd"
icon-off="ion-ios-personadd-outline" href="#/auth/signup">
<ion-nav-view name="auth-signup"></ion-nav-view>
</ion-tab>
|
運行serve命令時ionic報錯?
ionic $ An uncaught exception occured and has been reported to Ionic
|
看看你是不還有一個終端在運行着serve呢?
用docker跑ionic的時候,不能把地址綁定到0.0.0.0怎么處理?
可以用ionic serve -all
的方法解決
加載頁面的時候會看到雙括號一閃而過?
angularjs
在使用雙括號的時候,第一個加載的頁面,也就是應用中的index.html
,其未被渲染好的模版可能會被用戶看到。用ng-bind
就不會遇到這個問題。造成這種現象的原因是,瀏覽器需要首先加載HTML頁面,渲染它,然后Angular
才有機會把它解釋成你期望看到的內容。不過好消息是,在大多數的模版中你依然可以使用雙括號.但是對於index.html頁面中的數據綁定操作,建議使用ng-bind
。
ng-bind
使用方式如下: <p ng-bind="greeting"></p>
更新了數據,如何讓界面更新呢?
可以用廣播,注意$broadcast 和 $emit的區別
如何實現IonicView中card上面有一列分割線的效果?
在css里定義
#info-up {
border-top: 4px solid #f06336;
}
|
controller.js和service.js文件越來越大怎么辦?
所有的控制器不必都放在controllers.js這一個文件中,可以新建controllers文件夾,
然后把每個controller都建一個.js文件,同理services和utils等都是.但注意要在index.html中head部分聲明.但是為了避免他們相互覆蓋,第一個加載的js中模塊中要加[…],其他都不需要。如:
// File : /js/directives/mainDirective.js
angular.module('app.directives',[]);
// File : /js/directives/myGreatDirective.js
angular.module('app.directives')
.directive('myGreatDirective', function(){
return {
//...
}
});
// File : /js/directives/myBetterDirective.js
angular.module('app.directives')
.directive('myBetterDirective', function(){
return {
//...
}
});
...
|
看angularjs-code-organization了解更多,嗯這篇文章寫的還不是best practice,因為你還得記着自己把[]寫到那個模塊里了,統一地寫在app.js中即可,在app.js最下面加上類似:
angular.module('fcws.controllers',['ionic', 'fcws.services']);
angular.module('fcws.services', []);
|
可以達到和上面一樣的效果,而且可以統一管理.
如何尋找優秀的范例代碼?
目前有些ionic 的app沒有進行代碼混淆,至少ionic官方的ionic view沒有進行代碼混淆,下載他們的app,文件名改成zip,解壓,所有的 www文件都在assets文件夾中,相當於開源了有木有,看看那些最優秀的practice。看中哪些優秀的app,下下來,如何在googleplay上下載?把googleplay應用的地址貼到apps.evozi中。
如何顯示相對時間?
如幾分鍾前,幾天前等,可以用momentjs,看這篇教程
發布應用的時候如果遇到翻譯錯誤即MissingTranslation怎么辦?
暫時的解決方法是,不進行翻譯校正, 在 /platforms/android/build.gradle 中的android {}節中加入:
lintOptions {
disable 'MissingTranslation'
disable 'ExtraTranslation'
}
|
如何在列表右下方添加時間等信息?
span
可以用來將時間之類的附加信息顯示到列表右邊,如下面會將創建時間顯示在name的右邊:
<ion-item class="item item-avatar-left " ng-repeat="message in messages">
<img src="../../img/commander.jpg">
<span class="item-note">{{message.create_at}}</span>
<h2 >{{message.name}}</h2>
<p > {{message.content}}</p>
</ion-item >
|
如何回到上一頁面?
用$ionicHistory
這個模塊,引入該模塊后使用goBack([backCount])
,backCount指定回去多少個頁面(-1代表回去一個頁面),默認為-1
如何關閉應用?
ionic.Platform.exitApp();
|
在安卓設備上如何讓title居中?
在headerbar中添加align-title="center"
,如:
<ion-header-bar class="bar-positive" align-title="center">
<h1 class="title">{{username}}</h1>
</ion-header-bar>
|
不過這個設置對ion-view無效,親測,如果要統一讓所有navbar上的title居中(包括上面的headerbar),可以在config里設置,如:
.config(function($stateProvider, $urlRouterProvider,$ionicConfigProvider) {
$ionicConfigProvider.navBar.alignTitle('center');
...
|
如果要讓某一個view title居中,可以用$ionicNavBarDelegate
,參考ionic官方文檔
如何讓在sidemenu中的headerbar能夠顯示頭像等其他信息?
解決方案是去掉headerbar,添加一個avatar到sidemenu content中,如:
<ion-side-menu side="left">
<ion-content class="bar-positive">
<ion-list>
<ion-item class="item item-avatar item-positive" href="#">
<img src="img/commander.jpg">
<h2 class=" light">
<i class="icon ion-ios-star"></i>{{title}}
</h2>
<a>{{username}}</a>
</ion-item>
|
ionic的subheader擋住了內容區域怎么辦?
解決方案是給<ion-content>
加類has-subheader
,同理也可以加has-header
。如下:
<ion-content class="has-header has-subheader">
|
對於需要添加數據的list,在添加數據后頁面不能及時刷新造成卡頓怎么辦?
可以使用$ionicScrollDelegate.resize();
在添加數據后手動進行重新刷新,記得添加依賴
ionic如何處理回退按鈕?例如詢問用戶是否真的要退出應用
可以在app.js的.run方法中增加對硬件回退按鈕的注冊處理,這里我在大部分頁面都想注冊該事件,除去有二級歷史頁面的我單獨判斷了下,注意增加依賴。
$ionicPlatform.registerBackButtonAction(function(e) {
var current_state_name = $state.current.name;
if(current_state_name !== 'sidemenu.post'
&& current_state_name !== 'sidemenu.contact_town' &&
current_state_name !== 'sidemenu.contact_people'){
$ionicPopup.confirm({
title: '退出應用',
template: '您確定要退出xxxx嗎?'
}).then(function (res) {
if (res) {
//ionic.Platform.exitApp();
navigator.app.exitApp();
} else {
console.log('You are not sure');
}
});
e.preventDefault();
return false;
}else{
navigator.app.backHistory();
}
},100);
|
ionic如何實現對每個請求都添加認證信息或認證失敗自動重新登錄?
在應用的注冊或者登錄部分,不記名token
響應了這個請求並且這個token
被存儲到本地存儲中。當你向后端請求一個服務時,你需要把這個token
放在頭部中。你可以在app.js
的.config
方法中使用AngularJS
的攔截器實現這個。每次請求都會被攔截並且會把認證頭部和值放到頭部中,同理如果服務器端響應401
或403
,跳轉到重新登錄頁面.
$httpProvider.interceptors.push(function ($q, $location, User, $rootScope) {
return {
'request': function (config) {
config.headers = config.headers || {};
if (User.getToken()) {
config.headers.Authorization = 'Bearer ' + User.getToken();
}
return config;
},
'responseError': function (response) {
if (response.status === 401 || response.status === 403) {
//如果之前登陸過
if (User.getToken()) {
$rootScope.$broadcast('unAuthenticed');
}
}
return $q.reject(response);
}
};
});
|
ionic如何實現搜索框內的全部清除按鈕?
在label中的input不能嵌入按鈕,因為ionic對於label中的tap事件會進行重定向到input上。解決方案是將label替換成span或div。如下面的搜索框,注意ng-model需要是一個對象才能置空,變量不行:
<span class="item-input-wrapper">
<i class="icon ion-ios-search placeholder-icon"></i>
<input type="search" placeholder="請輸入姓名前綴" ng-model="search.key">
<i class="icon ion-close-circled placeholder-icon" style="vertical-align: middle;"
on-tap="clearSearch()" ng-if="search.key.length"></i>
</span>
|