フレックスカレンダーの入力

2018年、ファッショナブルな少年たちが長い間グリッド上で組版を行ってきました。私は3番目のブートストラップに座って、 col-mdカーリングを行い、4番目の瞬間を少し見ています。







私はこれは事実ではないと判断し、更新するのに少し知識が必要ですが、 グリッドはまだ足りないようですが、 フレックステクノロジーはすでにアイロンをサポートしています。







だから私はそれをマスターすることにしました。 そして同化のプロセスはあなたと共有します。 一般的に、年間を通してカレンダーを課します。







必要になります









結果は次のようになります。













私はvueの支持者であるため、レンダリングに使用します。 モーメントライブラリを使用して日付を操作しますが、日付ライブラリなしでも実行できますが、より詳しく知っています。







準備する



vue-cliをまだインストールしていない場合はインストールします。







npm install -g vue-cli
      
      





webpack-simpleテンプレートに基づいてプロジェクトを作成します。scss (主にコメント用)を使用します。







 ? Use sass? (y/N)
      
      





y(es)と答え、一般に、実行します:







 vue-init webpack-simple calendar_flex cd calendar_flex npm install
      
      





moment.jsライブラリを追加します







 npm install -S moment
      
      





ファイルApp.vueを消去します







 <template> </template> <script> export default { name: 'app', data () { return { } } } </script> <style> </style>
      
      





野b人のように見えないようにするために、私たちはむき出しのカレンダーを課すだけでなく、別のコンポーネントを開発します。







