Rumah > hujung hadapan web > View.js > teks badan

Analisis mendalam tentang cara merangkum komponen kalendar tersuai vue

藏色散人
Lepaskan: 2023-04-06 15:12:40
ke hadapan
2243 orang telah melayarinya

Artikel ini membawakan anda pengetahuan yang berkaitan tentang kalendar bahagian hadapan terutamanya tentang cara merangkum komponen kalendar tersuai. Saya harap ia dapat membantu semua orang.

Kata Pengantar

Seperti yang kita semua tahu, secara amnya, jika terdapat keperluan untuk menggunakan komponen kalendar dalam projek, mereka sering menggunakan komponen daripada perpustakaan UI pihak ketiga, atau mencari komponen siap pakai yang lain. Bagi ramai rakan, apabila mereka mula-mula melihat komponen kalendar, mereka secara tidak sedar menganggapnya sangat rumit dan tidak mempunyai cara untuk memulakannya. Tetapi apabila saya membaca kod sumber pemalam kalendar ini, saya dapati ia tidaklah serumit yang saya fikirkan. Saya pernah berfikir secara bodoh bahawa jika saya ingin membuat komponen kalendar, saya perlu mendapatkan data kalendar untuk sekurang-kurangnya sepuluh tahun sebelum dan selepas tahun semasa sebelum meneruskan langkah pembangunan seterusnya.

Namun, selepas saya cuba membaca kod sumber perpustakaan dycalendar.js, di satu pihak, saya rasa saya terlalu bodoh dan memikirkan masalah itu terlalu rumit. Saya juga mengagumi pemikiran jernih penulis. Selepas membacanya, saya merasakan bahawa saya mendapat banyak manfaat.

Selepas menyusun logik idea pengarang, saya membangunkan komponen vue berdasarkan idea ini. Seperti yang ditunjukkan dalam gambar di bawah:

Analisis mendalam tentang cara merangkum komponen kalendar tersuai vue

Seterusnya, ikuti saya untuk melihat cara membangunkan komponen kalendar anda sendiri.

Pelaksanaan kod teras

1 Isih idea

  • Dapatkan data tarikh sasaran
  • Dapatkan atribut penting tarikh semasa, seperti 当前年, 当前月, 当前日期, 当前星期几, 当前月一共有几天, 当前月的第一天对应的是星期几, 上个月总共有多少天, dsb.
  • menjana 日历日期数据列表 khusus berdasarkan atribut ini, dan kemudian memaparkannya ke dalam templat dalam gelung.
  • Apabila bertukar bulan, dapatkan pelbagai data penting yang sepadan dengan tarikh sasaran baharu. Selepas vue mengesan perubahan dalam atribut kalendar, halaman pemberitahuan dikemas kini.

2. Data diperlukan untuk permulaan

Secara umumnya, dalam komponen kalendar matang, tarikh ialah pembolehubah terikat dua hala. Untuk kemudahan penggunaan, kami juga menggunakan pengikatan dua hala.

<script setup>
import { reactive, ref, computed, watch } from "vue";

const props = defineProps({
  modelValue: Date,
});

const emits = defineEmits(["update:modelValue"]);

/**
 * 最小年份
 */
const MIN_YEAR = 1900;
/**
 * 最大年份
 */
const MAX_YEAR = 9999;

/**
 * 目标日期
 */
const targetDate = ref(props.modelValue);
Salin selepas log masuk

Seterusnya, kita juga perlu memulakan beberapa pemalar untuk mewakili bulan dan tarikh:

/**
 * 有关月度的名称列表
 */
const monthNameList = {
  chineseFullName: [
    "一月",
    "二月",
    "三月",
    "四月",
    "五月",
    "六月",
    "七月",
    "八月",
    "九月",
    "十月",
    "十一月",
    "十二月",
  ],
  fullName: [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December",
  ],
  mmm: [
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
  ],
};
/**
 * 有关周几的名称列表
 */
