作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
朱利安·雷诺的头像

Julien Renaux

Scrum Master Julien (MCS)是一名前端移动开发人员,曾在eBay等初创公司和企业工作过, 甚至是法国航天局.

Previously At

eBay
Share

Introduction

Ionic 到现在已经两年了. 它是一组很棒的工具,用于开发基于web的混合应用程序 AngularJS. Ionic目前非常流行, 已经构建了超过一百万个应用程序,并且拥有成千上万个不断增长的社区 developers.

自从Ionic第一次发布以来, time has passed, 网络技术和最佳实践在许多方面都有发展. 因此,在开始一个新项目时,很难确定该走哪条路. 在这些情况下, 开发人员可能会犯错误,从而潜在地影响应用程序的质量或团队的生产力.

通过阅读下面的常见错误, 你将掌握避免基本问题的关键,并使用Ionic创建高性能和可扩展的应用程序.

常见错误1:忘记启用原生滚动

Native Scrolling 允许Ionic监听受支持的webview上的滚动事件. It makes Pull to Refresh, List Reordering and Infinite Scroll 可能没有JavaScript滚动, 这是在浏览器缺乏适当的滚动事件的时候创建的.

自Ionic 1以来,Android默认启用原生滚动.2 (December 2015). 这是一个巨大的性能和用户体验的改进, 因为它确保了异步事件的平滑滚动.

Unfortunately, 由于iOS平台上缺少适当的事件,所以原生滚动还未在该平台上启用.

如果您使用的是早于1的版本.2、你可以启用原生滚动为Android使用 ionicConfigProvider美元:

//在Android上启用原生滚动
ionicConfigProvider美元.platform.android.scrolling.jsScrolling(假);

您还可以在任何页面上启用或禁用本机滚动 overflow-scroll directive on any ion-content:



不幸的是,请注意 collection-repeat,它允许您的应用程序显示巨大的项目列表,本机滚动无法覆盖.

常见错误#2:不使用Ionic CLI安装平台和插件

Ionic CLICordova CLI. 平台和插件持久性是Ionic CLI添加的一个重要特性.

Cordova CLI的问题是,您安装的平台和插件只安装在您的机器上. 当你在一个团队中工作时,为了避免漏洞,你需要共享相同的环境、平台和插件. 使用Cordova CLI,在开发人员的机器之间保持项目同步更加困难. 是的,您可以提交平台和插件文件夹,但不建议这样做.

使用Ionic CLI安装平台时 离子平台添加ios and plugins Ionic插件添加摄像头, the package.json 适当地编辑文件.

平台和插件都存储在 cordovaPlatforms and cordovaPlugins properties:

“cordovaPlugins”:(
    “cordova-plugin-whitelist@1.0.0",
    “cordova-plugin-inappbrowser@1.0.1",
    “cordova-plugin-splashscreen@2.1.0"
  ],
  “cordovaPlatforms”:(
    "android",
    "ios"
  ]

现在,其他开发人员在提取新代码时可以很容易地同步,只需运行即可 离子态恢复 必要时(添加、删除或版本更新).

常见错误#3:思维表现是开箱即用的

Ionic是基于AngularJS的,它在设备上的性能经常受到质疑. 我想在这一点上向你保证:有一点AngularJS的背景, 你可以用Ionic创建世界级的应用程序.

最好的例子是 Sworkit app 拥有900多万用户群,700多万次下载,平均4次.谷歌Play 5星.

如果你想充分利用AngularJS, 这里有一些你在开始你的项目之前应该了解的事情.

$watch

在AngularJS中,观察者习惯于监听作用域的变化. 基本上有四种类型 $watch: $watch (normal), $watch (deep), $watchCollection and $watchGroup.

每一个都是不同的, 选择正确的一个可以在性能方面产生巨大的差异.

$watch (normal)

Using the normal $watch 将只检查现有的对象属性或数组项. Shallow changes, 比如添加一个对象属性或将一个新项推入数组, 不会被照顾吗.

$scope.$watch('watchExpression', function(newVal, oldVal){
    if(newVal){
        // watchExpression已经改变.
    }
});

$watch (deep)

The deep $watch 处理浅层更改和深层更改,如嵌套对象属性. With this $watch 你一定不会错过任何修改. 然而,使用deep $watch 对性能有影响. 我建议谨慎使用.

