Following the discussion of various mixed application development schemes, I think the hybrid application cloud platform represented by APICloud is the most suitable for me at this stage. For front-end users who do not know native development, they really cannot afford to step on the pit of other schemes. In order to make the pit no longer trap people, I summarize and encapsulate my experience of projects based on cloud platform into a hybrid application development framework. HybridStart is discussed below.

Why do you need HybridStart

What does the platform offer

APICloud integration including window systems, application management, network communication, data storage, news events, device access, UI components, multimedia, and other functions, these functions requires no additional plugin support can be called directly, can be said to be worthy of “out of the box,” the official document with the introduction of the API or very detailed, It’s hard to know where to start when you first open a document, but here’s an example of what APICloud offers, and why it still needs to be repackaged in real projects.

Multiple WebViews are at the heart of APICloud, which means that an APP, like a website, is made up of several separate pages that open in sequence, forming a stack with the most recently opened pages on top and the previously opened ones at the bottom. The ability to navigate through the page stack by going back, jumping, closing, etc., is provided by the windowing system, which includes at least the following functions:

  • Open/close the page
  • Open/close the floating window
  • The jump page
  • Jump floating window
  • Execute scripts across pages
  • The local store
  • Page status monitoring
  • Global event publish/subscribe

These functions are sufficient to meet all the needs of window management, and some of them are even very powerful. For example, cross-page scripting means that you can execute A specific script from page A remotely from page B. There is also the ability to manipulate the stack directly, such as placing a specified page/floating window top/bottom; There is also a very useful publish and subscribe mechanism, which is an effective tool to break through page barriers.

It’s functional enough, but you probably won’t be able to write code after reading it.

What’s missing from the platform

There was no shortage of functionality, but I still had a lot of questions, at least from when I first encountered Windows.

First question, what is floating window? The background of the floating window is that on Android, only the scroll generated by the node is smooth and native, while the scroll generated by the

or other tags is very awkward. How do we do local scroll on the APP? By overwriting a small webView on the current webView, To implement smooth local scrolling, much like the

Second question, how to pass the parameter between Windows? There are two main ways, the first is the open window method itself supports parameter passing, can be in the new window through the specified API to get parameters, but this official method is not the best solution, the biggest disadvantage is that the need to wait for the native function ready, that is, in an asynchronous callback function to get parameters, not fast enough; Another method is to use local storage, save parameters in the original page, open a new page after the parameters, local storage is a Web capability, can be directly called without waiting for the native function ready, so more efficient; There are theoretically a third or fourth way, such as using cross-page scripting to fetch variables from another page, or using event listening to link two pages to pass parameters, but these are a bit weird. A = b&C =d works, but it won’t work on some Android systems.

Third question, how to synchronize the status of multiple pages? The biggest problem of multi-page mechanism is that the status is scattered in each page, which requires manual synchronization of the status. For example, after opening N pages, the user suddenly logs out, and the background page needs to be updated to the non-login state. At this time, global events need to be published and subscribed. Another scenario is the real-time update of list data, which can be performed each time the page comes back to the foreground by listening to the status of the front and back list pages. Another “point-to-point” approach is cross-page execution of scripts, which can make any page perform any action, powerful but with limited scenarios. As you can see, all of these operations can be implemented, but they’re cumbersome, and none of them seem to be standard implementations.

Fourth question, when to use Windows and when to use floating Windows? Local scroll with window, as long as it’s not have a possibility to use floating window, hope in the framework of the parent window by switch control multiple floating window to update the local content, the theory, but need more, because the father and son window basic is to rely on the communication across the page script execution, interaction will be very trouble, And floating Windows open slower than expected, development recommendations to avoid this practice.

Fifth question, an APP contains many pages, how to organize the code? On this problem and actually a question should be answered by the authorities, but the official newbie guide is basically no dice, can oneself cheer up the source code, but the official sample code organization is a mess, so to speak, not surprisingly you’ll see a bunch of HTML files in a folder, each filename of column name, the name of the page, the page type, If you open the HTML, you’ll find the javascript code at the bottom of the script tag. The only hint of organization is that you’ve extracted common CSS and common JS, which is weak.

Number six, how do you start? Give me a formula? Well, you just have to read through the document and step into a few project holes, and you’ll get it.

HybridStart is a hybrid application development scaffolding based on APICloud platform, filling in all possible pits.

What does HybridStart offer

Development mode

