Li Chao, front-end development engineer of Meituan Dianping, with 2 years of WEB development experience, is now a member of meituan Dianping ordering team.

After the publication of several articles of our team’s applets development experience series, have you had a deeper study and understanding of the applets view layer (The view layer), logic layer (the logic layer), API (official API document) and so on? It is easy to “talk the talk”, but the key is to “win the battle well”. Today, I would like to share with you the problems and solutions encountered in the actual development of “Dianping ordering mini program”.

Results show

Static effect display diagram

Dynamic effect display diagram

The page layout

If you have read our series of articles, you should have a general idea of the shape of our products. We are doing order menu service, the menu needs to be categorized, shopping cart module, so the typical ‘work’ layout is our first choice.

The general structure is: the top business name, there may be yellow bar prompt module; The navigation menu bar is on the left below; Below the right side is the list of dishes included in each menu category; A shopping cart module may appear at the bottom. This, combined with the image above, should give you a concrete idea of the structure of the menu page. Here are the specific interaction details from a product perspective.

Product demand

  • The top requirement shows the business name, has the sharing function;
  • In the lower part, the left and right sides can be scrolled separately. The left side does not affect the right side, and the right and left sides of the scrolling menu will be highlighted in linkage.
  • Click the left navigation menu bar below to highlight the clicked menu category. The top of the corresponding category details module on the right below coincides with the top of the scroll area on the right (similar to the anchor point function of # ID in HTML);
  • When scrolling the details of dishes on the lower right, when the top of the classification details module touches the top of the rolling area, the corresponding navigation menu bar on the left is highlighted;
  • If the navigation menu highlighted on the left is not visible:
    • When the top of the highlighted navigation menu is above the left scrollable area (hidden), scroll the highlighted navigation menu until the top of the highlighted navigation bar coincides with the top of the left scrollable area (the highlighted menu is the first category of the scrollable area);
    • When the highlighted navigation menu is under the left scrollview view area, scroll the highlighted navigation menu to the center area of the screen (minor deviation is acceptable, mainly depending on user experience). ;
  • A yellow bar may appear at the top and below to indicate the copywriting module;
  • A shopping cart module may appear above the bottom;
  • Yellow bar at the top prompts copywriting module to suck top, bottom shopping cart module suck bottom;
  • Need to adapt to a variety of different models.

List of key technologies

It should be pointed out here: before the design of the product is completed, we have done a careful research on the functions supported by the small program, and decided on the UI and interaction design on the premise of ensuring that the requirements of the product can be realized through technical means.

  • From the point of view of product compatibility, we consider using wechat mini programrpxSize as UI design. The size andremVery similar, except for the reference size.remUse the size set by the document root element as the base size, whilerpxUse iphone6(s) mobile phone screen width as the benchmark1rpxCorresponding width, the dynamic size of the device compatibility more friendly;
  • Wechat has its own Scroll View UI component and provides a series of component status operation interfaces.
  • scroll-viewThe Scroll event is triggered when the component is scrolling and returnedeventObject all length attributes are usedpxAs a unit;

The code to compile

SRC ├── Menu.html ├─ menu.js ├─ menu.json ├─ menu.less

We used tools to compile files in real time during development:

 `menu.html`->`menu.wxml`
 `menu.less`->`menu.wxss`Copy the code

For easy code maintenance and routine development habits, we supported the less syntax and introduced Promise.

WXML page layout

### menu.html <page> <view class="menu-content"> <view class="yellow-bar"> // Yellow bar </view> <scroll view class="scroll-view-left" height="{{ windowScrollHeight }}" scroll-into-view="{{ leftToView }}" scroll-top="{{ </scroll view> <scroll view class="scroll view-right" height="{{windowScrollHeight}}" </scroll class="cart-bar"> </view> </view> </page>Copy the code

Here we focus on two Scroll view structures. The left and right layout structures can use Css style properties float or Css3 Flex. In addition, yellow bar prompt module and shopping cart module use fixed attribute. To use the Scrollview component, you must specify the height. Practical result: The height can not be specified when using the scrollview, and there is a scroll area on the page. The problem is that the Scroll event cannot be triggered during scrolling, so the linkage design cannot be completed.

Height of rolling area

We know that we need to specify the height to use the scroll view, so how to calculate the height value and how to set it? I’m not going to go into the details here, but I’m going to look at the Scroll view document.

Two points to note:

  • You must use thepxAs a unit
  • Must be inscroll-viewSpecify it explicitlyheightattribute

Before obtaining windowScrollHeight, consider its influence factors:

  • Equipment is highly
  • Yellow clause case prompt module exists
  • Presence of shopping cart module
  • rpx->pxThe transformation of the

You can obtain the device height from wechat official API getSystemInfo interface API.

So, when should the interface be called? It is an asynchronous API interface and is directly subject to system permission control, so the timing of the result return is uncertain. We can call this API in onLaunch when the applet starts, and then put the results into the global variable globalData. GlobalData is a property that hangs on the global App and is visible to all pages.

getSystemInfoResult data structure

sysInfo Object {
    errMsg:"getSystemInfo:ok"
    language:"zh_CN"
    model:"iPhone 6"
    pixelRatio:2
    platform:"devtools"
    system:"iOS 10.0.1"
    version:"6.3.9"
    windowHeight:627
    windowWidth:375
}Copy the code

“WindowHeight” refers to the height and width of the screen in units of px.

To obtainsysInfo

// app.js // Note that WXP is our encapsulation of WX. It inherits all the properties of WX, with the feature that the async API function of WX returns a Promise instance if invoked. getSysInfo: function() { let that = this; If (that globalData && that. GlobalData. SysInfo &&. That globalData. SysInfo. WindowHeight) {/ / will result in Promise, Use the 'then' method to return promise.resolve (tha.globaldata.sysinfo); } return wxp.getSystemInfo() .then(res => { that.globalData.sysInfo = res; return res; }). Catch (e => {// Can try popup or toast console.error('[getSystemInfo]', e); }); }, // menu.js onLoad: function() { app.getSysInfo().then((sysInfo)=> { // transform rpx -> px and calculate scroll-view height. } }Copy the code

To calculatefixedThe element height

The height of the yellow section prompt module and the shopping cart module are known. But if you noticed the design detail I mentioned earlier: all elements use RPX units, but here we need to use PX units, we must do RPX ->px conversion.

RPX size comparison table

rpx->pxPacked in

var yellowBarRpxHeight = 50; / / yellow copywriting tip module highly var percent = app. The data. The sysInfo. WindowHeight / 375; Var yellowBarHeight = Number(yellowBarRpxHeight * percent).tofixed (2);Copy the code

Is there any question about the divisor 375, whether that ratio is affected by the actual number of pixels on the device? Answer: No. The same goes for cart module height, cartBarHeight. By the formula: windowScrollHeight = WINDOwheight-yellowbarheight-cartbarheight calculate the scrolling height of two scrollviews.

Left -> Right linkage

Click the left navigation menu bar and locate the corresponding classified dishes on the right. By viewing the scroll-view document, the scroll-into-view property can be used. This component automatically locates the location to scroll to on the right. Bind the tap event listening function to the left navigation menu bar, obtain the currentTarget attribute of the event object after the event is triggered, extract the classification ID stored on the node during rendering, and use this ID as a unique identifier to locate the classification details on the right. Set the scroll into view property of the right scroll view, then it will scroll the node with the id value of the right scroll view to the top of the scroll area (similar to the # ID anchor point function in HTML).

Tap event listener function

// menu.js bindLeftTap (e) {// Since the event bubbles, it is not certain on which element the click is triggered, but currentTarget represents the node corresponding to the current binding event, Let dataset = e && e.currenttarget && e.Currenttarget. Dataset; var LEFT_TO_RIGHT_SUFFIX = "l2r-"; if(! dataset || ! dataset.id) return; // Target this.setData({highlightCategoryId: dataset. Id, rightToView: LEFT_TO_RIGHT_SUFFIX + dataset. Id, // Update the right scroll-to-view attribute. }); }Copy the code
  • LEFT_TO_RIGHT_SUFFIX“What is it? It is a globally defined constant, but it is written inside the function for easy readingidSplicing to ensure uniqueness.
  • An attempt was made to get it directly during the development phaseidAs arightToViewIs set to the rightscroll-viewthescroll-into-viewProperty, found on the rightscroll-viewDoes not scroll to the specified height. Guess it could be because you getdataset.idIs a numeric string that is used internally= = =Mode causes a mismatch.
  • Set up thescroll-into-viewThe resulting scroll operation also firesscrollEvents.

Right -> left linkage

Right – left linkage is the core part of the whole page design. Because the small program cannot obtain the width, height and position information of elements, it is a challenge to realize the left linkage effect on the right side of scrolling.

How to accurately get the right scroll to the specific category, and make the left navigation menu bar corresponding category highlighted, and within the scope of visual?

In the design stage, we confirmed with the design students that the height of each dish detail module on the right side was fixed, and the small gray bar for classification was fixed, so that we could calculate the height of each element from the top of the document area according to the existing data structure. (Please refer to the red box below to circle the contents corresponding to the classification of the small gray bar, details of dishes module)

Individual dish classification details

Var sumScrollHeight = 0; var sumScrollHeight = 0; var assistantCategories = spuMenuSet.map(it => { let unitHeight = PER_BAR_HEIGHT + (it.spuMenuItemList && it.spuMenuItemList.length ) * PER_ITEM_HEIGHT; it.scrollHeight = sumScrollHeight; sumScrollHeight += unitHeight; return it; });Copy the code

The boundary condition for highlighting classification switching in the left navigation menu bar is that the top of the small gray bar of classification menu details on the right coincides with the top of the scroll area on the right.

By calculating the scrollHeight of each classification small gray bar from the top of the document, when each scroll event is triggered, compare the current scrolling height with the scrollHeight of the classification small gray bar to determine which classification menu details area is currently in, so as to realize the highlighting of the left classification navigation bar.

Machine error

During the test, it was found that when some models rolled the right scroll view at the bottom, the switch of highlighting classification in the left navigation menu bar would not be completed when the boundary conditions appeared, and there was often an error of 10-100px. From a product point of view, this kind of error cannot be tolerated. I’m not sure what causes the error, but there seems to be no good solution. So what can be done to reduce the error? My realization idea is “manual intervention automatic correction”.

Manual intervention automatic correction

Carefully analyze the event object returned by the scrolling event

Object
    currentTarget:Object
    detail:Object
        deltaX:0
        deltaY:-971
        scrollHeight:24737
        scrollLeft:0
        scrollTop:2409
        scrollWidth:295
        __proto__:Object

    target:Object
        dataset:Object
            __proto__:Object
            id:""
            offsetLeft:0
            offsetTop:38
        __proto__:Object
    timeStamp:13932
    type:"scroll"
    __proto__:ObjectCopy the code

Pay special attention to the scrollHeight in the detail.

The scrolling event will give the height of the entire Scroll View document content, which is very critical. We can calculate it completely by: scrollHeight = the height of a single dish detail * total number of dishes + the height of a single classification small grey bar * total number of classification small grey bars.

Since the height ratio between the detail height of a single dish and the height of the small grey bar of a single category is determined, the above equation is a unary equation, which calculates the detail height of a single dish and the height of the small grey bar of a single category, and updates the scrollTop value of the distance between the small grey bar of each category and the top of the document. It is found by test that the switching accuracy of left navigation menu bar highlighting classification is very high, and the compatibility is very good.

Left side highlight classification error

In the actual development, I also found A problem: there are categories A, B and C on the left, click category B, and category B will be highlighted. The right side will locate the details area of category B, and then the left highlighting category will switch to A. Do you have any idea what might be causing this? I mentioned a little bit about the scroll view property above:

The scroll operation caused by setting the scroll into-view will also trigger the Scroll event

Click the left classification here. On the right, since the scroll event is triggered by the scroll into-view, and the corresponding scroll event monitoring function function calculates that the navigation menu bar currently highlighted is A. Update the data on the page and switch the highlighting classification to A. Solution: (1) Modify the boundary conditions, but there are subtle differences on different machines, we can not accurately set the error range; After all, we figured out the width and height; ② Restrict the execution of the scroll event function on the right. The second option is recommended. If you click the left navigation menu bar to set the global lock status, if locked, do not move from right to left, and then unlock the lock status.

Categorize visual problems in the navigation bar

Through the above “right → left” linkage, we can make the left side highlight as the right side scrolls. The question is: the left side is also a Scroll view, how to ensure that the highlighted classification is in the visual area? See product requirements above for detailed interaction logic

Highlight categories below the viewable area

Highlight categories above the viewable area

Listen to the right scroll event, determine the current category, determine the document height of the category in the left scroll view, and determine whether to scroll the left scroll view. You can scroll through the scroll-in-view or scroll-top property of the scroll-view.

Var index = mapId2index(id); // Convert the id to the index value of the corresponding category var perCateHeight = 40; Var leftScrollTop = 0; Var windowScrollHeight = 1440; Var cHeight = index * perCateHeight; If (cHeight - leftScrollTop - windowScrollHeight > 0) {// The highlighted area is at the bottom of the screen leftScrollTop = cHeight -  windowScrollHeight / 2; // Left scroll-view up half screen height leftToView = null; Else if (cheight-leftScrollTop < 0) {// The highlighted area is above the top of the screen, Set the scrollinto-view property leftToView = id; leftScrollTop = cHeight; } else {leftToView = null;} else {leftToView = null; }Copy the code

Note: If both the scroll-into-view and scroll-top properties are set, the scroll-into-view property is preferred. Therefore, if the scroll-top property is used for scrolling, the scroll-into-viwe property must be null.

To optimize the

After the linkage function was developed, performance bottleneck was encountered. Due to the reuse of the previous C-side data interface, there are a lot of useless object attributes in the interface, and this data structure is directly used as the data data of the page rendering. The recommended approach is to simplify the data structure and only store data that affects page rendering, which can significantly reduce UI rendering time and give the user a smoother experience.

conclusion

Wechat small program is a very hot new technology in 2016 -2017. How to design and develop products with supported functions and features is an important link to ensure the smooth completion of projects. And in the development process, focus on the details of the implementation, understand API documents, so that users feel our sincerity to develop small programs, rather than doing rough product replication.

feeling

During the period of the release of small programs, there are always a variety of assumptions about the future of small programs, some pessimistic, some wait-and-see, and some radical. Personally, I don’t think the idea of “chasing ducks on shelves” is advisable. You must know your product positioning. Does your product satisfy the concept of “one-time consumption”, does the content not attract enough users to download your APP, and is it more attractive than your H5? These all need us to do careful thinking.


Did this article help you? Welcome to join the front End learning Group wechat group: