Skip to main content

跨平台

¥Cross Platform

Ionic 是从头开始构建的,无论你为什么平台构建,都可以轻松开发。Ionic 应用是真正跨平台的:能够作为 Android、iOS、Electron 和渐进式 Web 应用 (PWA) 运行,所有这些都来自单个代码库。在优化应用以跨这些平台运行时,需要记住一些要点。

¥Ionic is built from the ground up to make development easy, no matter what platform you are building for. Ionic apps are truly cross-platform: able to run as an Android, iOS, Electron, and Progressive Web App (PWA), all from a single codebase. There are some points to keep in mind when optimizing an app to work across these platforms.

硬件 API

¥Hardware APIs

在原生应用中,通常会调用 API 来与设备进行通信,例如打开摄像头或访问地理位置。这些 API 调用在 Web 环境中调用时将不起作用,因为没有原生桥。Ionic 有几种方法可以处理这个问题。

¥In a native application, it's common to make API calls to communicate with the device, such as opening the camera or accessing geolocation. These API calls won’t work when called in a web environment because there’s no native bridge. There are a few ways Ionic handles this.

Ionic 原生

¥Ionic Native

Ionic 原生 有自己的内部逻辑来检测它是否在原生环境中。如果不是原生环境并且没有可用的 Cordova 插件,它不会抛出运行时错误,而是打印警告。该应用不会折叠,并且会继续工作,尽管没有原生功能。

¥Ionic Native has its own internal logic to detect if it is inside of a native environment. Instead of throwing a runtime error, it will print a warning if it is not a native environment and there are no Cordova plugins available. The app won’t break and it will continue to work, although without the native functionality.

平台检测

¥Platform Detection

在应用的逻辑中,每当需要进行原生 API 调用时,建议始终首先检查原生环境的状态。例如:

¥In an app’s logic, whenever it is needed to make a native API call, it is recommended to always check the status of the native environment first. For example:

this.platform.ready().then(() => {
// 'hybrid' detects both Cordova and Capacitor
if (this.platform.is('hybrid')) {
// make your native API calls
} else {
// fallback to browser APIs
}
});

当针对无法确定对原生 API 的访问的环境时,这段代码非常有用。

¥This bit of code can be incredibly helpful when targeting environments where access to the native APIs is uncertain.

浏览器回退

¥Browser Fallbacks

人们使用的许多原生 API(例如文件 API)在浏览器中不可用。API 总是在改进并赶上原生,因此建议研究它们。考虑到前两点,创建适合应用运行平台的良好体验相当容易。

¥Many native APIs that people use (for example, the File API), are not available in the browser. The APIs are always improving and catching up to native, so it is recommended to research them. Taking the first two points into consideration, it's fairly easy to create a nice experience that will adapt for the platform the app is running on.

响应式用户界面

¥Responsive UI

当计划部署可在多种设备上使用的应用时,确保应用在更大的屏幕尺寸上顺利运行非常重要。

¥When planning to deploy an app that may be used across a variety of devices, it is important to ensure the app works smoothly on larger screen sizes.

布局

¥Layout

许多人很少注意到应用的布局,但它会对体验和可用性产生巨大影响。考虑以下常见的 UI 模式:

¥Many people rarely notice the layout of an app, but it can have a massive impact on experience and usability. Consider this common UI pattern:

<ion-content>
<ion-item>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
</ion-item>
<ion-item>
<ion-label>Item 4</ion-label>
</ion-item>
<ion-item>
<ion-label>Item 5</ion-label>
</ion-item>
</ion-content>

这将渲染 5 个项目,每个项目的宽度均为 100%。这在手机上看起来可能很棒,但在更大的屏幕上查看却是另一回事。由于屏幕宽度较宽,这些项目会被拉伸以填满整个屏幕,从而导致屏幕空间未使用。

¥This will render 5 items with a width of 100% each. This may look great on a phone, but viewing this on a larger screen is a different story. The items become stretched to fill the entire screen because of the wide screen width, leaving screen space unused.

为了改善这种体验,我们可以将这些项目封装在 网格 组件中。该视图可以轻松地重写为在更大屏幕上更可用的内容:

¥To improve this experience, we can wrap the items in a Grid component. The view can be easily rewritten into something more usable on larger screens:

<ion-grid>
<ion-row>
<ion-col>
<ion-item>
<ion-label>Item 1</ion-label>
</ion-item>
</ion-col>
<ion-col>
<ion-item>
<ion-label>Item 2</ion-label>
</ion-item>
</ion-col>
<ion-col>
<ion-item>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-col>
<ion-col>
<ion-item>
<ion-label>Item 4</ion-label>
</ion-item>
</ion-col>
<ion-col>
<ion-item>
<ion-label>Item 5</ion-label>
</ion-item>
</ion-col>
</ion-row>
</ion-grid>