const dayNameList = [
  {
    chineseFullName: "周日",
    chineseShortName: "日",
    fullName: "Sunday",
    shortName: "Sun",
    dayNumber: 0,
  },
  {
    chineseFullName: "周一",
    chineseShortName: "一",
    fullName: "Monday",
    shortName: "Mon",
    dayNumber: 1,
  },
  {
    chineseFullName: "周二",
    chineseShortName: "二",
    fullName: "Tuesday",
    shortName: "Tue",
    dayNumber: 2,
  },
  {
    chineseFullName: "周三",
    chineseShortName: "三",
    fullName: "Wednesday",
    shortName: "Wed",
    dayNumber: 3,
  },
  {
    chineseFullName: "周四",
    chineseShortName: "四",
    fullName: "Thursday",
    shortName: "Thu",
    dayNumber: 4,
  },
  {
    chineseFullName: "周五",
    chineseShortName: "五",
    fullName: "Friday",
    shortName: "Fri",
    dayNumber: 5,
  },
  {
    chineseFullName: "周六",
    chineseShortName: "六",
    fullName: "Saturday",
    shortName: "Sat",
    dayNumber: 6,
  },
];
Salin selepas log masuk

Seterusnya, sediakan beberapa data responsif untuk Vue:

/**
 * 今日
 */
const today = new Date();

/**
 * 日历的各项属性
 */
const calendarProps = reactive({
  target: {
    year: null,
    month: null,
    date: null,
    day: null,
    monthShortName: null,
    monthFullName: null,
    monthChineseFullName: null,
    firstDay: null,
    firstDayIndex: null,
    totalDays: null,
  },
  previous: {
    totalDays: null,
  },
});

/**
 * 用于展现的日历数据
 */
const calendarData = ref([]);
Salin selepas log masuk

3. Mulakan atribut kalendar

Seterusnya, dapatkan atribut kalendar melalui kaedah setCalendarProps dan isikan data dalam calendarProps satu persatu:

function setCalendarProps() {
  if (!targetDate.value) {
    targetDate.value = today;
  }
  // 获取目标日期的年月日星期几数据
  calendarProps.target.year = targetDate.value.getFullYear();
  calendarProps.target.month = targetDate.value.getMonth();
  calendarProps.target.date = targetDate.value.getDate();
  calendarProps.target.day = targetDate.value.getDay();

  if (
    calendarProps.target.year < MIN_YEAR ||
    calendarProps.target.year > MAX_YEAR
  ) {
    console.error("无效的年份,请检查传入的数据是否是正常");
    return;
  }

  // 获取到目标日期的月份【中文】名称
  let dateString;
  dateString = targetDate.value.toString().split(" ");
  calendarProps.target.monthShortName = dateString[1];
  calendarProps.target.monthFullName =
    monthNameList.fullName[calendarProps.target.month];
  calendarProps.target.monthChineseFullName =
    monthNameList.chineseFullName[calendarProps.target.month];
  // 获取目标月份的第一天是星期几,和在星期几中的索引值
  const targetMonthFirstDay = new Date(
    calendarProps.target.year,
    calendarProps.target.month,
    1
  );
  calendarProps.target.firstDay = targetMonthFirstDay.getDay();
  calendarProps.target.firstDayIndex = dayNameList.findIndex(
    (day) => day.dayNumber === calendarProps.target.firstDay
  );

  // 获取目标月份总共多少天
  const targetMonthLastDay = new Date(
    calendarProps.target.year,
    calendarProps.target.month + 1,
    0
  );
  calendarProps.target.totalDays = targetMonthLastDay.getDate();

  // 获取目标月份的上个月总共多少天
  const previousMonth = new Date(
    calendarProps.target.year,
    calendarProps.target.month,
    0
  );
  calendarProps.previous.totalDays = previousMonth.getDate();
}
Salin selepas log masuk

Satu perkara yang perlu diambil perhatian ialah apabila mendapat bilangan hari dalam bulan ini dan bilangan hari dalam bulan lepas, nilai tarikh ditetapkan kepada 0. Ini kerana apabila nilai tarikh ialah 0, objek Tarikh yang dikembalikan ialah hari terakhir bulan sebelumnya. Jadi, untuk mendapatkan bilangan hari dalam bulan ini, anda perlu menambah 1 pada nilai bulan pada bulan ini.

Selepas melaksanakan kaedah ini, nilai calendarProps pada masa ini ialah:

Analisis mendalam tentang cara merangkum komponen kalendar tersuai vue

4

Apabila kita sudah tahu nilai indeks hari dalam minggu sepadan dengan hari pertama bulan ini, berapa hari dalam bulan ini dan berapa banyak hari dalam bulan lepasSelepas tiga data teras ini, anda boleh mula menjana data kalendar yang sepadan.

