武装少女在线观看高清完整版免费,丝袜+亚洲区,少妇被cao高潮呻吟声,午夜伦情电午夜伦情电影,日日躁夜夜躁狠狠躁

小程序模板網(wǎng)

大眾點評點餐小程序開發(fā)經(jīng)驗 - 菜單聯(lián)動設(shè)計

發(fā)布時間:2018-04-14 14:59 所屬欄目:小程序開發(fā)教程
作者介紹:李超,美團點評前端開發(fā)工程師,2年WEB開發(fā)經(jīng)驗,現(xiàn)在是美團點評點餐團隊的一員。

“紙上談兵”很容易,“打好勝仗”才是關(guān)鍵。今天由我來為大家分享在實際開發(fā)“大眾點評點餐小程序”中遇到的問題和解決方案。

效果展示

 

靜態(tài)效果展示圖

 

 

動態(tài)效果展示圖

 

頁面布局

  如果你看過我們的系列文章, 應(yīng)該對我們的產(chǎn)品形態(tài)有了初步了解。我們是做點餐菜單服務(wù),菜單需要分類,需要購物車模塊,那么典型的'工'型布局是我們的首選。

大體結(jié)構(gòu)為:頂部商家名稱,可能會出現(xiàn)黃色橫條提示模塊;下方左側(cè)為導(dǎo)航菜單欄;下方右側(cè)為每個菜單分類包含的菜品展示列表;底部可能出現(xiàn)購物車模塊。
看到這里,再結(jié)合上面的圖片,你應(yīng)該對菜單頁的結(jié)構(gòu)有比較具象的了解。
下面從產(chǎn)品角度說下具體的交互細節(jié)。

產(chǎn)品需求

  • 頂部要求顯示商家名稱,有分享功能;
  • 下方左側(cè)、右側(cè)可分開滾動,滾動左側(cè)不影響右側(cè),滾動右側(cè)左側(cè)隨之聯(lián)動高亮顯示所在的菜單分類;
  • 點擊下方左側(cè)導(dǎo)航菜單欄,高亮顯示被點擊的菜單分類,下方右側(cè)對應(yīng)分類詳情模塊頂部與右側(cè)滾動區(qū)的頂部重合(類似于html中#id的錨點功能);
  • 滾動下方右側(cè)菜品分類詳情時,當該分類詳情模塊頂部接觸到滾動區(qū)域的頂部,左側(cè)對應(yīng)的導(dǎo)航菜單欄高亮;
  • 若左側(cè)高亮的導(dǎo)航菜單不在可視區(qū)域:
    • 當高亮的導(dǎo)航菜單頂部在左側(cè)scroll-view滾動區(qū)上方(被遮住了),則將該高亮導(dǎo)航菜單滾動至將高亮導(dǎo)航欄的頂部與左側(cè)可滾動區(qū)域頂部重合(高亮菜單為滾動區(qū)的第一個分類);
    • 當高亮的導(dǎo)航菜單在左側(cè)scroll-view滾動區(qū)可視區(qū)下方,將高亮導(dǎo)航菜單滾動到屏幕中央?yún)^(qū)域(微小偏差可以接受,主要看用戶體驗。);
  • 頂部下方可能會出現(xiàn)黃條提示文案模塊;
  • 底部上方可能會出現(xiàn)購物車模塊;
  • 頂部黃條提示文案模塊吸頂,底部購物車模塊吸底;
  • 需要適配各種不同機型。

