当前位置: 首页 > news >正文

使用React和Vite构建一个AirBnb Experiences克隆网站

这一篇文章中,我会教你如何做一个AirBnb Experiences的克隆网站。主要涵盖React中Props的使用。

克隆网站最终呈现的效果:
在这里插入图片描述

1. 使用vite构建基础框架

npm create vite@latestcd airbnb-project
npm install
npm run dev

2. 构建网站的3个部分

网站从上至下主要分为导航栏、简介和活动栏三个部分。
我们在public文件夹之下建立components文件夹,然后分别建立Navbar.jsx,Hero.jsx和Card.jsx这三个文件,分别对应网站的三个部分。
另外,在public文件夹之下建立images文件夹,包含网站要用的所有图片。
在这里插入图片描述
photo-grid.png
在这里插入图片描述
wedding-photography.png
在这里插入图片描述
mountain-bike.png
在这里插入图片描述
airbnb-logo.png
在这里插入图片描述
katie-zaferes.png
在这里插入图片描述
star.png

3. 删除index.css中的所有内容

index.css

* {box-sizing: border-box;
}body {margin: 0;font-family: 'Poppins', sans-serif;
}

4. 导航栏

Navbar.jsx

export default function Navbar() {return (<nav><img src="/images/airbnb-logo.png" className="nav--logo"/></nav>)
}

对应的index.css中的内容。

nav {height: 70px;display: flex;padding: 20px 36px;box-shadow: 0px 2.98256px 7.4564px rgba(0, 0, 0, 0.1);
}.nav--logo {max-width: 100px;
}

5. 简介栏

Hero.jsx

export default function Hero() {return (<section className="hero"><img src="/images/photo-grid.png" className="hero-photo" /><h1 className="hero-header">Online Experiences</h1><p className="hero--text">Join unique interactive activities led by one-of-a-kind hosts-all without leaving home.</p></section>)
}

对应的index.css中的内容。

section {padding: 20px;
}.hero {display: flex;flex-direction: column;
}.hero--photo {max-width: 400px;align-self: center;
}.hero--header {margin-bottom: 16px;
}.hero--text {margin-top: 0;
}

6. 活动栏

Card.jsx

export default function Card(props) {let badgeTextif (props.item.openSpots === 0){badgeText = "SOLD OUT"} else if (props.item.location === "Online"){badgeText = "ONLINE"}return (<div className="card">{badgeText && <div className="card--badge">{badgeText}</div>}<img src={`/images/${props.item.coverImg}` }className="card--image"alt="Image of Katie Zaferes."/><div className="card--stats"><img src="/images/star.png" className="card--star"alt="Star icon."    /><span>{props.item.stats.rating}</span><span className="gray">({props.item.stats.reviewCount}) · </span><span className="gray">{props.item.location}</span></div><h2>{props.item.title}</h2><p><span className="bold">From ${props.item.price}</span> / person</p></div>)
}

对应的index.css中的内容。

.card {width: 175px;font-size: 0.75rem;flex: 0 0 auto;display: flex;flex-direction: column;position: relative
}.card--image {width: 100%;border-radius: 9px;margin-bottom: 9px;
}.card--title {overflow: hidden;text-overflow: ellipsis;
}.card--stats {display: flex;align-items: center;
}.card--star {height: 14px;
}.card--price {margin-top: auto;
}.card--badge{position: absolute;top: 6px;left: 6px;background-color: white;padding: 5px 7px;border-radius: 2px;font-weight: bold;
}h2 {font-size: 0.75rem;font-weight: normal;
}.gray {color: #918E9B;
}.bold {font-weight: bold;
}

7. 删除App.css中的所有内容

8. 准备需要的数据

在src文件夹之下建立data.jsx文件,准备在活动栏中需要呈现的内容。
data.jsx

