The background,
1. Why Weex
Under the environment of rapid development of the company, App update and iteration are rapid and frequent. The technical team can produce a medium-sized App in two weeks on average, but the App team only has 6 people (3 for iOS and 3 for Android). On the premise of ensuring efficiency and quality, Relying solely on Native abilities is a stumbling process — we urgently need to improve team efficiency, hoping that one person can complete the workload of 2 to 3 people.
First, access to Web pages, one page ADAPTS to both ends;
Second, cross-platform development frameworks such as Weex, React Native, Flutter and Chameleon are selected. The mainstream frameworks are compared as follows:
Compare the content of |
React Native |
Flutter |
Weex |
To fit the difficulty |
general |
general |
easy |
Access to features |
Suitable for developing whole App |
Suitable for developing whole App |
Fit for a single page |
Maintenance difficulty |
general |
general |
easy |
Development of language |
React |
Dart |
Vue, Rax |
Frame size |
The heavier |
heavy |
The lighter |
The Bundle size |
larger |
Don’t need |
smaller |
community |
rich |
Since the new show |
imperfect |
Support terminal |
Android, iOS, |
Android, iOS, Web, etc |
Android, iOS, Web |
engine |
JSCore, V8 |
Flutter Engine |
JSCore, V8 |
After comparison, Weex was selected for the following reasons:
- Weex has a low cost, and single-page support is more in line with project planning.
- Vue framework, fit the big front-end environment of the team;
- Weex undertook taobao, Feizhu and other apps a large number of pages, giving the outside world sufficient confidence.
2. Weex with the Web
Although Web pages are easy to use and have lower maintenance costs, compared with Weex, the size of the Web package of the same page is larger than that of Weex. As a result, Web pages cannot provide pure Native experience, and the page loading speed is difficult to maximize, and the blank screen may occur on some devices. Weex has the following advantages that a team in pursuit of perfection would love.
Basic principles of Weex
Weex supports two front-end frameworks, Vue and Rax. The front-end team uses Vue for daily development. To reduce the cost of getting started, we choose Vue framework for Weex development. The Weex working process is as follows:
Weex WE file ————– front-end (we source)
↓ (Conversion) —————— Front end (construction process)
JS Bundle —————– front-end (JS Bundle code)
↓ (Deployment) —————— Server or local
JS bundle on server or local —- server or local
↓ (Compilation) —————— Client (JS engine)
Virtual DOM tree ————— client (Weex JS Framework)
↓ (Rendering) —————— Client (rendering engine)
Native view ————— client (rendering engine)
From the website
In addition to the front-end page preparation, Weex can be divided into
<text>
Iii. Client system architecture
Based on Native and with the help of front-end, the architecture evolves into a large front-end. The overall structure is shown in the following figure. We hope that App, as a terminal, can provide container capabilities, do a good job in the underlying services, and perfectly integrate Weex, Web and other cross-platform technologies.
4. Practice and solutions
The following lists some important and common problems and their solutions throughout the Weex page life cycle.
- Page to page communication
- routing
Weex navigator only supports simple online resources, but does not support loading of local files, and cannot meet dynamic presentation mode and complex parameter transfer. Therefore, it needs to implement a complete set of page hopping rules by itself.
In a lot of use
unified
convenience
The decoupling
Can be configured to change
routing
Scheme :/ Web /open? BundleUrl = XXX // Open the Weex page Scheme :/ Weex /open? BundleUrl = XXX // Open native page Scheme :/native/open? Url = XXX // Note: This form of routing can not only complete the intra-app hop service, but also perfectly support inter-app hopCopy the code
Example of launching a page redirect in Weex:
navigator.openUrl({
url: 'scheme://weex/open',
params: {
bundleUrl: '/dist/about.js',
name: 'Here are the parameters for the next page'},}) // Note: The next page only needs to declare an attribute in data with the same name as the parameter to receive the specific parameter.Copy the code
- Reverse the value
When we consider reverse value transmission, there are two scenarios. One is that the Weex page reversely transmits values to the Weex page, and the other is that the Native page reversely transmits values to the Weex page. We can use Weex based W3C specification
- When the page jumps
WXModuleKeepAliveCallback
Pass in the next page and execute the callback when appropriate. This is easy for iOS clients to do, but because Android needs to serialize the parameters into memory as it passes values between pages, and then deserialize them out of memory on the corresponding page, a new object is generated and the callback cannot be done.
- We tried to draw lessons from BroadcastChannel implementation, through the Weex project global JSContext object to trigger broadcast to complete the reverse value transmission, but in the end nothing.
We chose to use it
1.Weex added event listener const globalEvent = weex.requiremodule ('globalEvent');
globalEvent.addEventListener("eventName", (e) => { // ... }); 2. The native page send events weexInstance. FireGlobalEventCallback ("eventName", params); // Android
[weexInstance fireGlobalEvent:seventName params:params]; // iOSCopy the code
The weexInstance in the code can be understood as an instance object of a page, and the process needs to get the last one on the page that sends the listening
navigator.openUrl({
url: 'scheme://weex/open',
params: {
bundleUrl: '/dist/about.js',
needListen: true,}})Copy the code
2. Configure the page configuration file
Install the Mounted navigation bar on the Weex page. If the Weex page is mounted, add the following code to the Mounted method:
created () {
navigator.setTitle('Navigation bar title')
navigator.setItems([{
title: 'button',})}Copy the code
This unengineered and standardized approach causes great interference in later maintenance, cross-project migration, and architecture upgrade.
We optimized and upgraded the Weex page by referring to the design ideas of small programs. We added a CONFIGURATION file in JSON format for each Weex page that requires special configuration. The configuration file includes the configuration of the navigation bar, the page-level configuration, and the jump configuration, and made the configuration engineering and standardized.
For example, if I add a configuration file to the About page, the json file has the following class:
{
"navigationBarTitle": "Navigation bar title"."navigationItems": [{
"title": "Button"}}]Copy the code
The about.js and about.json files are in the same directory:
Then a complete page opening steps are as follows:
After the extension, the configuration file becomes richer. Previously troublesome jump processing and pop-up boxes can be realized through the configuration file. The following are some common attributes:
1. Some attributes
attribute |
type |
The default value |
describe |
backgroundColor |
HexColor |
Configuration of the same Project |
Window background color |
navigationBarBackgroundColor |
HexColor |
Configuration of the same Project |
Background color of navigation bar |
navigationBarHidden |
Bool |
false |
Hide navigation |
navigationBarTitle |
String |
|
Navigation bar title |
navigationBarTitleColor |
HexColor |
Configuration of the same Project |
Navigation bar title color |
2. IOS special form
To Present the page on an iOS client, you can set the following attributes:
present |
Bool |
false |
The Present page |
presentWithNavigationBar |
Bool |
false |
Present page with a navigation bar |
transition |
Map |
false |
Render as a transition and specify an animation expression for the transition (default background alpha from 0 to 1) |
Priority: Transition > presentWithNavigationBar > present |
In Transition, you need to define an animation expression, and Native needs to parse the expression and perform animation according to the expression.
3. Set navigation buttons
navigationItems |
Array |
[] |
Contains an array of button styles |
Use fireEvent to complete the callback of button events. |
Button style description:
{
"type": "TEXT", / /"TEXT"."IMG"."TEXT_IMG"Will pass"title": "Title"// Text header or"image": "Refresh"// Is the image address. The image address supports both local and network images"textColor": "FFFFFF", // Hexadecimal, default is white, can not be transmitted"backgroundColor": "", // hexadecimal, default transparent color, can not be transmitted"borderColor": "", // Hexadecimal, default no border, no transmission"borderWidth": 1, // Default no border, no transmission"cornerRadius": 1, // Default no rounded corners, can not pass"font": 16, // Default 16-point font, can not be transmitted"position": 0, // Default 0, no transmission, 0- left display, 1- right display"imagePosition": 0, // 0- picture on left, text on right, default, 1- picture on right, text on left, 2- Picture on top, text on bottom,Copy the code
4. Customize the navigation bar
For example, to meet the requirements of navigation bar segmentation:
navigationBarTitleComponent |
String |
There is no |
Name of the corresponding custom Component |
Component is implemented native and exposes apis to interact with Weex |
3. Shadow handling
Weex is iOS friendly, but Android doesn’t show shadows. The documentation explicitly addresses this problem, but the Android SDK provides a way to do it. Maybe ali’s engineers tried to fix it, but it didn’t work out. The obvious point is that if the item in the list uses a shadow, the slide of the list leaves the shadow where it was originally drawn. Android students have been trying to solve this problem, but it hasn’t worked out as well. The final downgrading solution was to use images instead of shadows. Here’s Weex’s official note:
Currently, only iOS supports the box-shadow attribute, but Android does not support it. You can use images instead.
Only one shadow effect can be set for each element. Multiple shadows cannot be applied to an element at the same time.
4. Network request
Weex provides
Therefore, we provide our own network request module, Weex side calls the method provided by Native, and determines the request through parameters, some optional parameters:
parameter |
type |
mandatory |
describe |
path |
String |
is |
Requested path |
method |
String |
no |
The request mode is’ GET ‘by default, and’ POST ‘and’ DELETE ‘are supported |
params |
Map |
no |
Request the required parameters |
timeout |
Number |
no |
Request timeout |
customHost |
String |
no |
Customize the Host of the request |
callback |
Function |
is |
The requested callback |
Example request:
// 1. Obtain native Module const nativeStream = weex.requireModule('nativeStream') // 2. Set basic parameters const options = {path:'/....'Method:'POST',
params: {
id: '123'Nativestream. fetch(options, (res) => {if (res.code === 0) {
succesCallback(res)
return
}
failCallback(res)
}Copy the code
5. Image loading
The loading of the <image> tag image requires the client to provide a handler. Currently, it supports remote linking and packaging of the generated Bundle resources, but does not directly support album images and images generated by taking photos. Its Base64 support provides a way for us to display photo albums. The following figure shows the process of selecting, photographing, and displaying photos in Weex:
From the above figure, we can know that a simple picture display process is not simple, among which the most critical is the choice of the scheme in the fifth step. Uploading pictures first is the most convenient solution for programmers, but it affects user experience. Pictures should be uploaded when they need to be uploaded, rather than interfering with business due to technical gap.
Switching to Base64 can improve the user experience, but has a performance impact. On iOS, the time required to convert a 1M image to Base64 is more than 45ms, and the time consumed in steps 6 and 7 is about 30ms, which increases with the image size in multiples.
To sum up, we design a localization scheme to generate a unique ID for each image added, and Native is responsible for image storage and loading.
6. Refresh components
The
components provided by Weex are simple in form and have interaction bugs. Therefore, we implement a set of refresh components by ourselves. Properties are used to determine whether the display is refreshed or not, and corresponding interfaces are provided to realize the interaction between Weex and Native.
1. The attribute
attribute |
type |
mandatory |
describe |
showRefresh |
Bool |
no |
Whether to add drop-down refresh |
showLoading |
Bool |
no |
Whether to add a pull-up refresh |
refreshAtCreated |
Bool |
no |
Whether to automatically refresh the display at the first time |
2. The event
- Refresh event: Triggered when
,-
,
is pulled down to complete, this event from native callback to Weex.
- Loading event: Triggered when
,-
,
is pulled up, this event is called back to Weex from native.
<list ref="list"
c
:show-refresh="true"
class="list"
@refresh="refreshList"
@loading="loadMoreList">
</list>Copy the code
- BeginRefresh event: the start of the drop-down refresh, called by Weex.
- BeginLoading event: starts a pull-up refresh, which is called by Weex.
- EndRefresh event: End the drop-down refresh, called by Weex.
- EndLoading event: Ends the pull-up. This event is called by Weex.
this.$refs.list.beginRefresh()
this.$refs.list.endRefresh()Copy the code
3. RefreshAtCreated properties
If you do not use this property, you need to manually invoke the refresh method in the Created or Mounted function to trigger the drop-down refresh. However, on some Android devices, a blank screen appears. Weex explains:
Unlike browsers, Weex’s rendering process is asynchronous, and the rendered results are all views in the native system, which cannot be directly accessed by javascript. Therefore, on Weex, the Mounted life cycle of a Vue is triggered when the virtual-dom (VNode in a Vue) of the current component is completed. In this case, the corresponding native view may not have been rendered.
7. Screenshots
Weex will generate a unique ID for each component when rendering. In JavaScript, ref is more intuitive. Although Weex does not have a real DOM, it still supports the use of REF. The specific approach is as follows:
// 1"poster"></div> // 2. Fetching this element is a Map const poster = this.$refs.poster // 3. Obtain the Map from the Map of saveViewShot({ref: poster. Ref}) // 4. Component // iOS WXComponent * Component = [weexInstance componentForRef:ref]; // Android WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(mWXSDKInstance.getInstanceId(), ref); // 5. Get the View and proceedCopy the code
8. Elegant popovers
This is a very simple popbox requirement where the view gets bigger and bigger and then it goes full screen. First, the Weex page layout starts from the bottom of the navigation bar by default. Second, the route hop mode does not support this popup mode. By default, the Weex page is pushed from right to left.
To implement the function of the popbox, we need four steps:
1. Native defines the PopView component
1. Set up the Weex page and layout the page based on PopView
2. Display the page in full screen and hide the navigation bar
3. Perform the animation
After the PopView component is defined natively, Weex pages can be laid out like this:
<template>
<pop-view class="pop-view"</pop-view> </template>Copy the code
Combined with the configuration file proposed in point 3, we put the control of steps 2 and 3 into the configuration file, and finally write the configuration file as follows:
{
navigationBarHidden: true// Hide the navigation bar transition: {property:'scale'Duration: 2, // Animation time, in seconds},// Transition display, and specify popView display animation}Copy the code
This is just the simplest example; more complex animations require client support.
B: Yes, Sir
The above summarizes the Weex access process, as well as the basic problems encountered in practice, shows that Weex in the team has been smooth and increasingly standardized, but more in-depth performance optimization, hot update, we need to continue to move forward, the following is the next article will cover the knowledge point:
- Hot update
- Resource preloading
- Make the configuration file dynamic
- Weex resource packaging is automatically added to the terminal warehouse
Add the official account of the Academy of Sciences
Mp.weixin.qq.com/s/LxdQ6Eq2R…