If it is the same as I had never come into contact with the front end of the APP development, I think the first thing to know is that different from the web APP is need a lot of initialization, such as the judge whether is logged in, data prefetching, check the update, registered push, global monitoring and so on, after the process APP to open the first page, The page life cycle is displayed.

There’s a very important concept in APICloud that hasn’t been stressed enough officially called root page, which is the first page that opens after the APP is launched. This page is very special and acts as the parent page of all other pages. When it’s closed, it means the APP exits, and it can’t be closed by other pages calling the close method. It is a necessary route to other pages. Based on these characteristics, this page is very suitable for APP initialization. After the initialization, the user immediately switches to the home page or login page. At this time, the user sees the first page, but it is actually the second page opened by the APP.

After the APP starts, the root page will stay in the background. For Android, it is also necessary to intercept the back key on the page that may return to the root page, prompting you to exit the APP and not allowing you to return to the root page, because root is a blank page with only JS code. The page life cycle of a hybrid application should be:

root -> index(exit) <=> page <=> page ...

Copy the code

The first thing we want to implement in the development is the initialization function of the root page, such as checking the login status and deciding whether to jump to the login page or the home page, and then implementing the login page or the home page.

APP data interaction almost all depends on the back-end interface, so it is necessary to agree an interaction format in advance to facilitate unified exception handling. For example, the simplest one is to first determine the large structure of JSON, including at least the status, data, and prompt information fields, as well as a total information field for the list data, so that a basic interaction format looks like this:

{

"Status ": "Y", // The status of the request "Y"/"N", can be extended as required

"Data ": [{...}], // The requested data array or object

"MSG ": "", // [Optional] Indicates the server information

"Count ": [number] // [Optional] When obtaining list data, attach count data to indicate the total number of lists for front-end paging

}

Copy the code

This allows us to encapsulate a data request method that automatically handles situations such as the MSG field when status is not “Y” without having to write error handling in every business logic.

Code organization

It’s not unusual for a slightly more complex APP to have dozens or hundreds of pages, so the first thing that APP code organization needs to address is page organization.

For sure, the pages should be managed together, but they can’t be listed directly. Then create a view/ folder first, and then divide it into two folders according to function modules. Put the member-related pages into member/ and the product pages into product/… ; Page scripts and styles do not want to be inline, it is best to have three files for each page, template, style and script, then put them in a folder, named after the page name. The pagefile is channel-page-pagefile, and the directory looks like this:

view/

| - member / / / member columns

| | - info / / / member information page

| | |--- temp.html

| | |--- style.css

| | `--- script.js

| ` - set / / / member Settings page

| |--- temp.html

| |--- style.css

| `--- script.js

|

| - home / / / APP homepage

| |--- temp.html

| |--- style.css

| `--- script.js

.

Copy the code

So even if there are more pages, find there are telltale signs, not see spent eyes in this file, the page style and split the script is also easy to develop, because once page code is very long, up and down the bala CSS and js also pretty painful, cleanly than apart, it’s a local file, little loading problem, Another advantage of organizing your pages as folders is that you can keep all of your unique resources in your own folders, so you don’t have to put all of your images in a public folder. When you look at a bunch of images in the future, you won’t know which ones are useful and which ones aren’t.

Then there is script organization. APP development needs to write a large number of JS. The purpose of ORGANIZING JS is to filter layers of non-business code out, so that more attention can be paid to the development of business scripts.

The first step is definitely to separate the class library from the business into plug-ins, services, and common scripts.

Common scripts are things like back button listening, image click listening, compatibility handling, etc. Every page should reference it (except root). You can pull all of them into common.js for easy modification. There are also some common business methods, such as formatting, looking up coordinates, etc., not every page can be used, but it is also necessary to centralized management, for the moment called him server.js; Other plugin scripts, such as upload and form validation, are packaged into modules and placed in modules/ folders. Finally, there is the class library, which is also the core of the framework. We call it core.js, which contains common class libraries and secondary encapsulation of the engine interface. The secondary encapsulation has at least three advantages. It’s like death to me; Second, if the API of the underlying engine is updated, there is no need to modify the business code, just change the corresponding package in core.js. Third, it is convenient to replace the bottom layer. In fact, the prototype of this framework is based on Appcan. Later, it is nothing more than changing a set of bottom API when switching to APICloud.

All that is left is script.js scattered across the pages, so the final script organization looks like this:

|--- sdk/

| |--- modules/

| | |--- upload.js

| | | -- -...

| |--- core.js

| |--- server.js