export default [{id: 1,title: "Life Lessons with Katie Zaferes",description: "I will share with you what I call \"Positively Impactful Moments of Disappointment.\" Throughout my career, many of my highest moments only came after setbacks and losses. But learning from those difficult moments is what gave me the ability to rise above them and reach my goals.",price: 136,coverImg: "katie-zaferes.png",stats: {rating: 5.0,reviewCount: 6},location: "Online",openSpots: 0,},{id: 2,title: "Learn Wedding Photography",description: "Interested in becoming a wedding photographer? For beginner and experienced photographers alike, join us in learning techniques required to leave the happy couple with memories that'll last a lifetime.",price: 125,coverImg: "wedding-photography.png",stats: {rating: 5.0,reviewCount: 30},location: "Online",openSpots: 27,},{id: 3,title: "Group Mountain Biking",description: "Experience the beautiful Norwegian landscape and meet new friends all while conquering rugged terrain on your mountain bike. (Bike provided!)",price: 50,coverImg: "mountain-bike.png",stats: {rating: 4.8,reviewCount: 2},location: "Norway",openSpots: 3,}
]

9. 更新App.jsx中的内容

App.jsx

import Navbar from "../public/components/Navbar"
import Hero from "../public/components/Hero"
import Card from "../public/components/Card"
import data from "./data"export default function App() {const cards = data.map(item => {return (<Cardkey = {item.id}item = {item}/>)})return (<div><Navbar /><Hero /><section className="cards--list">{cards}</section></div>)
}

对应的index.css中的内容。

.cards--list {display: flex;flex-wrap: nowrap;gap: 20px;overflow-x: auto;
}

10. 完整的index.css

* {box-sizing: border-box;
}body {margin: 0;font-family: 'Poppins', sans-serif;
}nav {height: 70px;display: flex;padding: 20px 36px;box-shadow: 0px 2.98256px 7.4564px rgba(0, 0, 0, 0.1);
}h2 {font-size: 0.75rem;font-weight: normal;
}.gray {color: #918E9B;
}.bold {font-weight: bold;
}.nav--logo {max-width: 100px;
}section {padding: 20px;
}.hero {display: flex;flex-direction: column;
}.hero--photo {max-width: 400px;align-self: center;
}.hero--header {margin-bottom: 16px;
}.hero--text {margin-top: 0;
}.cards--list {display: flex;flex-wrap: nowrap;gap: 20px;overflow-x: auto;
}.card {width: 175px;font-size: 0.75rem;flex: 0 0 auto;display: flex;flex-direction: column;position: relative
}.card--image {width: 100%;border-radius: 9px;margin-bottom: 9px;
}.card--title {overflow: hidden;text-overflow: ellipsis;
}.card--stats {display: flex;align-items: center;
}.card--star {height: 14px;
}.card--price {margin-top: auto;
}.card--badge{position: absolute;top: 6px;left: 6px;background-color: white;padding: 5px 7px;border-radius: 2px;font-weight: bold;
}

11. 上传到github

12. 上传到netlify

http://www.lryc.cn/news/483657.html

相关文章:

  • HBase压测 ycsb
  • 基于Python+Django+Vue3+MySQL实现的前后端分类的商场车辆管理系统
  • 网络安全web基础_HTML基础(扫盲篇)
  • (附项目源码)Java开发语言,监督管家APP的设计与实现 58,计算机毕设程序开发+文案(LW+PPT)
  • 前端基础的讲解-JS(11)
  • Python魔法方法深度解析:解密__call__、__new__和__del__的核心奥义
  • 当微软windows的记事本被AI加持
  • Python酷库之旅-第三方库Pandas(213)
  • 普林斯顿:LLM基于边际优化的梯度纠缠
  • 通俗易懂:什么是 Java 类加载?
  • Dijkstra 算法的实现方案
  • OpenGL 进阶系列07 - 阴影贴图(shadowmap )
  • 【CAN介绍】【第一篇章】
  • 【统计子矩阵——部分前缀和+双指针】
  • 用正则表达式检查是IP否为内网地址
  • Leetcode刷题笔记14
  • PHP图书绘本借阅管理系统小程序源码
  • 【JavaWeb】JavaWeb入门之XML详解
  • JS手写-this绑定实现
  • 【时间之外】IT人求职和创业应知【31】
  • 如何使用ffmpeg命令行进行录屏
  • ODOO学习笔记(8):模块化架构的优势
  • 数字IC后端实现之Innovus specifyCellEdgeSpacing和ICC2 set_placement_spacing_rule的应用
  • 每日小练:Day2
  • ubuntu 安装kafka-eagle
  • 深入理解指针
  • 自动驾驶合集(更新中)
  • Chapter 14 scoped样式以及data函数
  • Golang | Leetcode Golang题解之第557题反转字符串中的单词III
  • 区块链技术在电子政务中的应用