week8---10月28日 div 布局

本文介绍了CSS中常见的单行布局类型,包括单行单列、单行两列和单行三列布局,并探讨了如何通过浮动、定位等技术实现这些布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、复习

1、浮动的设置

2、浮动清除

3、外边距为负数

 

二、新课

(一)页面布局应用

利用CSS可实现任意布局方式,创建各种布局类型,这里介绍几种常用的单行布局类型,这些布局的重复使用可实现任意的按列布局。

1、单行单列布局

行单列布局可以用带单位的数字值设置为固定宽度布局,页面内容宽度不随浏览器窗口大小变化,若浏览器窗口宽度小于页面内容时自动增加滚动条。也可以用占父元素(浏览器窗口)宽度的百分比%设置为自适应宽度布局,页面内容宽度随浏览器窗口宽度变化而自动改变,但浏览器窗口宽度较小时页面内容也会被压缩的很窄。

    单行单列布局页面内容一般在浏览器居中显示:

    margin:0 auto;

    单行单列布局可以指定页面内容的固定高度,也可以不指定以页面内容自适应高度。

2、单行两列

单行两列布局一般将两个单行单列<div>元素放在一个<div>元素内,使用定位或浮动实现两列布局,即可以是固定宽度也可以是自适应宽度。

    使用定位布局时一般子元素绝对定位(不占空间)、父元素相对定位(不失去空间)但不设偏移量以保证子元素依据父元素定位。

    如果两个子元素都使用绝对定位(一般左侧用top:0; left:0;右侧用top:0; right:0;),则必须对父元素(空元素)设置高度以防止后续元素上移。

    如果只对右侧第二个子元素绝对定位,父元素可不设置高度自适应左侧不定位子元素的高度(但不能小于右侧定位元素的高度,否则定位元素超出部分与后续元素重叠)。

    使用浮动布局时两列子元素应同时浮动,父元素(空元素)可以同时浮动自适应子元素高度但必须考虑后续元素,也可以不浮动但必须设置高度防止后续元素上移。如果考虑兼容IE6及以下浏览器最好不浮动也不设高度,而在最后增加一个空子元素并设置为禁止浮动,这样即可以自适应浮动子元素的高度又不影响后续元素。

3、单行三列布局

单行三列通常左右较窄样式大致相同,可以绝对定位布局,也可以浮动布局,可以固定宽度,也可以自适应宽度布局。

4、多行多列综合布局

 


 

 

