微信小程序自定義日曆組件及flex佈局最後一行對齊問題分析


本文爲做者行舟客投稿,原文地址:css

https://yunxiaomeng.blog.csdn.net/article/details/108821829html

 歡迎點贊!前端




背景

最近爲我開源的小項目:微信小程序擴展自定義組件庫(點擊去GitHub) 增長了一個新組件 —— 日曆組件。css3

正文

在編寫過程當中,由於你們都知道,日曆組件是有固定行數和每一行的固定列數的(即便當前方塊內沒有值),因此結合小程序「數據優先」的特色,最合適的佈局方式必定是flex了!小程序

說一下大體思路(佈局上),筆者將整個組件分爲兩部分:分別是微信小程序

  1. 頭部的當前日期(年月)顯示,以及左右兩側的切換按鈕
  2. 當前切換月份的日期顯示

頭部的佈局自很少說:一個 display:flex; 加上 align-items:center; 居中簡直完美。底部的日期顯示我是採用的「將總體分爲六行,每一行七列」的佈局方式 —— 由於一個月最多31天,每一週最多7天,6X7=42,行數六行足夠使用。(並且如今基本上日曆都是6行7列的)微信

這樣的話我就給每一行設置相同的class,讓其再用flex規範子元素(子組件):ide

<view class="calendar_panel calendar_panel_two">
    <view class="calendar_box">
     <view class="weekday_label"></view>
     <view class="weekday_label"></view>
     <view class="weekday_label"></view>
     <view class="weekday_label"></view>
     <view class="weekday_label"></view>
     <view class="weekday_label"></view>
     <view class="weekday_label"></view>
    </view>

    <view class="calendar_box" wx:for="{{dateList}}" wx:for-item="week" style="{{index==0?'justify-content:flex-end':''}}">
       <view class="weekday_label {{(item.value==selectedDate)?'active_date':''}} {{(item.value==now_selectedDate)?'active_dates':''}}" wx:for="{{week}}">
        <view class="" bindtap="selectDate" data-date="{{item}}">
         {{item.date}}
        </view>
       </view>
    </view>

</view>

(代碼中倒數第7、八行的判斷是檢驗是不是當前日期(now_selectedDate)或選中日期(selectedDate),爲其加特殊效果,對佈局不形成影響)函數

.calendar_panel{
    width100%;
    heightcalc(100% - 56rpx);
}
.calendar_panel_two{
    display: flex;
    flex-direction: column;
    justify-content: space-around;
}
.calendar_box{
    width100%;
    background#fff;
    overflow: hidden;
    display: flex;
    justify-content: space-around;
    heightcalc(100% / 6);
    align-items: center;
}
.weekday_label{
    font-size27rpx;
    padding12rpx 0;
    display: flex;
    align-items: center;
    overflow: hidden;
}
.weekday_label>view{
    box-sizing: border-box;
    padding20%;
}
.select_icon{
    width30rpx;
    height30rpx;
}
.active_date{
    backgroundrgba(0,0,0,.12);
    colorrgba(0,0,0,.6);
    overflow: hidden;
    position: relative;
}
.active_dates{
    backgroundrgba(0,0,0,.1);
    colorrgba(0,0,0,.5);
    position: relative;
}
.active_dates::before{
    content"今天";
    position: absolute;
    top0;
    left50%;
    transformtranslateX(-50%);
    color: blue;
    font-size20rpx;
}

佈局方完成,我滿心歡喜的按下ctrl+s,發現:image.png佈局

能夠看到:控制每一行的類是 「calendar_box」,那麼毫無疑問,致使出現如圖緣由確定是此類中有這樣一行代碼:

justify-contentspace-around;

果不其然!


在本項目中,個人解決方法很簡單:將這一行代碼去掉,那麼由此致使的寬高問題怎麼解決?這個問題,css給出瞭解決方案—— calc() !我將「每一行」的高度設爲外部view的1/6:height:calc(100% / 6) ,每一行中列的寬度設爲整行寬度的1/7:width:calc(100% / 7)根據CSS文檔流的特色,這些元素就會一個接一個的排列,賊好看的那種~(去這裏)

有了calc等css3函數的「加盟」,能夠預見這種純‘原生’的解決方式將會愈來愈多的被使用到各類場景。

image.pngsucess

