本文概述
- 介绍
- 常见错误1:忘记启用本机滚动
- 常见错误#2:不使用Ionic CLI安装平台和插件
- 常见错误3:思维表现出众
- 常见错误4:与视图缓存逻辑混淆
- 常见错误5:不了解Android人行横道
- 常见错误6:尝试在浏览器中运行Cordova插件
- 常见错误7:针对大型应用程序遵循入门工具包体系结构
- 常见错误#8:将事件绑定到onscroll, 并忘记关于requestAnimationFrame的信息
- 常见错误9:手动制作Ionic应用原型
- 总结
介绍
Ionic已经存在两年了。它是用于基于AngularJS开发混合应用程序的大量工具。目前, Ionic非常受欢迎, 已构建了超过一百万个应用程序, 并且由成千上万的开发人员组成的社区不断增长。
自从Ionic的第一个版本发布以来, 时间已经过去, 并且网络技术和最佳做法已经在许多方面得到发展。因此, 很难确定开始新项目时应遵循的路径。在这种情况下, 开发人员可能会犯错误, 从而可能影响其应用程序的质量或团队的生产力。
通过阅读以下常见错误, 你将拥有避免基本问题并使用Ionic创建高性能和可扩展应用程序的关键。
目前, Ionic非常受欢迎, 已构建了超过一百万个应用程序。
鸣叫
常见错误1:忘记启用本机滚动
本机滚动允许Ionic在支持的Webview上侦听滚动事件。它可以在不进行JavaScript滚动的情况下实现”拉到刷新”, “列表重新排序”和”无限滚动”, 而JavaScript滚动是在浏览器缺少适当的滚动事件时创建的。
自Ionic 1.2(2015年12月)以来, 默认情况下在Android上启用”原生滚动”。它确保了异步事件带来的平滑滚动, 因此性能和用户体验得到了极大的改善。
不幸的是, 由于iOS上缺少适当的事件, 因此该平台尚未启用本机滚动。
如果使用的是1.2之前的版本, 则可以使用$ ionicConfigProvider为Android启用本机滚动:
// Enable Native Scrolling on Android
$ionicConfigProvider.platform.android.scrolling.jsScrolling(false);
你还可以在任何Ionic含量上使用溢出滚动指令在任何页面上启用或禁用本机滚动:
<!-- Disable Native Scrolling on this page only -->
<ion-content overflow-scroll="false">
请注意, 不幸的是, collection-repeat允许你的应用程序显示庞大的项目列表, 而本机滚动无法覆盖。
常见错误2:不使用Ionic CLI安装平台和插件
Ionic CLI为Cordova CLI添加了功能。平台和插件的持久性是Ionic CLI新增的一项重要功能。
Cordova CLI的问题在于, 你安装的平台和插件仅安装在计算机上。在团队中工作时, 为避免错误, 你想要共享相同的环境, 平台和插件。使用Cordova CLI, 使项目在开发人员计算机之间保持同步变得更加困难。是的, 你可以提交platform和plugins文件夹, 但是不建议这样做。
使用Ionic CLI安装平台ionic platform add ios和插件ionic plugin add camera时, 将适当地编辑package.json文件。
平台和插件存储在cordovaPlatforms和cordovaPlugins属性中:
"cordovaPlugins": [
"[email protected]", "[email protected]", "[email protected]"
], "cordovaPlatforms": [
"android", "ios"
]
现在, 其他开发人员在提取新代码时很容易同步, 只需在必要时运行Ionic状态还原(添加, 删除或版本更新)即可。
常见错误3:思维表现出众
Ionic基于AngularJS, 因此经常会质疑设备的性能。在这一点上, 我想向你保证:在AngularJS的基础上, 你可以使用Ionic创建世界一流的应用程序。
完美的例子是使用Ionic构建的Sworkit应用程序, 拥有900万以上的用户群, 700万以上的下载量以及在Google Play上平均获得4.5星。
如果你想从AngularJS中获得最大的收益, 那么在开始项目之前, 你应该学习以下几点。
$手表
观察者习惯于监听AngularJS中的范围更改。 $ watch基本上有四种类型:$ watch(普通), $ watch(深), $ watchCollection和$ watchGroup。
它们中的每一个都是不同的, 选择正确的一个可以在性能方面产生巨大的变化。
$ watch(正常)
使用普通的$ watch仅检查现有的Object属性或Array项。浅的更改(例如添加Object属性或将新项目推送到Array中)将不会得到处理。
$scope.$watch('watchExpression', function(newVal, oldVal){
if(newVal){
// watchExpression has changed.
}
});
$手表(深)
深度$ watch负责浅层更改和深层更改, 例如嵌套对象属性。有了这个$ watch, 你一定不会错过任何修改。但是, 使用深层的$ watch具有性能影响。我建议谨慎使用它。
$scope.$watch('watchExpression', function(newVal, oldVal){
if(newVal){
// watchExpression has changed.
}
}, true);
$ watchCollection
$ watchCollection可以考虑在普通$ watch和深$ watch之间。它也可以比较对象引用, 但是它的优点还在于可以通过添加Object属性或将新项推入Array来监视对象的属性。
$scope.$watchCollection('watchExpression', function(newVal, oldVal){
if(newVal){
// watchExpression has changed.
}
});
$ watchGroup
在AngularJS 1.3中引入的$ watchGroup允许一次查看多个表达式。
尽管$ watchGroup可能不会比普通的$ watch改善你的应用程序性能, 但它的优点是可以在观察多个范围表达式时更加综合。
$scope.$watchGroup([
'watchExpression', 'watchExpression2', 'watchExpression3'
], function(newVals, oldVals) {
if (newVals[0]) {
// watchExpression has changed.
}
if (newVals[1]) {
// watchExpression2 has changed.
}
if (newVals[2]) {
// watchExpression3 has changed.
}
});
追踪依据
使用ng-repeat时, 使用track by来避免不必要的DOM操作。确实, 如果摘要周期发现集合中至少一个元素发生了变化, 那么ng-repeat将重新呈现所有元素。 DOM操作始终会对应用程序性能产生影响, 因此, 越少越好。
为避免重新呈现完整的集合并仅更新需要更新的元素, 请使用带有唯一标识符的跟踪方式。
<!-- if items have a unique id -->
<div ng-repeat="item in items track by item.id"></div>
<!-- if not, you can use the $index that ng-repeat adds to every of its items -->
<div ng-repeat="user in users track by $index"></div>
只是避免在collection-repeat上使用track by。
一次性绑定
一次性绑定或:: ::在Angular 1.3中引入, 它对你的应用程序性能产生了真正的影响。
基本上, 在表达式上使用一次性绑定::会将其填充到$ watchers列表中。这意味着即使数据发生更改, 表达式也将无法更新。
<p>{{::user.firstName}}</p>
我们的建议是浏览你所有应用程序的视图, 并考虑哪些内容可能被更新或无法更新, 并相应地使用::一次性绑定。这将极大地缓解摘要周期。
请注意, 不幸的是, 一次重装订不能用于收集重复中, 因为屏幕上显示的项目列表会在滚动条上更改。
如果你想更多地了解AngularJS和Ionic性能技巧, 我建议阅读Ultimate AngularJS和Ionic性能备忘单。
常见错误4:与视图缓存逻辑混淆
默认情况下, 单页应用程序不缓存页面。你可能已经使用AngularJS应用程序体验过了, 在页面之间来回导航时, 滚动或用户输入不会保存。
使用Ionic, 默认情况下将缓存十个页面, 并且可以全局或按平台更改此页面。
// 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.loaded', function(){});
$scope.$on('$ionicView.unloaded', function(){});
$scope.$on('$ionicView.enter', function(){});
$scope.$on('$ionicView.leave', function(){});
$scope.$on('$ionicView.beforeEnter', function(){});
$scope.$on('$ionicView.beforeLeave', function(){});
$scope.$on('$ionicView.afterEnter', function(){});
$scope.$on('$ionicView.afterLeave', function(){});
如果要控制视图缓存, 则需要这些事件。
例如, $ ionicView.loaded事件是在第一次加载视图时触发的。缓存此视图时, 即使用户返回该事件, 也不会再触发该事件。通常, 使用与AngularJS中的$ viewContentLoaded事件相同的方式来初始化变量的事件。
如果你希望每次进入视图时都获取数据(是否缓存), 则可以使用$ ionicView.enter事件。
通过在正确的时间使用正确的事件, 可以提高应用程序的可用性。
关于性能, 使用缓存视图仅影响DOM的大小。缓存页面时, 所有观察者都将断开连接, 因此该页面只是页面上的一些DOM元素, 等待再次使用。
DOM的大小对于拥有良好的用户体验至关重要, 但是缓存多达十个页面似乎可以正常工作(当然, 这取决于你在页面中加载的内容)。
常见错误5:不了解Android人行横道
每个Android版本都运行不同的WebView(运行你的应用程序的浏览器)。不同设备的性能有所不同, 在旧的Android设备上可能确实很差。要在每台Android设备上获得流畅性和响应性的相同体验, 可以安装Crosswalk。它基本上将最新的Chromium浏览器嵌入到你的应用程序中, 并且每个APK(ARM和X86)都增加了约20Mb。
只需使用Ionic CLI或Cordova CLI即可安装Crosswalk:
ionic plugin add cordova-plugin-crosswalk-webview
常见错误6:尝试在浏览器中运行Cordova插件
使用Ionic的大多数开发人员都希望他们的应用程序可以在iOS和Android上运行。在添加了平台ionic平台之后, 添加了ios android并为一些插件ionic插件添加了cordova-plugin-device-orientation cordova-plugin-contacts, 一个愚蠢的错误是认为你可以在浏览器中对其进行测试。可以, 但是只有在安装正确的浏览器平台之后, 你才可以。请记住, 它不适用于所有插件。
Cordova的插件旨在通过JavaScript与本机设备API进行交互。因此, 联系人插件或设备定向插件将仅在设备上工作。
但是, 你可以轻松地在设备上测试代码并通过计算机进行远程调试。
在Android上进行远程调试
插入设备并通过运行adb设备确保计算机已正确检测到该设备(需要Android SDK)。
通过运行ionic run android构建你的应用并将其安装在设备上。在设备上启动应用后, 通过Chrome开发工具(在计算机上)chrome:// inspect /#devices打开控制台, 然后检查设备。
在iOS上进行远程调试
插入设备, 并确保计算机已正确检测到该设备。通过运行ionic run ios –device来构建你的应用程序并将其安装在设备上。
在设备上启动应用后, 通过点击开发> iPhone>应用, 打开Safari开发工具(在计算机上):
在浏览器中运行Cordova插件
在浏览器中运行Cordova插件是你应该了解的高级功能。从Ionic 1.2开始, 该浏览器得到了正式支持, 因此它开启了跨平台应用程序时代的超越iOS和Android平台的时代。
使用Cordova Browser平台, Electron和仅Web技术(JavaScript, HTML和CSS), 我们现在可以为浏览器和桌面(Windows, Linux和OSX)构建Ionic应用程序。
Github上提供了入门工具包。
Cordova浏览器平台
使用浏览器平台, 你可以为浏览器创建Cordova应用程序。这意味着你也可以在浏览器中使用Cordova的插件。
可以使用安装iOS或Android平台的相同方式安装它:
cordova platform add browser
与使用iOS或Android完全一样, 需要先编译你的应用程序:
cordova run browser
此命令将编译你的应用并打开默认浏览器。
跨平台插件
网络, 相机和Facebook等许多插件同时支持iOS, Android和浏览器平台-都具有相同的API。
为了说明使用ngCordova API可以了解你的设备在每个平台(iOS, Android, 浏览器和桌面)上是在线还是离线:
// listen for Online event
$rootScope.$on('$cordovaNetwork:online', (event, connectionType) => {
this.isOnline = true;
});
// listen for Offline event
$rootScope.$on('$cordovaNetwork:offline', (event, connectionType) => {
this.isOnline = false;
});
考虑到这一点, 你现在可以想象创建一个可以在一个代码库中任何地方运行的产品。
常见错误7:针对大型应用程序遵循入门工具包体系结构
使用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
这称为”按类型的文件夹”结构, 其中JavaScript, CSS和HTML文件按类型分组。对于初学者来说似乎很容易, 但这种架构很快就失控了。它根本无法扩展。
以下是一些不使用”按类型文件夹”结构的原因:
- 文件夹中的文件数量可能会庞大
- 查找需要为特定功能修改的所有文件可能很棘手
- 使用某个功能将导致许多打开的文件夹
- 扩展性不佳, 应用增长的越多, 使用它的难度就越大
我宁愿建议使用”功能文件夹”结构, 其中JavaScript, CSS和HTML文件按功能或AngularJS模块分组:
myNewFeature/
index.js (AngularJS module)
config.js
service.js
controller.js
index.html
style.scss
使用按功能文件夹结构的原因:
- 文件夹中的文件数限制为几个
- 查找特定功能所需修改的所有文件很容易-它们位于同一文件夹中
- 你可以独立处理功能
- 知道模块代表什么很容易-文件夹名称就足够了
- 易于创建新功能, 只需复制/粘贴现有功能
- 可以很好地扩展, 你可以根据需要添加任意数量的新功能, 而不会导致团队工作困难
请注意, 该架构与Angular2 / Ionic2应用程序中的默认按组件文件夹结构相似。
常见错误#8:将事件绑定到onscroll, 并忘记关于requestAnimationFrame的信息
这个单一的陷阱通常是初学者的错误, 但可能对性能产生最严重的影响。考虑一下:
<ion-content on-scroll="getScrollPosition()">
// …
</ion-content>
$scope.getScrollPosition = function () {
// heavy processing, like manipulating DOM
// or anything that triggers a $digest()
// will be called every ~80ms, // and will impact UX
}
即使Ionic为这些动作提供了限制, 但它仍然可能非常缓慢。基本上, 任何触发摘要循环的事件都应该推迟, 而不要与重画一起触发, 这也是滚动效果。
开发人员一直试图通过绑定滚动事件来实现许多目标, 尤其是动画, 也可以使用其他方法来实现。看一下requestAnimationFrame。
var myElement = document.getElementById('content');
var elemOffsetFromParent = myElement.offsetTop;
function onCapturedFrame() {
if (window.scrollY >= elemOffsetFromParent) {
customTweenFunction(myElement, options);
}
window.requestAnimationFrame(onCapturedFrame);
}
onCapturedFrame();
上面的代码是一个非常简单的示例, 它检查用户是否滚动到元素顶部之外。如果要使用该示例, 请记住添加特定于供应商的替代产品以实现跨浏览器兼容性。视浏览器而定, 它会以60帧/秒或屏幕刷新率的最佳速度运行。但是它是经过优化的, 高性能动画框架利用了这种简单的方法。
你可能还需要研究element.getBoundingClientRect(), 该元素提供有关HTML节点的大小和位置的信息。
常见错误9:手动制作Ionic应用原型
Ionic具有特定的设计, 几乎是一种视觉语言。特别是对于原型和早期产品, 通过利用可用的组件和样式可以节省大量时间和费用。它们实际上是最小的, 并且具有良好的美感。
呈现具有基本功能的线框和模型已成为行业标准。要查看图片并在移动设备上查看具有动态组件的实际应用, 可以喝两杯完全不同的茶。许多设计人员以及UX开发人员都使用Axure或Balsamiq之类的工具, 这些工具可以用最少的功能快速制作线框。
现在, Ionic的创建者发布了专门为Ionic开发人员设计的类似工具。它被称为Ionic创造者。它具有拖放式Web界面, 并且支持Ionic核心提供的所有功能。它的优点在于, 它可以使用标准的工作Ionic代码将原型导出为多种格式, 甚至可以构建应用程序并进行共享。该工具是专有工具, 但是许多选项可以免费使用。
总结
Ionic以前所未有的方式彻底改变了混合应用行业。但是, 随着时间的流逝, 最佳实践和工具缺乏发展。结果, 开发人员可能犯的潜在错误数量增加了。
资深的Ionic开发人员拥有一种清晰的方式将世界一流的应用程序同时交付到多个平台。方法是利用可用工具, 将性能放在首位, 并遵循最佳实践。
没有令人惊叹的Ionic社区, MichałMikołajczyk, Mike Hartington(Ionic核心团队)和Katie Ginder-Vogel(Ionic市场与传播经理)的创造力, 就不可能发布这篇文章。非常感谢大家。
评论前必须登录!
注册