成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

vue移動(dòng)端側(cè)滑面板組件

TNFE / 2214人閱讀

摘要:里邊涉及到的指令是自定義的指令,為了處理移動(dòng)端的點(diǎn)擊操作,我還整理了一片陋文移動(dòng)點(diǎn)擊長(zhǎng)按滑動(dòng)指令然后這個(gè)組件的源碼我放在了我出來(lái)的項(xiàng)目上謝謝各位品嘗,

以下這段都是廢話,請(qǐng)?zhí)^(guò)

公司移動(dòng)端開(kāi)發(fā)平臺(tái)進(jìn)行了大變革,前端架構(gòu)由DCloud大生態(tài)轉(zhuǎn)換為VUE,所以移動(dòng)端的UI組件庫(kù)從MUI改為使用MintUI,然后開(kāi)始大刀闊斧的把MintUI組件改成MUI組件的樣子,然后發(fā)現(xiàn)少了幾個(gè)較為常用的,其中一個(gè)就是,嗯,側(cè)滑面板(也叫側(cè)滑菜單,也叫抽屜面板-andriod官方是這么翻譯的,很形象)。但是,它就是一個(gè)布局組件,具體里邊菜單什么的,那都是浮云(嗯,就是愛(ài)用幾年前的流行詞匯,而且很喜歡在網(wǎng)上沖浪和踩別人的空間)

以上這段都是廢話,感謝閱讀
需求

開(kāi)發(fā)一個(gè)側(cè)滑面板(類似QQ、網(wǎng)易郵箱等app的)

可以在左邊,也可以在右邊

側(cè)滑面板內(nèi)容隨意定制

側(cè)滑面板相對(duì)的就有主面板,那么衍生出不同的體位和姿勢(shì)

(1)主面板滑動(dòng),側(cè)滑面板不動(dòng)
(2)側(cè)滑面板動(dòng),主面板不動(dòng)
(3)它倆一塊動(dòng),一起--------

代碼風(fēng)格盡量和MintUI的其他組件風(fēng)格類似(這個(gè)挺重要的)

參考

mintUI組件中同樣??滑動(dòng)操作的tabContainer,為了滿足需求5,我連函數(shù)名都抄了過(guò)來(lái)。

不說(shuō)廢話,上代碼吧

The Waaaaaaaay 1. 設(shè)計(jì)組件結(jié)構(gòu)

這個(gè)組件分為兩部分,一部分為側(cè)滑面板容器,另一部分為主面板容器,然后具體容器內(nèi)部直接放了插槽,然后還需要一個(gè)主面板容器的遮罩,為了側(cè)滑面板打開(kāi)的時(shí)候顯現(xiàn)出來(lái)。上代碼了

2. 配置設(shè)計(jì)

這塊加了一些我們公司的一些需求,可能各位哥哥姐姐門用不到里邊的一些props的設(shè)計(jì),僅供參考

props: {
      // 側(cè)滑面板的寬度(單位px)
      "drawerWidth": {
        type: Number,
        default: 200
      },
      // 是否可用
      "enable": {
        type: Boolean,
        default: true
      },
      // 側(cè)滑菜單是否在右邊,默認(rèn)為false,在左邊
      "isRight": {
        type: Boolean,
        default: false
      },
      // 側(cè)滑菜單滑動(dòng)操作類型
      // ["fixDrawer"——固定側(cè)滑面板,主面板滑動(dòng)]
      // ["fixContent"——固定主面板,側(cè)滑面板滑動(dòng)]
      // ["noFixed"——一起滑動(dòng)!]
      "swipeType": {
        type: String,
        default: "fixDrawer"
      },
      // 點(diǎn)擊出現(xiàn)側(cè)滑菜單的按鈕的id ( @TODO 這里如何處理異步渲染的問(wèn)題 )
      "btnId": {
        type: String,
        default: ""
      },
      // 狀態(tài)位,側(cè)滑面板是否為打開(kāi)狀態(tài)
      // (因?yàn)槲覀児居羞@種一開(kāi)始就把側(cè)滑菜單打開(kāi)的shabee場(chǎng)景,所以這才會(huì)有這么個(gè)東西)
      //(如果這個(gè)不希望配置的話、可以放在data里邊)
      "isDrawerOpened": {
        type: Boolean,
        default: false
      },
      // 是否可滑動(dòng),如果不可滑動(dòng)的話,就只能通過(guò)調(diào)用toogle方法打開(kāi)側(cè)滑面板
      // 這個(gè)也是公司的一個(gè)使用場(chǎng)景,就是你甭滑,找個(gè)按鈕觸發(fā)一下側(cè)滑面板打開(kāi)的方法才能打開(kāi)
      //(如果這個(gè)不希望配置的話、也可以放在data里邊)
      "swipeable": {
        type: Boolean,
        default: true
      }
    }