通过将项目封装在 ion-grid 元素中,Ionic 网格系统被添加到我们的布局中。将每个项目封装在一列中使得这些项目沿着同一行在网格内部占据相同的宽度。

¥By wrapping the items in an ion-grid element, the Ionic grid system is added to our layout. Wrapping each item in a column makes the items take up equal-width inside of the grid, along the same row.

我们可以通过将 fixed 属性添加到 <ion-grid> 元素来更进一步。这告诉网格根据屏幕尺寸具有固定宽度。当项目在网格上没有宽度的情况下再次开始拉伸时,这对于较大的屏幕来说是完美的。

¥We can take this even further by adding the fixed attribute to the <ion-grid> element. This tells the grid to have a fixed width based on the screen size. This is perfect for larger screens when items will begin to stretch again without a width on the grid.

通过添加 ion-col 属性,可以进一步自定义网格以更改列的大小。

¥The grid can be further customized to change the sizes of columns with the addition of the ion-col properties.

<ion-grid fixed>
<ion-row>
<ion-col size="12" size-sm="9" size-md="6" size-lg="4" size-xl="3">
<ion-item>
<ion-label>Item 1</ion-label>
</ion-item>
</ion-col>
<ion-col size="12" size-sm="9" size-md="6" size-lg="4" size-xl="3">
<ion-item>
<ion-label>Item 2</ion-label>
</ion-item>
</ion-col>
<ion-col size="12" size-sm="9" size-md="6" size-lg="4" size-xl="3">
<ion-item>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-col>
<ion-col size="12" size-sm="9" size-md="6" size-lg="4" size-xl="3">
<ion-item>
<ion-label>Item 4</ion-label>
</ion-item>
</ion-col>
<ion-col size="12" size-sm="9" size-md="6" size-lg="4" size-xl="3">
<ion-item>
<ion-label>Item 5</ion-label>
</ion-item>
</ion-col>
</ion-row>
</ion-grid>

上面的例子发生了很多事情。这些是关键点:

¥There’s a lot going on in the example above. These are the key points:

  • ion-col 从添加到它的 size 属性中获取其宽度,其中 size 的值是从总可用列中占用的列数。默认可用列数为 12。

    ¥The ion-col gets its width from the size attribute added to it, where the value of size is the number of columns to take up out of the total available columns. The default number of available columns is 12.

  • size 属性可以添加断点 size-{breakpoint}。该值设置指定断点及以上断点的大小。

    ¥The size attribute can have a breakpoint added to it, size-{breakpoint}. This value sets the size for the specified breakpoint and above.

有关使用网格进行自定义的更多信息,请参阅 网格 文档。

¥For more information on customizing with grid, see the Grid documentation.

存储

¥Storage

大多数应用在某些时候都需要在本地存储某种数据。无论是存储 XHR 请求中的一些 JSON,还是保存身份验证令牌,都有许多不同的存储选项可用。除此之外,如果应用在原生环境中运行,则可以创建完整的 SQLite 数据库并在其中存储数据。所有这些不同的存储机制都有各自的优点和缺点,但 Ionic 开发者不必担心这一点。

¥Most apps at some point will need to store some sort of data locally. Whether it’s storing some JSON from an XHR request, or saving an auth token, there are many different storage options available. On top of this, if the app is running in a native environment, it is possible to create a full SQLite database and store data there. All of these different storage mechanisms have their own advantages and disadvantages, but Ionic developers should not have to worry about that.

Ionic 存储

¥Ionic Storage

在这种情况下,Ionic 的存储库 是多环境用例的完美候选者。Ionic 的存储类构建在经过充分测试的 LocalForage 库之上,提供了一种适应性强的存储机制,可以为当前运行时选择最佳的存储解决方案。

¥In this case, Ionic’s Storage library is a perfect candidate for the multi-environment use case. Built on top of the well tested LocalForage library, Ionic’s storage class provides an adaptable storage mechanism that will pick the best storage solution for the current run time.

目前,这意味着它将通过 SQLite 运行原生、IndexedDB(如果可用)、WebSql 或本地存储。通过处理所有这些,它允许使用稳定的 API 写入存储。

¥Currently this means it will run through SQLite for native, IndexedDB (if available), WebSql, or Local Storage. By handling all of this, it allows writing to storage using a stable API.

class MyClass {
constructor(public storage: Storage) {}

async setData(key, value) {
const res = await this.storage.set(key, value);
console.log(res);
}

async getData(key) {
const keyVal = await this.storage.get(key);
console.log('Key is', keyVal);
}
}

还有其他存储解决方案,例如 PouchDB,它提供了类似的、适应性强的存储机制。

¥There are other storage solutions out there as well, such as PouchDB, which provide a similar, adaptable storage mechanism.