Ideanya adalah seperti berikut:

  1. Oleh kerana dalam kebanyakan kes, hari pertama bulan ini tidak bermula dari awal, bahagian sebelumnya adalah tarikh bulan sebelumnya. Jadi baris pertama perlu diproses secara berasingan.
  2. Tetapkan nilai tarikh awam dan nilai awal ditetapkan kepada 1. Kemudian mulakan kenaikan dari nilai indeks hari dalam seminggu sepadan dengan hari pertama bulan ini. Tetapkan algoritma untuk mengira tarikh sebelum dan selepas bulan ini.
  3. Untuk memudahkan penukaran tarikh dan pembezaan gaya kemudian, data yang dijana diproses menjadi objek, yang mengandungi jenis tarikh -
  4. , menunjukkan sama ada bulan ini, bulan sebelumnya atau bulan berikutnya ; dateType
/**
 * 生成日历的数据
 */
function setCalendarData() {
  let i;
  let date = 1;
  const originData = [];
  const firstRow = [];
  // 设置第一行数据
  for (i = 0; i <= 6; i++) {
    // 设置目标月份之前月份的日期数据
    if (i < calendarProps.target.firstDayIndex) {
      const previousDate =
        calendarProps.previous.totalDays -
        calendarProps.target.firstDayIndex +
        (i + 1);
      firstRow.push({
        dateObj: new Date(
          calendarProps.target.year,
          calendarProps.target.month - 1,
          previousDate
        ),
        dateNumber: previousDate,
        dateType: "previous"
      });
    } else {
      // 设置目标月份当月的日期数据
      firstRow.push({
        dateObj: new Date(
          calendarProps.target.year,
          calendarProps.target.month,
          date
        ),
        dateNumber: date,
        dateType: "current"
      });
      date++;
    }
  }
  originData.push(firstRow);
  // 设置后面五行的数据
  for (let j = 0; j <= 4; j++) {
    const rowData = [];
    for (let k = 0; k <= 6; k++) {
      // 设置目标月份剩下的日期数据
      if (date <= calendarProps.target.totalDays) {
        rowData.push({
          dateObj: new Date(
            calendarProps.target.year,
            calendarProps.target.month,
            date
          ),
          dateNumber: date,
          dateType: "current"
        });
      } else {
        // 设置目标月份下个月的日期数据
        const nextDate = date - calendarProps.target.totalDays;
        rowData.push({
          dateObj: new Date(
            calendarProps.target.year,
            calendarProps.target.month + 1,
            nextDate
          ),
          dateNumber: nextDate,
          dateType: "next"
        });
      }
      date++;
    }
    originData.push(rowData);
  }
  calendarData.value = originData;
}
Salin selepas log masuk
Pada ketika ini, logik teras komponen kalendar ini telah dilaksanakan. Lihat, bukankah ia sangat mudah?

Seterusnya, kami hanya perlu memaparkan templat html yang sepadan dan menambah gaya berdasarkan data dalam

. calendarData

5. Tambah bahagian templat dan gaya

Secara umumnya, komponen kalendar mempunyai struktur seperti grid, jadi saya memilih kaedah jadual untuk pemaparan. Tetapi jika anda bertanya kepada saya jika ada cara lain, masih ada, seperti menggunakan susun atur fleksibel atau susun atur grid, tetapi jika kaedah ini digunakan, struktur data calendarData tidak akan menjadi seperti sekarang.

Struktur DOM adalah seperti berikut:

Analisis mendalam tentang cara merangkum komponen kalendar tersuai vue

Bagi kesan mengalir sempadan butang, saya membuatnya dengan merujuk kepada artikel Su Su untuk butiran , sila lihat:

Klip-laluan melaksanakan animasi sempadan mengalir butangjuejin.cn/post/719877…

Kemudian gaya yang lain bahagian, improvisasi atau reka bentuk mengikut UI Hanya lukis gambar. Saya percaya anda semua pernah mengalami lukisan reka bentuk indah adik-adik UI (heehee

Bahagian kod khusus tidak akan disiarkan dalam artikel. Jika perlu, anda boleh terus melihat kod sumber lengkap di bawah

gitee.com/wushengyuan…

Kesimpulan

Bagi sesetengah komponen yang terasa sangat menyusahkan, logik teras mungkin Tidak terlalu Kompleks Kadangkala, anda mungkin hanya memerlukan sedikit kesabaran untuk membaca baris demi baris dan memahami idea

Disyorkan kajian: "Tutorial Video Vue"

Atas ialah kandungan terperinci Analisis mendalam tentang cara merangkum komponen kalendar tersuai vue. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.im
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!