剛纔說了,這個案例中的行列數是固定的 —— 這並很多見!那麼,除了本文提出的解決方法,還能怎麼作?

動態改變最後一個元素的寬度

咱們都知道,flex佈局中還有一個比較著名的概念就是 flex: 1; (flex: auto;)了,他能動態「填滿」剩餘空間,那麼咱們再子元素同級位置再加一個元素,對他設置最小寬度爲子元素相同寬度,而且margin和子元素一致:

<div class="container">
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <i class="lists"></i>
</div>
.container {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
}
.list {
    width:100px;
    height:100px;
    background-color: skyblue;
    margin10px;
}
i.lists{
   min-width:100px;
   margin10px;
}

這個方法和下一個問題的第一種方法相似,但要簡單不少!

根據個數最後一個元素動態margin

簡單來講就是:單獨設置最後一行的最後一個元素,控制其margin-right 因爲每一列的數目都是固定的,所以,咱們能夠計算出不一樣個數列表應當多大的margin值才能保證徹底左對齊。例如,假設每行4個元素,結果最後一行只有3個元素,則最後一個元素的margin-right大小是「列表寬度+間隙大小」的話,那最後3個元素也是能夠完美左對齊的。而後,藉助樹結構僞類數量匹配技術,咱們能夠知道最後一行有幾個元素。例如:

  1. .list:last-child:nth-child(4n - 1)說明最後一行,要麼3個元素,要麼7個元素……
  2. .list:last-child:nth-child(4n - 2)說明最後一行,要麼2個元素,要麼6個元素……
.container {
    display: flex;
    /* 兩端對齊 */
    justify-content: space-between;
    flex-wrap: wrap;
}
.list {
    width24%height100px;
    background-color: skyblue;
    margin-top15px;
}
/* 若是最後一行是3個元素 */
.list:last-child:nth-child(4n - 1) {
    margin-rightcalc(24% + 4% / 3);
}
/* 若是最後一行是2個元素 */
.list:last-child:nth-child(4n - 2) {
    margin-rightcalc(48% + 8% / 3);
}

那麼,若是每一行的列數是不固定的呢?

這個問題的解法有不少種,其中筆者最「推崇」的是——用空白元素佔位!使用足夠的空白標籤進行填充佔位:具體的佔位數量是由最多列數的個數決定的,例如這個佈局最多7列,那咱們可使用7個空白標籤進行填充佔位,最多10列,那咱們須要使用10個空白標籤。

<div class="container">
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <i></i><i></i><i></i><i></i><i></i>
</div>

這種方法的缺點(同時也是優勢)就是:佔位的 <i> 元素寬度和margin設置必須和列表父元素同樣便可!

.container {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    margin-right: -10px;
}
.container .list {
    width100px
    height:100px;
    background-color: skyblue;
    margin15px 10px 0 0;
}
/* 和列表同樣的寬度和margin值 */
.container > i {
    width100px;
    margin-right10px;
}

這裏要左對齊,則設置i的margin-right;一樣的若是右對齊,則需設置margin-left。

還有一種目前被不少人接受的方法就是曾經風靡的grid佈局—— 它有自然的單側對其和方塊間隙,對熟悉grid的人來講,本文這個問題幾乎不會出現:

/** html代碼 */
<div class="container">
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
</div>

/** CSS代碼 */
.container {
    display: grid;
    justify-content: space-between;
    grid-template-columnsrepeat(auto-fill, 100px);
    grid-gap10px;
}
.list {
    width100px
    height:100px;
    background-color: skyblue;
    margin-top5px;
}

最後再介紹一下這個組件:它在調用時接收兩個參數——他們是兩個event函數,你須要監聽他們,你能夠獲得:剛顯示組件時的當前日期/星期幾和你點擊選中日期時選中的年月日和星期幾image.png


結尾

之後可能爲組件增長什麼功能就把佈局方式更新了,到時候再回來補。

臨近國慶學校沒啥課,電腦放工做室沒帶回,室友電腦有點不會用,就到這吧。祝各位中秋&國慶快樂,嘿嘿!


最後

  • 歡迎加我微信(winty230),拉你進技術羣,長期交流學習...

  • 歡迎關注「前端Q」,認真學前端,作個專業的技術人...

image.png

相關文章
相關標籤/搜索