關(guān)鍵技術(shù)羅列

  這里需要指出:產(chǎn)品在設(shè)計成稿之前,我們已經(jīng)對小程序支持的功能做了細致的調(diào)研,在確??梢酝ㄟ^技術(shù)手段實現(xiàn)產(chǎn)品需求的前提下才確定UI以及交互設(shè)計。

  • 從產(chǎn)品兼容性角度出發(fā),我們考慮使用微信小程序的rpx作為UI設(shè)計的尺寸。該尺寸和rem非常類似,不同點在于其對基準尺寸的設(shè)定。rem使用文檔根元素設(shè)定的尺寸作為基準尺寸,而rpx使用iphone6(s)手機屏幕寬度為基準定出1rpx對應(yīng)的寬度,該動態(tài)尺寸對設(shè)備的兼容性更加友好;
  • 微信自帶scroll-view UI組件,并提供一系列組件狀態(tài)操作接口;
  • scroll-view組件滾動時觸發(fā)scroll事件,返回的event對象各項長度屬性均使用px作單位;

代碼編譯

src
├── menu.html
├── menu.js
├── menu.json
└── menu.less

我們在開發(fā)中使用工具對文件實時編譯:


 `menu.html`->`menu.wxml`
 `menu.less`->`menu.wxss`

為方便代碼維護以及日常的開發(fā)習慣,我們支持了less語法,引入了Promise。

wxml頁面布局


### menu.html 
<page>
    <view class="menu-content">
        <view class="yellow-bar">
            // 黃色橫條提示模塊
        </view>
        <scroll-view class="scroll-view-left" height="{{ windowScrollHeight }}" scroll-into-view="{{ leftToView }}" scroll-top="{{ leftScrollTop }}">
            // 左側(cè)分類導(dǎo)航
        </scroll-view>
        <scroll-view class="scroll-view-right" height="{{ windowScrollHeight }}" scroll-into-view="{{ rightToView }}">
            // 右側(cè)分類詳情
        </scroll-view>
        <view class="cart-bar">
            // 購物車模塊
        </view>
    </view>
</page>

  這里著重考慮兩個scroll-view結(jié)構(gòu)設(shè)計,左右的布局結(jié)構(gòu)可以使用Css樣式屬性float或者是Css3的flex;另外黃條提示模塊和購物車模塊使用fixed屬性搞定。
微信官方文檔介紹,使用scroll-view組件,必須指定高度。
實踐結(jié)果:使用scroll-view可以不指定高度,頁面有滾動區(qū)存在,問題是滾動時無法觸發(fā)scroll事件,也就無法完成聯(lián)動設(shè)計。

滾動區(qū)域高度

  我們知道使用scroll-view需要指定高度,那么這個高度值該怎么算出來,以什么樣的方式設(shè)定呢?
這里我就不詳細的說明其用法了,直接看 scroll-view文檔。

注意兩點:

  • 必須使用px作單位
  • 必須在scroll-view上顯式的指定其height屬性

在獲取滾動區(qū)高度windowScrollHeight之前,考慮其影響因素:

  • 設(shè)備高度
  • 黃條文案提示模塊的存在
  • 購物車模塊的存在
  • rpx->px的轉(zhuǎn)換

設(shè)備高度可以通過微信官方api getSystemInfo接口API獲取。

那么,該什么時候調(diào)用接口?
首先這是一個異步API接口,另外其直接受系統(tǒng)權(quán)限控制的影響,基于這兩點因素,其結(jié)果返回的時機就不是確定的。
我們可以在小程序啟動時在onLaunch中調(diào)起該API,然后將獲取的結(jié)果放入到全局變量globalData中。而globalData是掛在在全局App上的屬性,對所有頁面均可見。

getSystemInfo 結(jié)果數(shù)據(jù)結(jié)構(gòu)


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
}

這里的windowHeight, windowWidth指的是屏幕高度和寬度,且使用的單位是px。

獲取sysInfo


// app.js
// 注意這里的wxp為我們對wx的封裝,它繼承wx的所有屬性,特點是若調(diào)起wx的異步api函數(shù)將返回一個Promise實例。
 getSysInfo: function() {
        let that = this;
        if(that.globalData && that.globalData.sysInfo 
            && that.globalData.sysInfo.windowHeight) {
            // 將結(jié)果封裝成Promise,后續(xù)可統(tǒng)一使用`then`方法
            return Promise.resolve(that.globalData.sysInfo);
        }
        return wxp.getSystemInfo()
            .then(res => {
                that.globalData.sysInfo = res;
                return res;
            })
            .catch(e => {
                // 可以嘗試彈出框或toast
                console.error('[getSystemInfo]', e);
            });
   },