| `--- common.js

|--- view/

| |--- page/

| | |--- script.js

| | -...

Copy the code

The organization of CSS and other static resources is very simple, and there is no need to go into detail. Here is a complete directory structure:

| - docs / / / the document (no need to upload packing platform)

| - error / / / app error pages

| - res / / / app static resources (images, templates, etc.)

|-- sdk/

| | - modules / / / plug-in modules

| | - the font / / / fonts icon

. | | - core js / / core library

| | - server. Js / / business methods

. | | - common js / / common code page

| ` -- UI. CSS / / common style

| - view / / / app page

| -- config. Js / / framework configuration

'-- config.xml //APICloud configuration

Copy the code

Technology stack

Such fragmentary JS points must be inseparable from modularization, so the whole project is based on seaJS modular loading; JQuery 2. X is used for DOM manipulation. Many people feel that jQuery is too low to make hybrid applications. Does a few kilobytes of local resources make a difference? Etpl template engine used, this is very useful, a lot of asynchronous data rendering, no template engine can not.

Js class libraries are directly compressed into the top of core.js. Theoretically, you can add, delete, or change the code at will. However, the above three class libraries are also used in the subsequent app object implementation, so they cannot be deleted directly. Libraries other than these three can be deleted if not needed, such as xss.js, a library that protects against cross-site scripting attacks.

The significance of HybridStart

Objectives and Principles

I have a little code cleanliness, which is reflected in that I don’t like any secondary encapsulation. I hope to reach the key of function realization through the shortest path. Therefore, for this purpose, I did not use the official JS SDK at the beginning and directly called the engine API to develop business, which I think is the fastest and highest performance way.

However, the API provided by Appcan is inefficient and unreliable. When I was working on my first project with Appcan, IT was extremely buggy. Can you imagine that when I moved to APICloud, there were fewer obvious bugs, but some of the API still broke occasionally? This basic problem is no way out, then saw some introduction to hybrid application principle just know, this thing is a hack, reflex arc is longer, experience disadvantageous suo “, “accidental failure, also can understand, in fact, it is no wonder that, same as calling a native can be really like that doing more native.

So I changed my mind and stopped programming for the engine, because if you don’t know how an API works, you don’t really know how much it costs to use, so I started to accept secondary packaging and use engine power as little as possible in principle.

At the beginning, I modified the official JS SDK, deleted the useless functions and added the needed functions. After changing, I found that the JS SDK was too different from my needs, so I simply rewrote one. It was very cool to use it. As development progresses, it becomes more and more obvious that most of the requirements can be achieved with a limited number of apis. If you look closely at the API of the engine, you will find that some of the features are not necessary, or syntactically sugar. Even some functions are not as good as JS simulation, the quality of development behind it can be seen.

In this purpose and principle, the engine API is secondary encapsulated into the APP object, in addition to the common core methods are directly mounted on the APP, but also includes several modules app.crypto, app.ls, app.window, app.Ajax.

app.openView

App object encapsulates all the functions needed for hybrid application development, but many trivial functions are hidden as far as possible, and may only need to modify a configuration to use in development, in order to simplify development. The app.openView() method, which opens a page, is one of the most commonly used methods in development, and gives you a sense of what HybridStart is made of.

First, let’s look at the API provided by the engine:

api.openWin({

Name: 'page1', // Name the window so that it can be closed by calling the close method

Url: './page1.html', // page path

PageParam: {// argument

name: 'test'

},

Animation: 'push', // animation effect

SubType: 'form_right' // Animation direction

});

Copy the code

OpenView () is a wrapper around this API. We hope to simplify the configuration in various ways without sacrificing functionality, so let’s start with these configurations. Let’s see how we can simplify each one.

The name attribute is used to give a window a name that can be used to call methods to operate on it in the future. If we want to omit this configuration, we can only automatically generate, but this name will be used in the future, so it can not be randomly generated, there must be a certain rule, here can be combined with the page organization to solve, according to the rules we talked about before the page is divided into two types, Level 1 page “/ view/channel/temp. HTML” and secondary page “/ view/channel/page/temp. HTML”, the law is clear, just provide the name of the page’s channel and if is secondary pages plus the name of the page, You can navigate to the page and get a unique name value from channel + “_” + page. Let’s assume that the openView method takes channel and page. Page is optional and will be called like this:

app.openView('home');           //url: "/view/home/temp.html", name: "home"



app.openView('member','set'); //url: "/view/member/set/temp.html", name: "member_set"