Calendar.vueファイルを作成します。







 <template> <div></div> </template> <style lang="scss" scoped> </style> <script> export default { props: { year: { //      type: Number, default: (new Date()).getFullYear() }, }, data () { return {} } } </script>
      
      





main.jsでコンポーネントをグローバルに接続します







 import Vue from 'vue' import App from './App.vue' import Calendar from './Calendar.vue' Vue.component("calendar", Calendar); new Vue({ el: '#app', render: h => h(App) })
      
      





App.vueにコンポーネントを追加します







 <template> <calendar></calendar> </template> ...
      
      





すべてが正しく行われると、白い背景に「カレンダー」という単語が表示されます。







データの準備



何かを描画する前に、カレンダーのデータを準備する必要があります。 その年のデータを月の配列にプッシュすることを提案します。 同様に、各月は次の形式のオブジェクトになります。







 { title: '', weeks: {1: {}, 2: {}, ...} }
      
      





月の名前と週の配列を意味します。 毎週は、日付が毎日(1から7まで)添付されるオブジェクトであり、他のメタ情報も含まれます。







 week = { 1: {date: new Date(), ...}, //  2: {date: new Date(), ...}, //  ... }
      
      





Calendar.vueファイルに切り替えて、スクリプトを担当する部分を更新します。







 import moment from 'moment'; export default { ... computed: { yearData() { let data = []; for (let m = 0; m < 12; ++m) { //        let day = moment({year: this.year, month: m, day: 1}); let daysInMonth = day.daysInMonth(); //     let month = { //    title: day.format("MMMM"), weeks: {}, }; //       for (let d = 0; d < daysInMonth; ++d) { let week = day.week(); //  ,   //      , //       53 if (m === 11 && week === 1) { week = 53 } //       ,    if (!month.weeks.hasOwnProperty(week)) { month.weeks[week] = {} } //  ,  weekday()   , //   ,    , //     month.weeks[week][day.weekday() + 1] = { date: day.toDate(), }; //    , moment    day.add(1, 'd'); } //       data.push(month); } return data } } ... }
      
      





vue-devtoolsを調べて、そこを見ることができます:













組版



さて、すでに何かを手に入れましょう。 最初に、1か月を構成する方法を学習し、それに慣れると、他のすべてを表示します。 一般に、 Calendar.vueテンプレートを編集します







 <template> <div class="month"> <div class="title">{{yearData[0].title}}</div> <div class="week" v-for="week in yearData[0].weeks"> <div class="day" v-for="day in 7"> <span v-if="week[day]">{{week[day].date.getDate()}}</span> </div> </div> </div> </template>
      
      





まず、週の日付を一列に表示します。これにより、スタイルを修正します。







 <style lang="scss" scoped> .week { display: flex; } </style>
      
      











ここで、毎日、同じ行のスペースを占有する必要があることを示します。







 <style lang="scss" scoped> .week { display: flex; } .day { flex-grow: 1; } </style>
      
      











まあ、それはもっとまともなようで、数字だけがジャンプします。 これは、 flex-growが本質的に空のスペースを分配し、数字のテキストがこの空のスペースに含まれていないために発生します。したがって、数字のセルが本当に等しくなるためには、スタイルでテキストの幅を考慮しないように指定する必要があります。 これを行うには、 flex-basisプロパティをゼロに設定します。







私が言っていることが明確でない場合は、この写真を勉強してみてください:







画像







まあどう? スタイルを編集します。







 <style lang="scss" scoped> .week { display: flex; } .day { flex-grow: 1; flex-basis: 0; } </style>
      
      





今から美人













これで、すべての月を表示し、テンプレートを編集する準備ができたと思います。







 <template> <div class="year"> <div class="month" v-for="month in yearData"> <div class="title">{{month.title}}</div> <div class="week" v-for="week in month.weeks"> <div class="day" v-for="day in 7"> <span v-if="week[day]">{{week[day].date.getDate()}}</span> </div> </div> </div> </div> </template>
      
      





さて、すでに一種のレスポンシブカレンダーがあります。













しかし、これでは十分ではありません。祖父がdivに遺贈されたように、カレンダーは列に表示され、並べる必要があります...類推してみましょう。 彼女の日のために、 フレックスコンテナを毎週割り当てました。 そして、 今月はフレックスコンテナに年ブロックを割り当てます。 スタイルを追加します。







 <style lang="scss" scoped> .week {...} .day {...} .year { display: flex; } .month { flex-grow: 1; flex-basis: 0; } </style>
      
      





さらに、ある種のおpor:













この混乱の理由は、デフォルトではflexはハイフネーションを行わず、すべてを1行で表示しようとするため、十分な力があるが十分ではない限り圧縮するためです。 ハイフネーションモードを有効にするには、年コンテナにflex-wrapプロパティを追加する必要があります。これを実行します。







 <style lang="scss" scoped> .week {...} .day {...} .year { display: flex; flex-wrap: wrap; //  } .month {...} </style>
      
      





まあ、ええと...それは転送されますが、良くなりました:













ここでは空気は十分ではありませんが、ところで私たちにとってはさらに興味深いものです。 明らかに、11月と12月は最高の気分になりますが、平等であるため、目立たないように絞りましょう。







縮小するには、月からflex-grow:1を削除する必要があります(現在が追加され、現在は削除されています...)。







 <style lang="scss" scoped> ... .month { flex-basis: 0; } </style>
      
      











コンテナのスタイルのJustify-contentは、最後の2つ(実際にはそれらだけではない)のハング要素の配置方法を担当します。デフォルトではflex-startです。 端に揃えることができます。







 <style lang="scss" scoped> .week {...} .day {...} .year { display: flex; flex-wrap: wrap; justify-content: flex-end; //    } .month {...} </style>
      
      





異なる意味を持つgifを次に示します。













常に同じ月数を連続して使用し、それらにすべての空き領域を占有させることを計画しているため、おそらくflex-grow:1を返します。 戻って、空気を追加します。







 <style lang="scss" scoped> .week {...} .day { margin: 0.25em; //  flex-grow: 1; flex-basis: 0; } .year { display: flex; flex-wrap: wrap; } .month { margin: 0.25em; //  flex-basis: 0; flex-grow: 1; //   } </style>
      
      





美しさ:













もう一度、 justify-contentflex-growに戻ります:1 。 最初の月にflex-grow = 1、2番目に2つのgifを比較します-プロパティがありません:



















あなたが好むオプションは、あなた自身で決めてください。







曜日を含む行を追加します。 最初に計算プロパティをスクリプトに追加します







  export default { ... computed: { weekDays () { //   let days = []; for(let i = 1; i<=7;++i) { days.push(moment().isoWeekday(i).format("dd")) } return days; }, ... } }
      
      





そして、テンプレートに表示します:







 <template> <div class="year"> <div class="month" v-for="month in yearData"> <div class="title">{{month.title}}</div> <div class="week"> <div class="day" v-for="d in weekDays"> <span>{{d}}</span> </div> </div> <div class="week" v-for="week in month.weeks"> <div class="day" v-for="day in 7"> <span v-if="week[day]">{{week[day].date.getDate()}}</span> </div> </div> </div> </div> </template>
      
      











日曜日を赤にしたいので、動的なスタイルを.dayノードに追加しましょう。







 <template> <div class="year"> <div class="month" v-for="month in yearData"> ... <div class="week" v-for="week in month.weeks"> <div class="day" v-for="day in 7" :class="{[`week-day-${day}`]: true}"> <span v-if="week[day]">{{week[day].date.getDate()}}</span> </div> </div> </div> </div> </template>
      
      





そして今、スタイルを修正し、ちょっとした美しさを提案します。







 <style lang="scss" scoped> .title { //      margin: 0.25em; font-weight: bold; } .week-day-7 { //  color: red; } ... </style>
      
      











さて、最後の仕上げ:年を変更する機能を追加し、 flexを使用して固定ヘッダーを作成します。







App.vueファイルに切り替えて、テンプレートを調整します。







 <template> <div class="wrapper"> <div class="content"> <div class="header"> <div class="title">{{year}}</div> </div> <div class="body"> <calendar :year="year"></calendar> </div> </div> </div> </template>
      
      





あなたが見ることができるように、修正されていない間、年で行を追加しました:













App.vueでスタイルを調整し、 ボディのインデントを削除し、 htmlbodyの高さをウィンドウ全体の高さに設定し、タイトルをよりカラフルにします。2つのスタイルノードを使用します。1つはグローバルスタイル用、もう1つはローカルスタイル用です:







 <style lang="scss"> html { height: 100%; } body { height: 100%; margin: 0; } </style> <style lang="scss" scoped> .title { font-weight: bold; font-size: 1.5em; margin: 0.25em; text-align: center; } </style>
      
      





flexで固定ヘッダーを作成するという考え方は、2つのネストされたflexコンテナを使用することです。1つはすべてのコンテンツの高さを制限し、2番目はネストされたflex-direction:columnを使用します







スタイルを編集します。







 <style lang="scss" scoped> .title {...} .wrapper { //   display: flex; height: 100%; //        ,    '  body } .content { //       display: flex; flex-direction: column; } .body { //    flex-grow: 1; // ,     overflow-y: auto; // ,    } </style>
      
      











かっこいい? フッターを作成することもできます。







 <template> <div class="wrapper"> <div class="content"> <div class="header"> <div class="title">{{year}}</div> </div> <div class="body"> <calendar :year="year"></calendar> </div> <div class="header"> <div class="title">{{year}}</div> </div> </div> </div> </template>
      
      











さて、年を切り替えるためのボタンを追加しましょう。







 <template> <div class="wrapper"> <div class="content"> <div class="header"> <button @click="--year">&lt;</button> <div class="title">{{year}}</div> <button @click="++year">&gt;</button> </div> <div class="body"> <calendar :year="year"></calendar> </div> <div class="header"> <div class="title">{{year}}</div> </div> </div> </div> </template>
      
      











すでに得た知識を使用して、ヘッダーをよりフレックスのようにし、スタイルを編集します。







 <style lang="scss" scoped> .title {...} .header { padding: 0.25em; display: flex; justify-content: space-between; } .wrapper {...} .content {...} .body {...} </style>
      
      











うーん...ここで何かが間違っています。 私たちの見出しさえも直接絞られ、レイアウトは浮いていました。 残念ながら、これは私がこれがなぜ起こったか完全に理解しなかった瞬間です。 しかし、私が推測するように、これはdisplay:flexが動的な高さを設定し、別のflexコンテナ内にあり、親によって設定されたサイズに焦点を合わせているという事実によるものです。







一般に、これを解決するには、ヘッダーが配置されているコンテナへのflexを禁止して、その寸法を圧縮する必要があります。このため、 flex-shrinkプロパティを追加します。







 <style lang="scss" scoped> .title {...} .header { padding: 0.25em; display: flex; flex-shrink: 0; //    justify-content: space-between; } .wrapper {...} .content {...} .body {...} </style>
      
      





さて、これですべての年のフレックスカレンダーができました!













この記事ではflexのすべての可能性を示すことはできませんでしたが、それを扱うための一般的なアプローチを反映していると思いました。







この記事が、私のように、3回目と4回目のブートストラップの間にcssの時間に閉じ込められている人たちが、現代のcssに向けて最初の一歩を踏み出すのに役立つことを願っています。







サンプルコードはで入手できます








All Articles