// menu.js 
onLoad: function() {
    app.getSysInfo().then((sysInfo)=> {
        // transform rpx -> px and calculate scroll-view height.
    }
}

計算fixed元素高度

  黃條文案提示模塊,購物車模塊的高度都是已知的。但大家是否注意到我之前提到的設(shè)計細節(jié):所有的元素統(tǒng)一使用rpx做單位,而這里需要使用px作單位,必須要做rpx->px的轉(zhuǎn)換。

rpx尺寸對照表

 

rpx->px裝換


    var yellowBarRpxHeight = 50;  // 黃色文案提示模塊高度
    var percent = app.data.sysInfo.windowHeight / 375; // 當前設(shè)備1rpx對應(yīng)的px值
    var yellowBarHeight = Number(yellowBarRpxHeight * percent).toFixed(2);

大家對除數(shù)375是否有疑問呢, 該比值是否會受到設(shè)備實際像素點的影響呢? 答案:不會。
同樣的道理可以得到購物車模塊的高度cartBarHeight。
通過公式:
windowScrollHeight = windowHeight - yellowBarHeight - cartBarHeight
計算得出兩個scroll-view的滾動高度。

左->右聯(lián)動

點擊左側(cè)導(dǎo)航菜單欄,右側(cè)定位到對應(yīng)的分類菜品詳情。
通過查看scroll-view文檔發(fā)現(xiàn)可以使用scroll-into-view屬性;該組件自動定位右側(cè)需要滾動到的具體位置。
給左側(cè)導(dǎo)航菜單欄綁定tap事件監(jiān)聽函數(shù),事件觸發(fā)后獲取event對象的currentTarget屬性,取出渲染時存放在該節(jié)點上的分類id,用此id作為唯一標識定位右側(cè)分類詳情,設(shè)置右側(cè)scroll-view的scroll-into-view屬性,這時其會將右側(cè)scroll-view上id屬性值為該值的節(jié)點滾動到滾動區(qū)域的頂部(類似于html中的#id錨點功能)。

Tap事件監(jiān)聽函數(shù)


    // menu.js
   bindLeftTap (e) {
        // 由于事件是冒泡的,所以不確定點擊操作是在哪個元素上觸發(fā)的,但currentTarget表示當前綁定事件對應(yīng)的節(jié)點,便可準確獲取該節(jié)點上的dataset
        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, // 左側(cè)高亮的導(dǎo)航菜單欄
            rightToView: LEFT_TO_RIGHT_SUFFIX + dataset.id, // 更新右側(cè)的scroll-to-view屬性。
        });
    }
  • LEFT_TO_RIGHT_SUFFIX"是什么東西?其為全局定義的常量,只是為了方便大家閱讀,才將其寫入函數(shù)內(nèi)部,用作id拼接,保證唯一性。
  • 在開發(fā)階段曾經(jīng)嘗試直接將獲取到的id作為rightToView的值,也就是設(shè)定右側(cè)scroll-view的scroll-into-view屬性,發(fā)現(xiàn)右側(cè)scroll-view不會滾動到指定的高度。猜想可能因為獲取到的dataset.id是一個數(shù)字類型字符串,其內(nèi)部使用===方式導(dǎo)致不匹配。
  • 設(shè)置scroll-into-view引起的滾動操作同樣會觸發(fā)scroll事件。

右->左聯(lián)動

   右→左聯(lián)動是整個頁面設(shè)計最核心的部分。由于小程序無法獲取元素的寬高,位置信息,對滾動右側(cè)實現(xiàn)左側(cè)聯(lián)動效果帶來挑戰(zhàn)。

