AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

爱彼迎React项目

作者: 作者的头像   我是java同学 ,  2025-01-12 22:15:51 ,  所有人可见 ,  阅读 9


0


header的搭建

1.一共有三个页面,可以每个页面都做一个header,也可以只做一个header,根据每个页面需要展示的条件进行控制显示。选择第二种方式进行搭建
2.分别对header的left、center和right进行封装
3.中间居中的问题
3.1.如果给左边固定宽度,右边固定宽度,中间部分flex: 1。但是左右两边的固定宽度不一样,中间部分是不会居中的。
3.2.可以给中间部分一个固定的宽度,左右两部分分别flex: 1,永远保证左右两边宽度是一致的,这样就能居中了

svg在react中的使用

1.如果是.svg文件,在img和background-image中都可以使用
2.如果是直接嵌入svg标签,svg可以随着html文件的下载一起下载下来。

将svg抽成组件,用一个工具函数将样式的字符串转化为string

<div>
    <svg><path></path></svg>
</div>

style-components管理资源

1.混入


2.传入服务器返回数据的样式
2.1.在wrapper中传入变量
2.2.将props使用

react中引入图片

应该直接用import引入
如果直接引入,因为是从js中引入图片,是解析不出来的。

<img src="../../assest/..."> 

home-itme的每张图片的比例不一样,造成高度不一致

1.给padding-top的值设为66.6%,一个足够的高度
2.padding的百分比是相对于width而言的
3.给img设置绝对定位,img完全覆盖上去

.cover {
    position: relative;
    box-sizing: border-box;
    padding: 66.66% 8px 0;
    border-radius: 3px;
    overflow: hidden;

    img {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
    }
}

这么写就能让每个内容有对齐的宽高
Snipaste_2025-01-12_17-40-54.png

scrollView的一些注意点

1.需要设置在父盒子的内部,这样才能获取到相关的width数据

longfor-list是父盒子,只有放在里面才能拿到相对于longfor-list的scorollWidth、clientWidth、offsetLeft等数据
Snipaste_2025-01-14_22-07-56.png

2.如果每个item没有达到对应的宽度,flex-shrink应该设置为0

Snipaste_2025-01-14_22-14-57.png

给item设置inner

1.如果要给item设置内边距,如果不用inner,需要计算一个整个盒子的宽度与padding的关系
2.使用inner就可以不需要考虑这些问题

给home的每个组件都加一个margin-top

不需要给每个组件都设置一次,可以在home中直接设置
这样是给直接子元素div设置margin-top: 30px

export const HomeWrapper = styled.div`
    > div {
        margin-top: 30px;
    }
`

Snipaste_2025-01-14_22-04-34.png

分页器切换页面效果

1.回到顶部

window.scrollTo(0, 0)

2.利用定位加一个蒙版
2.1 定义一个变量isLoading,保存在store中
2.2 在rooms中增加蒙版

{ isLoading && <div className="bg-cover"></div> }

2.3 一旦发送网络请求,派发action修改状态

export const fetchEntireDataAction = createAsyncThunk("fetchData", async (page = 0, {dispatch, getState}) => {
  // 请求数据前,增加蒙版
  dispatch(changeIsLoadingAction(true))
  // 请求数据
  const res = await getEntireRoomListData(page * 20)
  dispatch(changeCurrentPageAction(page))
  dispatch(changeRoomListAction(res.list))
  dispatch(changeTotalCountAction(res.totalCount))
  // 请求完数据,移除蒙版
  dispatch(changeIsLoadingAction(false))
})

图片被强行压缩

现象:
Snipaste_2025-01-15_16-26-19.png
解决:可以给image加一个属性,保持原来宽高比的情况下,把超出的部分隐藏
Snipaste_2025-01-15_16-27-23.png
效果:
Snipaste_2025-01-15_16-28-00.png

sliper的样式学习

.slider {
    position: relative;
    cursor: pointer;

    &:hover {
        .control {
          display: flex;
        }
    }

    .control {
        position: absolute;
        z-index: 9;
        left: 0;
        top: 0;
        bottom: 0;
        right: 0;
        display: none;
        justify-content: space-between;
        color: #fff;

        .icon {
          display: flex;
          justify-content: center;
          align-items: center;
          width: 83px;
          height: 100%;
          background: linear-gradient(to left, transparent 0%, rgba(0, 0, 0, 0.25) 100%);

          &.right {
            background: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.25) 100%);
          }
        }
    }
}

entire页面轮播图indicator

