天天看點

bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

這篇文章主要介紹了微信小程式自定義月曆元件及flex布局最後一行對齊問題,本文通過執行個體代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

最近為我開源的小項目:微信小程式擴充自定義元件庫(點選去GitHub) 增加了一個新元件 —— 月曆元件。

效果示範:

bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

在編寫過程中,因為大家都知道,月曆元件是有固定行數和每一行的固定列數的(即使目前方塊内沒有值),是以結合小程式“資料優先”的特點,最合适的布局方式一定是flex了!

先說一下大緻思路(布局上),筆者将整個元件分為兩部分:分别是

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

頭部的布局自不多說:一個

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}}">
   			{{}}
   		</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,發現:

bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

可以看到:控制每一行的類是 “calendar_box”,那麼毫無疑問,導緻出現如圖原因肯定是此類中有這樣一行代碼:

justify-content: space-around;
           

果不其然!

在本項目中,我的解決方法很簡單:将這一行代碼去掉,那麼由此導緻的寬高問題怎麼解決?

這個問題,css給出了解決方案——

calc()

我将“每一行”的高度設為外部view的1/6:

height:calc(100% / 6)

(因為這是個元件,要用到其他地方,外部元素寬高不一定,是以要用百分比),每一行中列的寬度設為整行寬度的1/7:

width:calc(100% / 7)

根據CSS文檔流的特點,這些元素在一行中就會一個接一個的排列,賊好看的那種~(去這裡)

答疑:

文章發出後有人留言問“為啥不全部設定calc(100% / 6)然後用flex換行?”,emmmmmmm沒這個必要吧,這不是看個人喜好嗎,嘿嘿。先不說這裡我是采用的“周幾和日期父元素同一個class,在裡面隻控制和‘整行'相關的屬性值”的政策;其實這裡也是一個語義化:一周有七個日期,那一行就放七個元素,之間互不影響 —— 你如果去GitHub看源碼的話就會發現:在JS渲染日期時我就有意将每一行之間(也就是每一周)“隔離操作、單獨渲染”。

當然,你也可以如代碼中判斷index==0(第一行)一樣去判斷:

style="{{index==5?'justify-content:flex-start':''}}"
           

不過就顯得有點“多此一舉”了。

有了calc等css3函數的“加盟”,可以預見這種純‘原生'的解決方式将會越來越多的被使用到各種場景。
bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

剛才說了,這個案例中的行列數是固定的 —— 這并不少見!那麼,除了本文提出的解決方法,還能怎麼做?

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

我們都知道,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;
}
{
  min-width:100px;
  margin: 0 10px;
}
           

這個方法和下一個問題的第一種方法類似,但要簡單很多!

警告!

經過有讀者留言提醒,這種方法确實不準确(感謝@李奕威(微信使用者)),當時筆者測試的時候沒有考慮到所有情況而且測試用class為list的div的個數有些取巧造成了這一現象。後經過多次測試發現:這種方法受min-width的影響在一些特殊情況下可行(比如:list個數為7且一行最多四個(每行列數可小于4)時是可以的,但這種規律不是絕對的) —— 如果不是flex,它将會呈現和為最後一個元素添加“margin-right:auto”一樣的效果!

是以,建議跳過這種方法,我會再探索其相關實踐應用。

根據個數最後一個元素動态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;
}
           

答疑:

我看到文章發出後有人留言問“如果像這種子產品分布,但列數不固定且是根據可視化視窗變化決定一列放多少個,但是要每個方塊的間距都是一樣的”?這種問題其實很簡單:上面這個用grid布局的代碼如果将

justify-content: space-between;

換為

justify-content: space-around;

就可以了。。。(雖然也會有間距變化,但是在可接受範圍,‘空白'不會顯得突兀)

現在的問題是因為“space-between”是按照“最兩側的貼近父容器邊緣”的方法排版的,也就是說類似“兩邊的兩個貼着邊,剩下的幾個瓜分中間的空間,每往裡一層還是按這樣的方式”,也就造成了響應式變化時由于一行内個數變化中間會有一大片空白的效果。

最後再介紹一下這個元件:它在調用時接收兩個參數——他們是兩個event函數,你需要監聽他們,你可以得到:剛顯示元件時的目前日期/星期幾和你點選選中日期時選中的年月日和星期幾

bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

2020-09-28更新

你可以在調用元件時傳入一個數組參數 dateTimes ,它的作用:标記哪一天的事件。它的格式如:

bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

他将顯示如下:

bootstraptable 添加一行 demo_淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題_javascript技巧

結尾:

以後可能為元件增加什麼功能就把布局方式更新了,到時候再回來補。

到此這篇關于淺析微信小程式自定義月曆元件及flex布局最後一行對齊問題的文章就介紹到這了,更多相關小程式自定義月曆元件flex布局内容請搜尋腳本之家以前的文章或繼續浏覽下面的相關文章希望大家以後多多支援腳本之家!

繼續閱讀