如何準確的獲取右側(cè)滾動到的具體分類,并讓左側(cè)導(dǎo)航菜單欄相應(yīng)分類高亮,且在可視的范圍內(nèi)?

在設(shè)計階段,我們和設(shè)計同學確認右側(cè)每個菜品詳情模塊高度固定,分類小灰條高度固定,這樣我們就可以根據(jù)已有的數(shù)據(jù)結(jié)構(gòu)計算出每個元素距離文檔區(qū)頂部的高度。(請參考下圖紅框圈出內(nèi)容分別對應(yīng)分類小灰條,菜品模塊詳情)

 

單個菜品分類詳情

 


// PER_BAR_HEIGHT 分類小灰條的高度
// PER_ITEM_HEIGHT 單個菜品詳情的高度
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;
});

左側(cè)導(dǎo)航菜單欄高亮分類切換的邊界條件為右側(cè)分類菜單詳情的分類小灰條頂部與右側(cè)滾動區(qū)頂部重合。

通過計算出每個分類小灰條距離文檔頂部的高度scrollHeight,在每次滾動事件觸發(fā)時,比較當前滾動的高度與分類小灰條的scrollHeight,就可確定當前在哪個分類菜單詳情區(qū)域內(nèi),從而實現(xiàn)左側(cè)分類導(dǎo)航欄的高亮。