2. 樣式設(shè)計(jì)

不得不承認(rèn),我的css寫的shit

對(duì)于整個(gè)的組件來(lái)說(shuō),它應(yīng)該是默認(rèn)充滿整個(gè)父容器的,而且這個(gè)組件,我覺(jué)得,一般都是用來(lái)放在最外層的一個(gè)布局組件,所以,默認(rèn)充滿窗口就行了
所以組件的最外層來(lái)一個(gè)絕對(duì)布局,然后如下:

.mint-drawer-layout {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    overflow-x: hidden;
}

然后側(cè)滑面板,只需要縱向充滿就可以了,寬度是配置

.mint-drawer-warp {
    position: absolute;
    top: 0;
    bottom: 0;
}

然后是主面板,沒(méi)說(shuō)的

.mint-content-warp {
    position: relative;
    width: 100%;
    height: 100%;
}
4. 關(guān)鍵實(shí)現(xiàn)

終于來(lái)到了介紹到底該怎么實(shí)現(xiàn)的了

滑動(dòng)處理三步走,start、drag、end

首先第一步上來(lái)就要設(shè)置一個(gè)記錄滑動(dòng)操作的狀態(tài)變量——dragging,設(shè)置為false,方便屏蔽滑動(dòng)時(shí)觸發(fā)的其他操作的執(zhí)行

——開(kāi)始的時(shí)候記錄開(kāi)始滑動(dòng)的位置
——滑動(dòng)中,dragging狀態(tài)記錄為true,開(kāi)始進(jìn)行滑動(dòng)位置和手指移動(dòng)的聯(lián)動(dòng)
——滑動(dòng)結(jié)束,dragging狀態(tài)記錄為false,計(jì)算當(dāng)前的滑動(dòng)位置,判斷是劃開(kāi)側(cè)滑面板還是關(guān)閉,并進(jìn)行動(dòng)畫處理

其中幾個(gè)細(xì)節(jié)小談一哈
(1)左右滑動(dòng)操作觸發(fā)的判斷:我這邊是公司的規(guī)范,橫軸移動(dòng)位移大于五,豎軸位移不大于橫軸的1.73倍就可以
(2)最后結(jié)束時(shí)判斷側(cè)滑面板的打開(kāi)和關(guān)閉:是這樣的,我這邊取的是三分之一的側(cè)滑面板的寬度,也就是從打開(kāi)到關(guān)閉,那么像關(guān)閉的方向滑動(dòng)側(cè)滑面板寬度的三分之一就可以了,如果是關(guān)閉到打開(kāi),往打開(kāi)的方向滑動(dòng)三分之一就可以了
(3)左側(cè)和右側(cè),還有三種不同的滑動(dòng)方式:三種不同的滑動(dòng)方式實(shí)際上就是控制到底哪個(gè)面板隨著手指動(dòng),具體的動(dòng)作過(guò)程和面板的偏移量實(shí)際上是一樣的。左右兩側(cè)就更簡(jiǎn)單了,直接是對(duì)稱的操作就可

