最近為我開源的小專案:微信小程式擴展自定義組件庫(點擊去GitHub) 增加了一個新組件 —— 日歷組件,
在撰寫程序中,因為大家都知道,日歷組件是有固定行數和每一行的固定列數的(即使當前方塊內沒有值),所以結合小程式“資料優先”的特點,最合適的布局方式一定是flex了!
先說一下大致思路(布局上),筆者將整個組件分為兩部分:分別是
- 頭部的當前日期(年月)顯示,以及左右兩側的切換按鈕
- 當前切換月份的日期顯示
頭部的布局自不多說:一個 display:flex; 加上 align-items:center; 居中簡直完美,
底部的日期顯示我是采用的“將整體分為六行,每一行七列”的布局方式 —— 因為一個月最多31天,每一周最多7天,6X7=42,行數六行足夠使用,(而且現在基本上日歷都是6行7列的)
這樣的話我就給每一行設定相同的class,讓其再用flex規范子元素(子組件):
<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 wx:for="{{week}}">
<view class="" bindtap="selectDate" data-date="{{item}}">
{{item.date}}
</view>
</view>
</view>
</view>
.calendar_panel{
width: 100%;
height: calc(100% - 56rpx);
}
.calendar_panel_two{
display: flex;
flex-direction: column;
justify-content: space-around;
}
.calendar_box{
width: 100%;
background: #fff;
overflow: hidden;
display: flex;
justify-content: space-around;
height: calc(100% / 6);
align-items: center;
}
.weekday_label{
font-size: 27rpx;
padding: 12rpx 0;
display: flex;
align-items: center;
overflow: hidden;
}
.weekday_label>view{
box-sizing: border-box;
padding: 20%;
}
.select_icon{
width: 30rpx;
height: 30rpx;
}
.active_date{
background: rgba(0,0,0,.12);
color: rgba(0,0,0,.6);
overflow: hidden;
position: relative;
}
.active_dates{
background: rgba(0,0,0,.1);
color: rgba(0,0,0,.5);
position: relative;
}
.active_dates::before{
content: "今天";
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
color: blue;
font-size: 20rpx;
}
布局方完成,我滿心歡喜的按下ctrl+s,發現:

可以看到:控制每一行的類是 “calendar_box”,那么毫無疑問,導致出現如圖原因肯定是此類中有這樣一行代碼:
justify-content: space-around;
果不其然!
在本專案中,我的解決方法很簡單:將這一行代碼去掉,那么由此導致的寬高問題怎么解決?
這個問題,css給出了解決方案—— calc() !
我將“每一行”的高度設為外部view的1/6:height:calc(100% / 6) (因為這是個組件,要用到其他地方,外部元素寬高不一定,所以要用百分比),每一行中列的寬度設為整行寬度的1/7:width:calc(100% / 7)
根據CSS檔案流的特點,這些元素在一行中就會一個接一個的排列,賊好看的那種~(去這里)
當然,你也可以如代碼中判斷index==0(第一行)一樣去判斷:
style="{{index==5?'justify-content:flex-start':''}}"
不過就顯得有點“多此一舉”了,
有了calc等css3函式的“加盟”,可以預見這種純‘原生’的解決方式將會越來越多的被使用到各種場景,

剛才說了,這個案例中的行列數是固定的 —— 這并不少見!那么,除了本文提出的解決方法,還能怎么做?
動態改變最后一個元素的寬度
我們都知道,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;
margin: 10px;
}
i.lists{
min-width:100px;
margin: 0 10px;
}
這個方法和下一個問題的第一種方法類似,但要簡單很多!
根據個數最后一個元素動態margin
簡單來說就是:單獨設定最后一行的最后一個元素,控制其margin-right
由于每一列的數目都是固定的,因此,我們可以計算出不同個數串列應當多大的margin值才能保證完全左對齊,
例如,假設每行4個元素,結果最后一行只有3個元素,則最后一個元素的margin-right大小是“串列寬度+間隙大小”的話,那最后3個元素也是可以完美左對齊的,
然后,借助樹結構偽類數量匹配技術,我們可以知道最后一行有幾個元素,
例如:
- .list:last-child:nth-child(4n - 1)說明最后一行,要么3個元素,要么7個元素……
- .list:last-child:nth-child(4n - 2)說明最后一行,要么2個元素,要么6個元素……
.container {
display: flex;
/* 兩端對齊 */
justify-content: space-between;
flex-wrap: wrap;
}
.list {
width: 24%; height: 100px;
background-color: skyblue;
margin-top: 15px;
}
/* 如果最后一行是3個元素 */
.list:last-child:nth-child(4n - 1) {
margin-right: calc(24% + 4% / 3);
}
/* 如果最后一行是2個元素 */
.list:last-child:nth-child(4n - 2) {
margin-right: calc(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 {
width: 100px;
height:100px;
background-color: skyblue;
margin: 15px 10px 0 0;
}
/* 和串列一樣的寬度和margin值 */
.container > i {
width: 100px;
margin-right: 10px;
}
這里要左對齊,則設定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-columns: repeat(auto-fill, 100px);
grid-gap: 10px;
}
.list {
width: 100px;
height:100px;
background-color: skyblue;
margin-top: 5px;
}
最后再介紹一下這個組件:它在呼叫時接收兩個引數——他們是兩個event函式,你需要監聽他們,你可以得到:剛顯示組件時的當前日期/星期幾和你點擊選中日期時選中的年月日和星期幾

2020-09-28更新
你可以在呼叫組件時傳入一個陣列引數 dateTimes ,它的作用:標記哪一天的事件,它的格式:

他將顯示如下:

結尾:
以后可能為組件增加什么功能就把布局方式更新了,到時候再回來補,
臨近國慶學校沒啥課,電腦放作業室沒帶回,室友電腦有點不會用,就到這吧,中秋&國慶快樂,嘿嘿!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/143333.html
標籤:java
上一篇:組件的設計原理
下一篇:MSComm控制元件問題