機器誤差

  在測試時發(fā)現(xiàn),有些機型滾動下方右側(cè)scroll-view時,在邊界條件出現(xiàn)時并不會完成左側(cè)導(dǎo)航菜單欄高亮分類的切換,往往存在10-100px的誤差。從產(chǎn)品角度,這種誤差是不能容忍的。個人并不確定是什么原因?qū)е抡`差的出現(xiàn),但看起來并沒有非常好的解決辦法。
那么能用什么方案減少誤差呢? 我的實現(xiàn)思路是"人工干預(yù)自動校正"。

人工干預(yù)自動校正

仔細分析滾動事件返回的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__:Object

特別留意detail中的scrollHeight。

滾動事件會給出整個scroll-view文檔內(nèi)容的高度,這個高度值非常關(guān)鍵,我們完全可以通過計算:
scrollHeight = 單個菜品詳情高度 * 菜品總數(shù) + 單個分類小灰條高度 * 分類小灰條總數(shù)。

由于單個菜品詳情高度與單個分類小灰條高度的高度比是確定的,所以上面的方程式為一元方程,計算出單個菜品詳情高度和單個分類小灰條高度,更新每個分類小灰條距離文檔頂部的距離scrollTop值。
經(jīng)測試發(fā)現(xiàn),左側(cè)導(dǎo)航菜單欄高亮分類的切換精度非常高,而且兼容性很好。

左側(cè)高亮分類跳錯問題

在實際開發(fā)中, 我還發(fā)現(xiàn)一個問題: 左側(cè)有分類A、B、C,點擊分類B,分類B高亮,右側(cè)定位到分類B的詳情區(qū)域,隨之左側(cè)高亮分類切換到A上。
大家是否想到是什么原因?qū)е碌模?在上面講解scroll-view屬性時我提到過一句話:

設(shè)置scroll-into-view引起的滾動操作同樣會觸發(fā)scroll事件

這里點擊左側(cè)分類,右側(cè)由于scroll-into-view觸發(fā)了滾動事件,而相應(yīng)的滾動事件監(jiān)聽函數(shù)函數(shù),計算得出當前高亮的導(dǎo)航菜單欄為A,更新頁面的data將高亮分類切換到了A上。
解決方案: ① 修改邊界條件,但在不同機器上存在細微差別,我們無法準確的設(shè)置誤差范圍;畢竟元素寬高都是我們算出來的;② 限制右側(cè)的scroll事件函數(shù)的執(zhí)行。
推薦使用第二種方式。思路:若點擊左側(cè)導(dǎo)航菜單欄,設(shè)定全局鎖定狀態(tài),若鎖定則不右→左的聯(lián)動操作,再解除鎖定狀態(tài)。

分類導(dǎo)航欄的可視問題

  通過上面“右→左”聯(lián)動,我們已經(jīng)可以讓左側(cè)隨著右側(cè)滾動而高亮,問題是: 左側(cè)也是一個scroll-view,如何保證高亮的分類在可視區(qū)呢?具體的交互邏輯請看前面的產(chǎn)品需求

 

高亮分類在可視區(qū)下方

 

 

高亮分類在可視區(qū)上方

 

監(jiān)聽右側(cè)滾動事件,判斷當前在哪一個分類上,確定該分類在左側(cè)scroll-view的文檔高度,判斷是否需要滾動左側(cè)scroll-view。
可以通過scroll-view的scroll-into-view或者scroll-top屬性完成滾動。


// 這里是偽代碼實現(xiàn)
var index = mapId2index(id); //將id轉(zhuǎn)換為對應(yīng)分類的index值
var perCateHeight = 40; // 左側(cè)每個分類高度為40
var leftScrollTop = 0; // 左側(cè)scroll-view滾動的高度
var windowScrollHeight = 1440; // 這個值為屏幕高度,可通過getSystemInfo獲取到
var cHeight = index * perCateHeight; // 當前分類距離文檔頂部的scrollTop值
if( cHeight - leftScrollTop - windowScrollHeight > 0) {
    // 高亮的區(qū)域在屏幕底部
    leftScrollTop = cHeight - windowScrollHeight / 2; //左側(cè)scroll-view向上滾動半個屏幕高度
    leftToView = null; // 不使用scroll-into-view 屬性, 必須置空, 否則會優(yōu)先應(yīng)用該屬性而不是leftScrollTop
} else if (cHeight - leftScrollTop < 0) {
    // 高亮的區(qū)域在屏幕頂部之上,設(shè)置scroll-into-view屬性
    leftToView = id;
    leftScrollTop = cHeight; // 需要記錄下當前scroll-view滾動高度,以便下次使用
} else {
    leftToView = null;
}

注意點: 若同時設(shè)置了scroll-into-view和scroll-top屬性,優(yōu)先使用scroll-into-view屬性, 故這里若使用scroll-top屬性滾動時需要將scroll-into-viwe屬性置空。

優(yōu)化

聯(lián)動功能開發(fā)完之后,遇到了性能瓶頸。由于復(fù)用之前C端的數(shù)據(jù)接口,接口中存在大量無用的對象屬性,而這個數(shù)據(jù)結(jié)構(gòu)直接作為頁面渲染的data數(shù)據(jù)。
推薦的做法就是簡化data數(shù)據(jù)結(jié)構(gòu),只存放影響頁面渲染的數(shù)據(jù),這樣做能夠大幅度降低UI渲染時間,給用戶更加流暢的體驗。

總結(jié)

微信小程序算是2016年-2017年里非?;鸬囊婚T新技術(shù)了。
如何使用已經(jīng)支持的功能特性來設(shè)計、開發(fā)產(chǎn)品是保障項目順利完成的重要環(huán)節(jié)。
而在開發(fā)過程中,專注細節(jié)實現(xiàn),吃透API文檔,讓用戶感受到我們開發(fā)小程序的誠意,而不是在做粗糙的產(chǎn)品復(fù)制。

感受

在小程序發(fā)布那段時間,總能看到各種對小程序未來的設(shè)想,有悲觀的,有觀望的,也有激進的。我個人認為,“趕鴨子上架”的思路并不可取,必須清楚自己的產(chǎn)品定位。你的產(chǎn)品是否滿足“一次性消費”理念,內(nèi)容是否不足以吸引用戶下載你的APP,是否比你的H5更加具有吸引力。這些都是需要我們做細致的思考的。



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.kknew.com.cn/wxmini/doc/course/23392.html 復(fù)制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢: 點擊咨詢
在線客服
易小優(yōu)
轉(zhuǎn)人工 ×