$scope.$watch('watchExpression', function(newVal, oldVal){
    if(newVal){
        // watchExpression已经改变.
    }
}, true);

$watchCollection

$watchCollection 可以考虑在正常之间吗 $watch and the deep $watch. 它还可以比较对象引用, 但它的优点是还可以通过添加object属性或将新项推入Array来观察对象的属性.

$scope.$watchCollection('watchExpression', function(newVal, oldVal){
    if(newVal){
        // watchExpression已经改变.
    }
});

$watchGroup

在AngularJS 1中引入.3, $watchGroup 允许同时观看多个表情.

While $watchGroup 可能无法提高应用程序的性能 $watch,它的优点是在观察多个作用域表达式时更加综合.

$scope.$watchGroup([
    “watchExpression”,
    “watchExpression2”,
    “watchExpression3”
, function(newVals, oldVals) {
    if (newVals[0]) {
        // watchExpression已经改变.
    }
    if (newVals[1]) {
        // watchExpression2已经改变.
    }
    if (newVals[2]) {
        // watchExpression3已经改变.
    }
});

Track By

The track by 是用来避免无用的DOM操作时使用 ng-repeat. 实际上,如果摘要循环发现集合中至少有一个元素发生了更改, ng-repeat 会重新渲染所有的元素吗. DOM操作总是对应用程序性能有影响,所以越少越好.

以避免重新呈现整个集合,而只更新需要更新的元素, use track by 具有唯一标识符.


Just avoid using track by on collection-repeat.

One-Time Binding

一次性绑定,或 :: 在Angular 1中引入的.3,它对您的应用程序性能有实际影响.

基本上,使用一次性绑定 :: 上的表达式将把它从 $watchers 填充时的列表. 这意味着即使数据发生变化,表达式也无法更新.

{{::user.firstName}}

我们的建议是检查应用程序的所有视图,并考虑哪些可以更新,哪些不能更新, 使用一次性绑定 :: accordingly. 这将极大地缓解消化周期.

请注意,不幸的是,一次性绑定不能在 collection-repeat,因为屏幕上显示的项目列表在滚动时发生了变化.

如果你想了解更多关于AngularJS和Ionic性能的提示和技巧, 我建议大家阅读 终极AngularJS和Ionic性能备忘单 .

常见错误#4:混淆 View Cache Logic

默认情况下,单页应用程序不缓存页面. 你可能在使用AngularJS应用程序时经历过这种情况, 当您在页面之间来回导航时,滚动或用户输入没有保存在哪里.

使用Ionic,默认情况下缓存10个页面,这可以在全局或每个平台上更改.

// Globally
ionicConfigProvider美元.views.maxCache(5);

// Per platforms
ionicConfigProvider美元.platform.android.views.maxCache(5);
ionicConfigProvider美元.platform.ios.views.maxCache(5);

这是一个很棒的功能, 但是有时候初学者很难理解如何处理缓存页面.

问题是,当用户返回到缓存页面时, 控制器没有重新实例化, 与AngularJS应用程序有什么不同, 一切就像你从未离开过那一页.

在这些情况下,您应该如何更新页面上的数据?

控制器生命周期事件介绍

与AngularJS相比,Ionic提供了许多生命周期事件:

$scope.$on('$ionicView.加载的函数(){});
$scope.$on('$ionicView.卸载,函数(){});
$scope.$on('$ionicView.输入的函数(){});
$scope.$on('$ionicView.离开的,函数(){});
$scope.$on('$ionicView.beforeEnter’,function () {});
$scope.$on('$ionicView.beforeLeave’,function () {});
$scope.$on('$ionicView.afterEnter’,function () {});
$scope.$on('$ionicView.afterLeave’,function () {});

如果您希望控制视图缓存,这些事件是必需的.

$ionicView.loaded 例如,Event在视图第一次加载时触发. 在缓存此视图时,将不再触发此事件, 即使用户再次回到游戏中. 这通常是您用来初始化变量的事件,方法与 viewContentLoaded美元 在AngularJS中.

如果希望每次进入视图(无论是否缓存)时都获取数据,可以使用 $ionicView.enter event.

通过在正确的时间使用正确的事件,可以提高应用程序的可用性.

关于性能,使用缓存视图只会影响DOM的大小. 当页面被缓存时, 它的所有监视器都断开了连接,因此页面只是页面上等待再次使用的一些DOM元素.

DOM的大小关系到用户体验的好坏, 但是缓存最多10个页面似乎工作得很好, 这取决于你在页面中加载的内容).

常见错误5:不了解Android的人行横道

每个Android版本运行不同的WebView(运行应用程序的浏览器). 不同设备的性能是不同的,在旧的Android设备上可能会非常糟糕. 为了在所有Android设备上获得同样的流畅性和响应性体验,你可以安装 Crosswalk. 它基本上将最新的Chromium浏览器嵌入到您的应用程序中, 并且每个APK增加了大约20Mb, both ARM and X86.

Crosswalk可以简单地使用Ionic CLI或Cordova CLI安装:

添加cordova-plugin- croswalk -webview插件

常见错误#6:试图在浏览器内运行Cordova插件

大多数使用Ionic的开发者都希望他们的应用能在iOS和Android上运行. 添加平台之后 Ionic平台添加ios android and some plugins Ionic插件添加cordova-plugin-device-orientation一个低级的错误是认为你可以在浏览器中测试它们. 当然可以,但前提是要安装合适的浏览器平台. 请记住,它并不适用于所有插件.

Cordova的插件旨在通过JavaScript与本机设备API进行交互. 因此,联系人插件或设备方向插件只能在设备上工作.

但是,您可以轻松地在设备上测试代码并通过计算机远程调试它.

Android远程调试

插入您的设备,并通过运行确保计算机正确检测到它 adb devices (需要Android SDK).

通过运行构建应用程序并将其安装到设备上 ionic run android. 一旦你的应用在设备上启动,通过Chrome开发工具打开控制台(在你的电脑上)。 chrome: / /检查/ #设备,并检查您的设备.

图片:Chrome开发工具

iOS上的远程调试

插入您的设备,并确保您的计算机正确检测到它. 通过运行构建应用程序并将其安装到设备上 Ionic run ios -device.

一旦应用程序在设备上启动,通过点击打开Safari开发工具(在您的计算机上) Develop > Your iPhone > Your app:

图片:Safari开发工具

在浏览器中运行Cordova插件

在浏览器中运行Cordova插件是一项您应该了解的高级功能. Since Ionic 1.2, 正式支持浏览器, 所以它开启了跨平台应用的时代,超越了iOS和Android平台.

借助Cordova浏览器平台, Electron 并且只能使用Web技术(JavaScript), HTML, 和CSS),我们现在可以为浏览器和桌面(Windows, Linux, and OSX).

入门工具包可在 Github.

Cordova浏览器平台

使用Browser平台,您可以为浏览器创建Cordova应用程序. 这意味着你也可以在浏览器上使用Cordova的插件.

它可以像安装iOS或Android平台一样安装:

Cordova平台添加浏览器

你的应用程序需要在使用之前进行编译,就像在iOS或Android上一样:

Cordova运行浏览器

该命令将编译应用程序并打开默认浏览器.

跨平台插件

A lot of plugins such as Network, 相机和Facebook支持iOS, Android, 以及浏览器平台——都使用相同的API.

为了说明这一点,有一种方法可以知道你的设备在每个平台上是在线还是离线的(iOS, Android, 浏览器和桌面)使用 ngCordova API:

//监听在线事件
$rootScope.$on('$cordovaNetwork:online', (event, connectionType) => {
    this.isOnline = true;
});

//监听离线事件
$rootScope.$on('$cordovaNetwork:offline', (event, connectionType) => {
    this.isOnline = false;
});

With this in mind, 现在,您可以想象使用一个代码库创建可以在任何地方运行的产品.

常见错误#7:为大规模应用程序使用Starter Kit架构

When using the ionic start myapp 命令,创建一个启动项目,文件夹结构如下:

www/
    js/
        app.js
        controllers/
            aaa.js
            bbb.js
            ccc.js
        services/
            xxx.js
            yyy.js
            zzz.js
        templates/
            aaa.html
            bbb.html
            ccc.html

这被称为按类型文件夹结构, where JavaScript, CSS, 和HTML文件按类型分组. 对于初学者来说,这似乎很容易,但这种架构很快就会失控. 它根本无法扩展.

以下是不使用按类型文件夹结构的一些原因:

  • 文件夹中的文件数量可能会变得非常庞大
  • 找到您需要为特定功能修改的所有文件可能很棘手
  • 开发一个特性会导致打开许多文件夹
  • 不能很好地扩展,应用越大,开发它就越困难

我建议使用按功能分类的文件夹结构, where JavaScript, CSS, 和HTML文件按特性或AngularJS模块分组:

myNewFeature/
        index.js (AngularJS模块)
        config.js
        service.js
        controller.js
        index.html
        style.scss

使用按功能文件夹结构的原因:

  • 文件夹中的文件数量有限
  • 找到所有你需要为特定功能修改的文件很容易——它们都在同一个文件夹中
  • 你可以独立完成一个功能
  • 知道模块代表什么很容易——文件夹名称就足够了
  • 轻松创建新功能,只需复制/粘贴现有功能即可
  • Scales well, 您可以添加尽可能多的新功能,而不会给团队的工作带来困难

请注意,这种架构与现在Angular2/Ionic2应用中默认的按组件分类的文件夹结构很接近.

Ionic Flipbook动画

常见错误8:将事件绑定到 onscroll和忘记 requestAnimationFrame

这个单一的陷阱通常是初学者的错误, 但它对性能的影响可能是最严重的. Consider this:


// …

$scope.getScrollPosition = function () {
  //繁重的处理,比如操作DOM
  //或任何触发$digest()
  //每~80ms调用一次
  //会影响用户体验
}

尽管Ionic为这些动作提供了节流功能,但它仍然很慢. Basically, 任何触发消化循环的东西都应该被推迟,而不是与重绘制一起触发, 滚动的效果是什么.

开发人员一直试图通过绑定滚动事件来实现许多目标, 尤其是动画, 也可以用不同的方法来实现吗. Behold requestAnimationFrame.

var myElement =文档.getElementById(“内容”);
var elemOffsetFromParent = myElement.offsetTop;
函数oncaptureframe () {
  if (window.scrollY >= elemOffsetFromParent) {
    customTweenFunction (myElement、期权);
  }
  window.requestAnimationFrame (onCapturedFrame);
}
onCapturedFrame ();

上面的代码是一个非常简单的例子,检查用户是否滚动过元素的顶部. 如果您打算使用这个示例,请记住为跨浏览器兼容性添加特定于供应商的替代方案. 它基本上会以最佳速度运行, 取决于浏览器, 60 FPS或屏幕刷新率. 但它是经过优化的,高性能动画框架利用了这种简单的方法.

你可能还想看看 element.getBoundingClientRect (),它提供有关HTML节点的大小和位置的信息.

常见错误#9:手工制作Ionic应用原型

Ionic有一个特殊的设计,几乎是一种视觉语言. 特别是对于原型和早期产品, 利用可用的组件和样式可以节省大量的时间和费用. 他们实际上是相当小,有一个很好的审美.

呈现具有基本功能的线框图和模型已经成为一种行业标准. 在移动设备上看图片和看带有动态组件的实际应用完全是两码事. 许多设计师,以及用户体验开发人员,使用像 Axure or Balsamiq,它允许用最少的功能快速制作线框.

现在,Ionic的创建者发布了一个专门为Ionic开发者制作的类似工具. It is called Ionic Creator. 它有一个拖放web界面,并支持几乎所有核心Ionic提供. 它的伟大之处在于它允许将原型导出为多种格式, 使用标准的Ionic代码, 甚至构建应用程序和 share it. 该工具是专有的,但许多选项是免费使用的.

图片:Ionic Creator

Conclusion

Ionic以一种无人能想象的方式彻底改变了混合应用行业. 然而,随着时间的推移,最佳实践和工具缺乏发展. 因此,开发人员可能犯的潜在错误数量增加了.

专业的Ionic开发人员有一个明确的方法,可以同时向多个平台交付世界级的应用程序. 方法是利用可用的工具, 把业绩放在首位, 并遵循最佳实践.

如果没有爱奥尼亚社区的创造力,这篇文章就不可能出现, Michał巫女łajczyk, Mike Hartington (Ionic Core团队)和 凯蒂Ginder-Vogel (Marketing & 传讯经理(Ionic). 非常感谢大家.

就这一主题咨询作者或专家.
Schedule a call
朱利安·雷诺的头像
Julien Renaux

Located in Toulouse, France

Member since June 16, 2015

About the author

Scrum Master Julien (MCS)是一名前端移动开发人员,曾在eBay等初创公司和企业工作过, 甚至是法国航天局.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Previously At

eBay

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.