<template> <view class="calendar-container" style="margin: 20rpx 0; margin-bottom: 0"> <!-- 头部显示 --> <!-- <view class="header"> <text class="year-month">{{ displayYearMonth }}</text> --> <!-- <img class="person-img" style="width: 120rpx" :src="IMG_URL + 'schedulePerson.png'" /> --> <!-- <img width="100%;" style="border-top-left-radius: 32rpx; border-top-right-radius: 32rpx" :src="IMG_URL + 'date-header.png'" /> --> <view class="fr jb ac" style="margin: 0 40rpx"> <view class="fr jb ac"> <!-- 向左箭头上一周 --> <image class="arrow-left" v-if="isShowArrowLeft" style="width: 30rpx; height: 30rpx; margin-right: 10rpx; transform: rotate(180deg)" :src="IMG_URL + 'before_icon.png'" @click="handleArrowLeft" /> <image class="arrow-left" v-if="!isShowArrowLeft" style="width: 30rpx; height: 30rpx; margin-right: 10rpx" :src="IMG_URL + 'after_icon.png'" @click="handleArrowLeft" /> <!-- 中间显示--> <view class="date-change-btn">{{ formattedDate }}</view> <!-- 向右箭头下一周 --> <image class="arrow-right" v-if="isShowArrowRight" style="width: 30rpx; height: 30rpx; margin-left: 10rpx" :src="IMG_URL + 'before_icon.png'" @click="handleArrowRight" /> <image class="arrow-right" v-if="!isShowArrowRight" style="width: 30rpx; height: 30rpx; margin-left: 10rpx; transform: rotate(180deg)" :src="IMG_URL + 'after_icon.png'" @click="handleArrowRight" /> </view> <!-- <view class="fr jb ac" v-if="props.isShow != false"> <view class="date-change-btn"> <image style="width: 40rpx; height: 40rpx; margin-right: 20rpx" :src="IMG_URL + 'filtration.png'" /> </view> </view> --> </view> <!-- 滑动容器 --> <!-- <swiper :current-item-id="currentItemId" @change="onSwiperChange" class="swiper-container" :duration="300"> --> <swiper :current-item-id="currentItemId" @change="throttledSwiperChange" class="swiper-container" :duration="300" :circular="false"> <swiper-item v-for="item in weekArray" :key="item" :item-id="item.toString()" class="swiper-item"> <view class="week-container"> <view v-for="day in weekDateObject.obj[item]" :key="day.date" class="day-item" @tap="selectDay(day)"> <text class="weekday">{{ day.weekday }}</text> <text class="day-number" :class="{ today: day.isToday, current: currentSelected === formatDate1(day.date) }">{{ day.day }}</text> <!-- <view v-if="dataArray?.includes(formatDate1(day.date))" style="background-color: #ffbd27; width: 6rpx; height: 6rpx; border-radius: 999rpx; margin-top: 4rpx"> </view> --> <image v-if="dataArray.includes(formatDate1(day.date))" style="width: 10rpx; height: 10rpx; margin-top: 4rpx" :src="IMG_URL + 'star_a.png'" /> </view> </view> </swiper-item> </swiper> </view> </template> <script setup> import { IMG_URL } from '@/config/base' import { getCalendarStatistics } from '@/request/api/org/course.js' import { addWeeks, eachDayOfInterval, endOfWeek, format, isSameDay, isToday, startOfWeek, subWeeks } from 'date-fns' import { zhCN } from 'date-fns/locale' import { throttle } from 'lodash-es' import { computed, ref, watch } from 'vue' const emit = defineEmits(['date-change']) // 当前基准期(中间位置) const baseDate = ref(new Date()) const currentItemId = ref('0') const isInitialized = ref(false) // 添加初始化标志 const props = defineProps({ courseId: { type: String, default: '' }, // 兼容c端约课组件 type: { type: Number, default: 1 }, function: { type: Function, default: null }, // 兼容c端约课组件 courseMode: { type: Number, default: null }, //插班补课是否显示筛选 isShow: { type: Boolean, default: true } }) // 预渲染的周数据(前一周/当前周/下一周) const formatDate1 = dateString => { const date = new Date(dateString) const year = date.getFullYear() const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') return `${year}-${month}-${day}` } const userInfo = uni.getStorageSync('USERINFO') const orgId = computed(() => uni.getStorageSync('orgInfo').orgId || {}) // const weekArray = ref([-4, -3, -2, -1, 0, 1, 2, 3, 4]) const weekArray = ref([-1, 0, 1]) // 只保留前一周/当前周/下一周 const dataArray = ref([]) const weekDateObject = computed(() => { const finallyArray = weekArray.value.map(week => { let curDate if (week < 0) { curDate = subWeeks(baseDate.value, Math.abs(week)) } else if (week == 0) { curDate = baseDate.value } else { curDate = addWeeks(baseDate.value, week) } const start = startOfWeek(curDate, { weekStartsOn: 1 }) const end = endOfWeek(curDate, { weekStartsOn: 1 }) return { [week]: eachDayOfInterval({ start, end }).map(day => ({ date: day, day: format(day, 'd'), // 使用自定义函数截取第二个字符(去掉"周"字) weekday: format(day, 'EEE', { locale: zhCN }).substring(1), isToday: isToday(day), isCurrent: isSameDay(day, new Date()) })) } }) console.log('finallyArray', finallyArray) const obj = {} finallyArray.forEach(item => { obj[Object.keys(item)[0]] = Object.values(item)[0] }) const returnObj = { obj, startTime: formatDate1(obj[weekArray.value[0]][0].date), endTime: formatDate1(obj[weekArray.value[weekArray.value.length - 1]][6].date) } console.log(obj, 'obj') return returnObj }) const getScheduleData = () => { if (!weekDateObject.value) { return } const params = { beginTime: `${weekDateObject.value.startTime} 00:00:00`, endTime: `${weekDateObject.value.endTime} 23:59:59`, orgId: orgId.value, userId: userInfo.userId } if (props.courseId) { params.courseId = props.courseId } // 兼容c端约课组件 if (props.courseMode) { params.courseMode = props.courseMode } let port = getCalendarStatistics // 兼容c端约课组件 if (props.type == 1) { port = getCalendarStatistics } else { port = props.function } console.log(port, 'port') port(params).then(res => { dataArray.value = res.data?.map(v => v.scheduleDate) // console.log(dataArray.value, "dataArray"); }) } watch( () => [weekDateObject.value, props.courseId], () => { getScheduleData() }, { immediate: true, deep: true } ) // 判断上一周是否有课表 const isShowArrowLeft = computed(() => { const prevWeekMonday = format(startOfWeek(subWeeks(baseDate.value, 1), { weekStartsOn: 1 }), 'yyyy-MM-dd') return dataArray.value.includes(prevWeekMonday) }) // 判断下一周是否有课表 const isShowArrowRight = computed(() => { const nextWeekMonday = format(startOfWeek(addWeeks(baseDate.value, 1), { weekStartsOn: 1 }), 'yyyy-MM-dd') return dataArray.value.includes(nextWeekMonday) }) const handleArrowLeft = () => { const { start, end } = getLastWeek() baseDate.value = subWeeks(baseDate.value, 1) emit('date-search', start, end) } const handleArrowRight = () => { const { start, end } = getNextWeek() baseDate.value = addWeeks(baseDate.value, 1) emit('date-search', start, end) } // 新增辅助方法获取期范围 const getDateRange = date => { const start = format(startOfWeek(date, { weekStartsOn: 1 }), 'yyyy-MM-dd') const end = format(endOfWeek(date, { weekStartsOn: 1 }), 'yyyy-MM-dd') return [start, end] } // 重构 onSwiperChange 方法 // const onSwiperChange = e => { // const curId = Number(e.detail.currentItemId) // currentItemId.value = curId.toString() // // 向左滑动加载前一周 // if (curId === weekArray.value[0]) { // baseDate.value = subWeeks(baseDate.value, 1) // emit('date-search', ...getDateRange(baseDate.value)) // } // // 向右滑动加载下一周 // if (curId === weekArray.value[weekArray.value.length - 1]) { // baseDate.value = addWeeks(baseDate.value, 1) // emit('date-search', ...getDateRange(baseDate.value)) // } // } const onSwiperChange = e => { const curId = Number(e.detail.currentItemId) currentItemId.value = curId.toString() // 如果是初始化阶段,不触发date-search if (!isInitialized.value) { isInitialized.value = true return } // 向左滑动加载前一周 if (curId === weekArray.value[0]) { weekArray.value.unshift(curId - 1) // 限制最大数量(可选) if (weekArray.value.length > 10) weekArray.value.pop() } // 向右滑动加载下一周 else if (curId === weekArray.value[weekArray.value.length - 1]) { weekArray.value.push(curId + 1) // 限制最大数量(可选) if (weekArray.value.length > 10) weekArray.value.shift() } // 触发数据更新 const curDate = addWeeks(baseDate.value, curId) emit('date-search', ...getDateRange(curDate)) } // 创建节流版本 const throttledSwiperChange = throttle(onSwiperChange, 300, { leading: true, trailing: false }) // 向左箭头查询上一周课表列表数据 // 获取上一周的开始和结束时间 const getLastWeek = () => { //时间格式化为YYYY-MM-DD const lastWeek = subWeeks(baseDate.value, 1) const start = format(startOfWeek(lastWeek, { weekStartsOn: 1 }), 'yyyy-MM-dd') const end = format(endOfWeek(lastWeek, { weekStartsOn: 1 }), 'yyyy-MM-dd') return { start, end } } //获取下一周的开始和结束时间 const getNextWeek = () => { const nextWeek = addWeeks(baseDate.value, 1) const start = format(startOfWeek(nextWeek, { weekStartsOn: 1 }), 'yyyy-MM-dd') const end = format(endOfWeek(nextWeek, { weekStartsOn: 1 }), 'yyyy-MM-dd') return { start, end } } // const handleArrowLeft = () => { // // 先获取时间范围(只调用一次) // const newId = Math.min(...weekArray.value) - 1 // weekArray.value.unshift(newId) // currentItemId.value = newId.toString() // // 发送单个请求 // getCalendarStatistics({ // beginTime: `${start} 00:00:00`, // endTime: `${end} 23:59:59`, // orgId: orgId.value, // userId: userInfo.userId // }).then(res => { // formattedDate.value = `${start} - ${end}` // }) // // 触发父组件更新(只需要触发一次) // emit('date-search', start, end) // } // 向右箭头下一周 // const handleArrowRight = () => { // // 先获取时间范围(只调用一次) // const { start, end } = getNextWeek() // //下一周 // baseDate.value = addWeeks(baseDate.value, 1) // // 触发父组件更新(只需要触发一次) // //发送单个请求 // getCalendarStatistics({ // beginTime: `${start} 00:00:00`, // endTime: `${end} 23:59:59`, // orgId: orgId.value, // userId: userInfo.userId // }).then(res => { // formattedDate.value = `${start} - ${end}` // }) // // 触发父组件更新(只需要触发一次) // emit('date-search', start, end) // } const currentSelected = ref(formatDate1(new Date())) // 初始化为字符串格式 // 选择期 // 修改后的selectDay方法 const selectDay = day => { currentSelected.value = formatDate1(day.date) // 确保存储字符串格式 emit('date-change', currentSelected.value) // 调试志 console.log('当前选中:', currentSelected.value) console.log('点击期:', formatDate1(day.date)) } // 格式化期取当前期的一周的开始和结束 const formattedDate = computed(() => { const currentWeekIndex = currentItemId.value const currentWeek = weekDateObject.value.obj[currentWeekIndex] if (!currentWeek) return '' const monday = currentWeek[0].date const sunday = currentWeek[6].date // 格式化期为 "YYYY年MM月DD" 格式 const formatDate = date => { const year = date.getFullYear() const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') return `${year}年${month}月${day}` } // 格式化结束期为 "MM月DD" 格式 const formatEndDate = date => { const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') return `${month}月${day}` } return `${formatDate(monday)} - ${formatEndDate(sunday)}` }) const formatDate = dateString => { const date = new Date(dateString) return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}` // 格式化为 YYYY年MM月 // return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}`; // 格式化为 YYYY年MM月DD } </script> <style scoped> .calendar-container { position: relative; background: #fff; border-radius: 32rpx; /* box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); */ } .header { padding: 24rpx; border-bottom: 1rpx solid #eee; } .year-month { font-size: 32rpx; color: #333; font-weight: bold; } .swiper-container { /* padding-top: 90rpx; */ height: 180rpx; } .swiper-item { height: 100%; } .week-container { display: flex; justify-content: space-around; align-items: center; padding: 0 20rpx; gap: 5rpx; height: 100%; } .day-item { display: flex; flex-direction: column; align-items: center; flex: 1; /* 关键修改:等分容器宽度 */ height: 120rpx; border-radius: 16rpx; transition: all 0.2s; font-weight: 500; color: #4a4a4a; } .weekday { font-size: 20rpx; color: #4a4a4a; margin-bottom: 8rpx; } .day-number { font-size: 28rpx; color: #333; padding: 0 10rpx; border-radius: 12rpx; margin-bottom: 10rpx; } /* .current { background: #5e94ff !important; color: #fff !important; border: 1rpx solid #3a6ccc !important; } */ .today { background: #83c3ff; color: #333; } .today { /* background: #83c3ff; */ /* border: 1rpx solid #5e94ff; */ } /* .today .day-number { color: #328add; font-weight: bold; } */ .current { background: #5e94ff !important; color: #fff !important; } .current .weekday, .current .day-number { color: #fff !important; } .date-change-btn { /* position: absolute; top: 10rpx; left: 24rpx; */ /* padding: 0 20rpx; */ font-weight: bold; font-size: 26rpx; color: #000000; line-height: 70rpx; height: 70rpx; /* margin-left: 40rpx; */ /* background: #edf6ff; */ border-radius: 20rpx 20rpx 20rpx 20rpx; } .person-img { position: absolute; right: 60rpx; top: -128rpx; width: 200rpx; } </style>能不能根据已上代码重新写这个组件,样式布局不变,props的条件不变,就是把滑动历的功能和点击上一周和下一周这两个共嗯那个每一次改变保持同步可以更改const weekArray = ref([-1, 0, 1]) 的初始值,只要滑动和切换保持一致就可以,
最新发布
07-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值