http://mclspace.com/2016/01/16/ionic-problems-and-solutions/

Ionic 常見問題及解決方案

Jan 16, 2016

前言

Ionic是目前較爲流行的Hybird App解決方案,在Ionic開發過程中會遇到很多常見的開發問題,本文嘗試對這些問題給出解決方案。


一些常識與技巧

  • list 有延遲,可以在ion-content處使用 overflow-scroll="true"嘗試
  • <i>上用ng-click上是沒效果的
  • <label>標籤內的事件會在整個label內被觸發,點哪都觸發
  • 快捷修改背景色style="background-color: #212326;"
  • 能用ng-if就用ng-if,ng-if的效率比ng-showng-hide
  • 直接在ion-list中的ion-item中並不能觸發ng-click事件,可以在item中的元素上再套一層div
  • 可以用ng-class="{'important': post.important}"配合css 根據列表元素顯示不同的效果
  • 獲取日期用$filtervar 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
  • controllersservices 的文件名可能會重合,但是他們意義差不多,可以將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

問題列表

  1. 如何在某個界面中去掉導航欄?
  2. 如何在ionic中加載本地圖片?
  3. 如何在ionic中嵌入網頁代碼?
  4. 如何將template加載到某個tab或某個sidemenu項目下?
  5. 運行serve命令時ionic報錯?
  6. 用docker跑ionic的時候,不能把地址綁定到0.0.0.0怎麼處理?
  7. 加載頁面的時候會看到雙括號一閃而過?
  8. 更新了數據,如何讓界面更新呢?
  9. 如何實現IonicView中card上面有一列分割線的效果?
  10. controller.js和service.js文件越來越大怎麼辦?
  11. 如何尋找優秀的範例代碼?
  12. 如何顯示相對時間?
  13. 發佈應用的時候如果遇到翻譯錯誤即MissingTranslation怎麼辦?
  14. 如何在列表右下方添加時間等信息?
  15. 如何回到上一頁面?
  16. 如何關閉應用?
  17. 在安卓設備上如何讓title居中?
  18. 如何讓在sidemenu中的headerbar能夠顯示頭像等其他信息?
  19. ionic的subheader擋住了內容區域怎麼辦?
  20. 對於需要添加數據的list,在添加數據後頁面不能及時刷新造成卡頓怎麼辦?
  21. ionic如何處理回退按鈕?例如詢問用戶是否真的要退出應用
  22. ionic如何實現對每個請求都添加認證信息或認證失敗自動重新登錄?
  23. 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的攔截器實現這個。每次請求都會被攔截並且會把認證頭部和值放到頭部中,同理如果服務器端響應401403,跳轉到重新登錄頁面.

$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>
發佈了15 篇原創文章 · 獲贊 25 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章