滑動(dòng)結(jié)束的操作,參考的tabcontainer,也挺巧妙的,各位請(qǐng)上眼~

      /**
       * 滑動(dòng)結(jié)束的動(dòng)畫
       */
      swipeLeaveTransition() {
        let g = this, currentMovingDoms = [];
        let {swipeType, drawerWidth} = g;

        switch (swipeType) {
          case "fixDrawer":
            currentMovingDoms.push(g.content);
            break;
          case "fixContent":
            currentMovingDoms.push(g.drawer);
            break;
          case "noFixed":
            currentMovingDoms.push(g.drawer);
            currentMovingDoms.push(g.content);
            break;
          default:
            break;
        }

        currentMovingDoms.forEach((val) => {
          val.classList.add("swipe-transition");
        });

        setTimeout(() => {
          if (g.isDO) {
            this.swipeMove(drawerWidth);
          } else {
            this.swipeMove(0);
            g.contentMask.style.opacity = 0;
            g.contentMask.style.display = "none";
          }

          g.isToggle = false;

          currentMovingDoms.forEach((val) => {
            once(val, "webkitTransitionEnd", _ => {
              val.classList.remove("swipe-transition");
              g.swiping = false;
            });
          });


        }, 0);
      },

      /**
       * 滑動(dòng)操作
       * @param offset 滑動(dòng)位置
       */
      swipeMove(offset) {
        let g = this;
        let {swipeType, isRight} = g;

        g.contentMask.style.display = "block";
        g.contentMask.style.opacity = Math.abs(offset) / g.drawerWidth * 0.4;

        switch (swipeType) {
          case "fixDrawer":
            g.content.style.webkitTransform = `translate3d(${(!isRight ? "" : "-") + offset}px, 0, 0)`;
            g.swiping = true;
            break;
          case "fixContent":
            g.drawer.style.webkitTransform = `translate3d(${(!isRight ? "" : "-") + offset}px, 0, 0)`;
            g.swiping = true;
            break;
          case "noFixed":
            g.content.style.webkitTransform = `translate3d(${(!isRight ? "" : "-") + offset}px, 0, 0)`;
            g.drawer.style.webkitTransform = `translate3d(${(!isRight ? "" : "-") + offset}px, 0, 0)`;
            g.swiping = true;
            break;
          default:
            break;
        }
      },
      
      // 開(kāi)始滑動(dòng)
      startDrag(evt) {
        let g = this;
        if (!g.enable || !g.swipeable) return false;

        evt = evt.changedTouches ? evt.changedTouches[0] : evt;

        g.start.x = evt.pageX;
        g.start.y = evt.pageY;
      },

      // 滑動(dòng)中
      onDrag(evt) {
        let g = this, swiping;
        if (!g.enable || !g.swipeable) return false;

        g.dragging = true;

        const e = evt.changedTouches ? evt.changedTouches[0] : evt;
        const offsetTop = e.pageY - g.start.y;
        const offsetLeft = e.pageX - g.start.x;
        const y = Math.abs(offsetTop);
        const x = Math.abs(offsetLeft);

        swiping = !(x < 5 || (x >= 5 && y >= x * 1.73));
        if (!swiping) return;
        evt.preventDefault();

        let offset;

        if (g.isDO) {
          offset = g.isRight ? (g.drawerWidth - offsetLeft) : (g.drawerWidth - (-offsetLeft));
        } else {
          offset = g.isRight ? -offsetLeft : offsetLeft;
        }

        if (offset < 0 || offset > g.drawerWidth) {
          g.swiping = false;
          return;
        }
        g.offset = offset;
        g.swipeMove(offset);
      },

      // 結(jié)束滑動(dòng)
      endDrag() {
        let g = this;

        if (!g.enable || g.isToggle || !g.dragging) {
          return false;
        }

        const tempWidth = g.drawerWidth / 3;

        if (g.isDO && g.offset < tempWidth * 2) {
          g.isDO = false;
        } else if (!g.isDO && g.offset > tempWidth) {
          g.isDO = true;
        }
        g.dragging = false;

        g.swipeLeaveTransition();
      }

好啦,到這應(yīng)該就差不多了。。。
里邊涉及到的v-tap指令是自定義的指令,為了處理移動(dòng)端的點(diǎn)擊操作,我還整理了一片陋文:https://segmentfault.com/a/11... (移動(dòng)點(diǎn)擊長(zhǎng)按滑動(dòng)vue指令)

然后這個(gè)組件的源碼我放在了我fork出來(lái)的mintUI項(xiàng)目上
https://github.com/LylaYuKako...

謝謝各位品嘗,

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94272.html

相關(guān)文章

  • 基于React的仿QQ音樂(lè)(移動(dòng)

    摘要:學(xué)習(xí)成本很低,另外官方有比較完善的中文文檔。簡(jiǎn)單本身是沒(méi)有錯(cuò)誤,一個(gè)東西能以簡(jiǎn)單的方式解決難道不好嗎關(guān)于這個(gè)中文文檔居然還有人噴那些喜歡用的是不是英文能力差,我就再報(bào)以呵呵一笑。本身?yè)碛兄形奈臋n就是一個(gè)優(yōu)勢(shì),結(jié)果還成了被噴的地方。 前言 由于這段時(shí)間工作上也是挺忙的,就沒(méi)有時(shí)間去寫這個(gè)項(xiàng)目,中間一直都是寫寫停停,進(jìn)度也是非常慢的。正好前幾天都還比較空,就趕緊抓著空閑時(shí)間去寫這個(gè)項(xiàng)目,最...

    xiaodao 評(píng)論0 收藏0
  • 匠心打造Vue側(cè)滑菜單組件

    摘要:本文介紹一個(gè)簡(jiǎn)單的類似的布局組件的實(shí)現(xiàn),基于。介紹的內(nèi)容已經(jīng)制作成組件。即當(dāng)不可以拖出抽屜時(shí),應(yīng)觸發(fā)默認(rèn)事件,比如垂直方向的滾動(dòng)等等。這種優(yōu)化可以將一部分復(fù)雜的計(jì)算工作提前準(zhǔn)備好,使頁(yè)面的反應(yīng)更為快速靈敏。 本文介紹一個(gè)簡(jiǎn)單的DrawerLayout(類似Android的DrawerLayout)布局組件的實(shí)現(xiàn),基于Vue.js。介紹的內(nèi)容已經(jīng)制作成 vue-drawer-layout...

    sutaking 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<