1.封装成base-ui组件
2.包裹需要使用的内容
3.监听点击,特判两个边界(最后一个点击跳到第一个,第一个点击同理)
4.每个选中的item滚动到中间的位置
4.1.其实就是滚动蓝色箭头的长度,按照下面公式
Snipaste_2025-01-17_09-26-05.png
4.2.flex布局要放在i-content里面,clientWidth的值才正确
5.其他逻辑和scroll-view组件思路一致
6.左右特殊情况。0和1都不需要居中。
6.1.左边的判断方法:0和1如果要居中都是向右边移动(1在居中位置的左边),2需要向左移动。0和1移动到中间按照计算公式计算出来的结果是负值,而2计算出来的是正值。通过这个条件特判。如果小于0,就让distance = 0,不能直接return,否则点击上一张/下一张会原地不动
Snipaste_2025-01-17_10-22-21.png
6.2.右边的判断方法:最多的移动距离是蓝色箭头的距离,如果比这个距离要大,让它等于这个距离
Snipaste_2025-01-17_10-28-17.png

entire页面item点击跳转到详情页

如果直接在组件内部监听事件,全部使用到这件组件的地方都会进行跳转。可以不在item组件内部来做,可以在entire页面定义这个事件,传递给item组件内部,判断itemClick有没有值,只有有值的情况下再去调用,同时把itemData回调出去。将数据派发保存到store中

<RoomItem itemclick={itemClickHandle}>

const { itemClick } = props

function itemClickHandle() {
    if (itemClick) itemClick(itemData)
}

bug:切换到entire页面不在顶部

在app.jsx中编写逻辑或者封装成hooks(推荐),对应位置使用

detail详情页

1.通过entire页面进入详情页传递过来的数据,如果在detail页面再刷新,数据就会清空,影响开发效率。
1.1.解决:store里的detail初始化值,不要用空对象,而是用一个itemInfo做初始化值。这样测试的时候就很方便,不需要每次都重新进入。做完以后再复原。
2.需求:手指放上图片,所有图片加上cover,只有鼠标对应的图片没有cover,放上去的图片有缩放,需要有动画

 &:hover {
    .bg-cover {
      opacity: 1 !important;
    }

    .item:hover {
      .bg-cover {
        opacity: 0 !important;
      }

      img {
        transform: scale(1.1);
      }
    }
  }

图片浏览器

1.用固定定位设置全屏背景
2.取消右侧滚动条,取消滚动功能
使用useEffect设置对应的样式,组件卸载的时候还原

useEffect(() => {
    document.body.style.overflow = "hidden"
    return (() => {
      document.body.style.overflow = "auto"
    })
  }, [])

3.关闭图片浏览器,从detail-pictures传递事件进去

<PictureBrowser 
    picturesData={DetailPictures}
    closeClick={e => setIsShowBrowser(false)}
/> 
const closeBtnHandle = () => {
    if (closeClick) closeClick()
  }

4.点下一张图片时太快,图片会被选中,被蓝色背景遮罩覆盖
添加样式user-select: none;
5.切换图片过程中的动画,利用react-transition-group库
npm install react-transition-group
6.底部显示和隐藏照片列表
6.1.控制栏和图片列表整体是一个做一个绝对定位,监听点击,height由70px变为0,控制栏就能跟着往下走
Snipaste_2025-01-18_13-05-12.png
7.bug:点击轮播图切换会进入到详情页,因为由冒泡事件,所以会页面跳转。解决:阻止冒泡。需要拿到event对象
Snipaste_2025-01-18_15-47-53.png

<div className="left icon" onClick={e => IconClickHandle(false, e)}>
  <IconArrowLeft height='30' width='30' />
</div>

const IconClickHandle = (isNext = true, event) => {
    // 轮播图逻辑
    isNext ? sliderRef.current.next(): sliderRef.current.prev()

    // 指示器逻辑
    const length = roomData.picture_urls.length
    let newIndex = isNext ? selectIndex + 1: selectIndex - 1
    if (newIndex === length) newIndex = 0
    if (newIndex < 0) newIndex = length - 1
    setSelectIndex(newIndex)

    // 阻止事件冒泡
    event.stopPropagation()
  }

appHeader

1.每个页面最好单独使用组件,互不影响的调整。而这次不是,只用一个组件
2.将用一个变量保存在store-main中,控制每个页面是否使用固定定位。
2.1.bug:provider包裹suspense,否则状态更新可能监听不到
Snipaste_2025-01-20_09-03-09.png
3.appHeader组件中根据store中的状态切换fixed样式
4.界面搭建
5.监听滚动切换header样式。封装一个hooks拿到scrollY,用一个变量记录上一个点开header的位置(可以用useRef),用新滚动的位置减去旧的位置,判断是否切换header的样式

const prevY = useRef()
const { scrollY } = useScrollPosition()
if (!isSearch) prevY.current = scrollY
if (isSearch && Math.abs(scrollY - prevY.current)) setIsSearch(false)

6.顶部透明效果:记录一个变量保存在store中,只有当前在顶部才实现透明效果。将变量传到themeProvider,这样所有组件都能够拿到这个变量,控制样式的设置

Style-component不生效问题

React 在渲染组件时,标签名称是区分大小写的。styled-components会根据你定义的组件名称来解析相应的标签名。

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息