Copy the code

The property pageParam is a bit more complicated. Let’s talk about it later. Let’s look at animation and subType first.

These two properties should be encapsulated most. The animation type of page switching must be managed in a global configuration, and animation can be omitted when invoked. Animation direction configuration is basically a pseudo-requirement, open nature is right push, close nature is left push, respectively wrapped in the open and close page methods, subType can also be omitted.

Now look at pageParam, which is used to pass parameters to the page in Object format. Ok, this requirement must be there. We’ll make app.openView() support passing parameters, and the syntax will look like this:

app.openView(param[Object], channel[String], page[String]);

Copy the code

Because the page is optional and placed last for easy implementation, put the param parameter first. Seems to look also ok, but there will be other configuration, can not repeatedly add parameters, how to do.

There’s a experience, page and most occur in the page from the list to open the detail page, then we pass parameter is a id, which is a string, in fact, the vast majority of cases the page and is a string, need the Object is not much, based on this premise, we will extend the param parameter, You can accept both a string and an object, passing the value as an argument to the new page when you accept a string, and allowing the object to contain all the configuration of the openView method when it is an object, as well as the page parameters.

app.openView('newsID', 'news', 'detail'); // The most commonly used string parameter in real development



app.openView(null, 'home'); // If you do not need to pass the parameter, sorry, you must pass a null/undefined placeholder



App.openview ({//Object parameters must be passed this way

param: Object

}, 'home');



App.openview ({// Other parameters of the openView method can also be configured here

duration: 350

}, 'home');

Copy the code

This fixes all of the problems, but there is a minor glitch: no arguments must be passed with null/undefined placeholder, because the page argument is already available, and the param argument is not valid.

There are two ways to pass parameters to the page, one is through the API provided by pageParam, the other is through localStorage across the page value, the problem of pageParam is that the new page value is slow, the value code may be like this:

// Native functionality ready callback

app.ready(function(){

var pageParam = api.pageParam;

// Subsequent operations based on pageParam, such as page rendering, form validation, event binding

.

});

Copy the code

App.ready () is a native function-ready callback wrapped in the framework. It is an asynchronous callback. Usually, to speed up script response, we would put operations that do not require native capabilities outside of app.Ready () and execute them synchronously. But in order to wait for the parameters to be fetched, they must also be executed in app.ready(), which is annoying.

Therefore, the frame advocates the method of parameter transmission is to use localStorage, which can be synchronized in the new page. The only problem with this method is that it may cause a waste of resources, and various parameters are put into the local, how to clean up? My method is to specify a key crossParam that will be used to pass the parameter. Each time I pass the parameter, I will put it in here, and I will erase it again and again. All that is left is the last parameter value. Json.stringfiy () is handled if the parameter is an object type, so if you pass an object, you need to do json.parse ().

// synchronize page parameters

var param = app.ls('crossParam');

// Perform operations that do not require native capabilities

.



app.ready(function(){

// Perform operations that require native capabilities

.

})

Copy the code

Returning to the problem that the first argument of app.openView() must be filled, the point is that when app.openView() detects null/undefined it removes the crossParam key from local storage, minimizing the possibility of waste.

Of course, the official pageParam method is not obsolete, if the parameter is an object, pageParam and localStorage two methods are valid, through the api.pageparam method can also fetch the value.

With these packaging, open the grammar of the page has been very simple, but the app. OpenView () and many other functions, such as in the form of pop-up window open the page, in order to take the form of the title bar to open the page, open the new page at the same time close the current page, or open a web page, the realization of these functions are relatively complex, not a one by one, HybridStart here focuses on encapsulation ideas, but if you are interested in it, you can take a look at the HybridStart document.

Afterword.

Blowing along while, also have to go back to type selection, I don’t think the majority of projects for this plan, I think even only a few projects, or only the initial period of the project, you can use this solution fast horse fast iterative, my ideal mixing is primary and auxiliary web application form, but from the perspective of a front end, I have not found a better feasibility scheme, Some might say React Native, but that thing still needs to have a Native development base, and if APICloud takes things a step further with the UI components, it looks like it could approach React Native as well.

In short, this framework may be helpful if you feel that your project fits right into the scheme.

Source: making

Framework itself is a demo APP, with part of the function of the demo page, the code will be synchronized to your project can be compiled and downloaded, if the project is helpful to you, please go to Github to enjoy the Star do not feel welcome.

http://refined-x.com/2017/06/26/ Hybrid application development framework based on APICloud /