使用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
相关文章:

使用React和Vite构建一个AirBnb Experiences克隆网站
这一篇文章中,我会教你如何做一个AirBnb Experiences的克隆网站。主要涵盖React中Props的使用。 克隆网站最终呈现的效果: 1. 使用vite构建基础框架 npm create vitelatestcd airbnb-project npm install npm run dev2. 构建网站的3个部分 网站从上…...

HBase压测 ycsb
## ycsb 导入数据 rootXX.14.40.1971、对portrait压测 ansible hadoop -i hosts_hbase_portrait_20230730.txt -m shell -a "hostname && chdir/data/workspace/ycsb-0.17.0 nohup bin/ycsb load hbase20 -P workloads/workload_insert -cp /usr/local/fqlhadoop/…...

基于Python+Django+Vue3+MySQL实现的前后端分类的商场车辆管理系统
项目名称:基于PythonDjangoVue3MySQL实现的前后端分离商场车辆管理系统 技术栈 开发工具:PyCharm、Visual Studio Code (VSCode)运行环境:Python 3.10、MySQL 8.0、Node.js 18技术框架:Django 5、Vue 3.4、Ant-Design-Vue 4.12 …...

网络安全web基础_HTML基础(扫盲篇)
web基础_HTML扫盲篇 一、什么是 HTML? 二、HTML 的基本特点 三、HTML 基本结构概述 1.文档声明(!DOCTYPE html) 2. html元素 3. head元素 4. body 元素 四、HTML5的主要标签清单 文档结构标签 文本内容标签 链接和锚点标签 表格标…...

(附项目源码)Java开发语言,监督管家APP的设计与实现 58,计算机毕设程序开发+文案(LW+PPT)
摘要 随着互联网的快速发展和智能手机的普及,越来越多的用户选择通过移动应用程序进行事项设定、提醒通知和事项打卡。监督管家APP作为一个专注于事项设定、提醒通知、事项打卡的监督管理平台,具有广泛的应用前景和商业价值。本研究旨在构建一个功能丰富…...

前端基础的讲解-JS(11)
对象 对象是什么? 在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,所有的数据类型都可以存放在内。 属性:即事物的特征,在对象中用属性来表示(常用名词…...

Python魔法方法深度解析:解密__call__、__new__和__del__的核心奥义
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! Python中的魔法方法(Magic Methods)是构建Python高级功能的基础,它们使得对象可以…...

当微软windows的记事本被AI加持
1985年,微软发布了Windows 1.0,推出了一款革命性的产品:记事本(Notepad)。这款软件旨在鼓励使用一种未来主义的新设备——鼠标,并让人们可以不依赖VI等键盘工具就能书写文本和编写代码。记事本因其简洁和高…...

Python酷库之旅-第三方库Pandas(213)
目录 一、用法精讲 996、pandas.DatetimeIndex.day属性 996-1、语法 996-2、参数 996-3、功能 996-4、返回值 996-5、说明 996-6、用法 996-6-1、数据准备 996-6-2、代码示例 996-6-3、结果输出 997、pandas.DatetimeIndex.hour属性 997-1、语法 997-2、参数 99…...

普林斯顿:LLM基于边际优化的梯度纠缠
📖标题:A Common Pitfall of Margin-based Language Model Alignment: Gradient Entanglement 🌐来源:arXiv, 2410.13828 🌟摘要 🔸从人类反馈中强化学习(RLHF)已成为对齐语言模型…...

通俗易懂:什么是 Java 类加载?
文章目录 类加载过程的三个阶段一个简单的案例:类加载的工作原理使用这个类类加载的顺序类加载的特点类加载的好处总结推荐阅读文章 在 Java 中, 类加载是一种将我们写的 Java 类文件加载到内存中的过程,让 JVM(Java 虚拟机&…...

Dijkstra 算法的实现方案
下面是一个基于 Dijkstra 算法的实现方案,能够在 DEM(数字高程模型)数据上进行寻路,并满足以下需求: 使用 Qt C++ 编写; 规避 DEM 中的障碍物; 支持指定起点和终点; 使用 GDAL 库读取 DEM 文件; 输出路径到 TXT 文件; 输出的坐标为地理坐标(例如经纬度),而不是像…...

OpenGL 进阶系列07 - 阴影贴图(shadowmap )
一:概述: 在 OpenGL 中,Shadow Mapping(阴影贴图)是一种常用的实时阴影技术,用于渲染物体的阴影效果。这种方法通过生成光源视角下的深度贴图,再在场景渲染时使用它来判断物体是否被遮挡,从而实现阴影效果。下面是实现 Shadow Mapping 的基本步骤和相关知识。 二:绘制…...

【CAN介绍】【第一篇章】
1. CAN简介 • CAN 总线( Controller Area Network Bus )控制器局域网总线 • CAN 总线是由 BOSCH 公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线,广泛应用于汽车、嵌入式、工业控制等领域 • CAN 总线特征࿱…...

【统计子矩阵——部分前缀和+双指针】
题目 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; const int N 510; int s[N][N]; int main() {ios::sync_with_stdio(0);cin.tie(0);int n, m, k;cin >> n >> m >> k;for(int i 1; i < n; i)for(int j 1; j <…...

用正则表达式检查是IP否为内网地址
用正则表达式检查是ip否为内网地址 PHP function isIntranet($ip) {/* IPV4内网地址A 类10.0.0.0~10.255.255.255B 类172.16.0.0~172.31.255.255C 类192.168.0.0~192.168.255.255*/// 检查是否为 IPv4 内网地址if (preg_match(/^10\./, $ip…...

Leetcode刷题笔记14
136. 只出现一次的数字 136. 只出现一次的数字 - 力扣(LeetCode) 核心思想:按位异或运算 利用按位异或运算的性质来解决这个问题: 异或运算的性质: a ^ a 0:相同的数异或结果为0。 a ^ 0 a:…...

PHP图书绘本借阅管理系统小程序源码
📚 图书绘本借阅管理系统:打造孩子的阅读乐园 📚 🏷️ 引言:为什么我们需要图书绘本借阅管理系统? 在孩子的成长旅程中,阅读是不可或缺的一部分。然而,面对琳琅满目的图书和绘本&a…...

【JavaWeb】JavaWeb入门之XML详解
目录 1.XML介绍 1.1.XML概述 1.1.1.什么是XML 1.1.2.XML的作用 1.1.3.XML与HTML的比较 1.1.4.XML和properties(属性文件)比较 1.1.5.W3C组织 1.2.XML语法概述 1.2.1.XML文档展示 1.2.2.XML文档的组成部分 1.3.XML文档声明 1.3.1.什么是XML文…...

JS手写-this绑定实现
在 JavaScript 中,bind、call 和 apply 方法都可以用来改变函数的 this 指向。下面我们将分别实现这些方法的简单版本。 1. 实现 bind bind 方法创建一个新的函数,在调用时设置 this 值,并返回这个新的函数。 Function.prototype.myBind …...

【时间之外】IT人求职和创业应知【31】
目录 新闻一:2024年“秦创原沣东杯”陕西省科技工作者创新创业大赛颁奖仪式暨沣东新城机器人产业发展大会盛大启幕 新闻二:声网CEO赵斌:RTE将成为生成式AI时代AI Infra的关键部分 新闻三:“5G工业互联网”融合应用试点城市名单…...

如何使用ffmpeg命令行进行录屏
录屏软件,我们去网上下载,发现有很多软件都是要收费的!但是录屏功能很难做吗?为啥都需要收费呢? 于是我整了个小demo,用于实现基础的屏幕录制功能。 思路很简单,考虑到 FFMpeg.exe是一个非常成…...

ODOO学习笔记(8):模块化架构的优势
灵活性与可定制性 业务流程适配:企业的业务流程往往因行业、规模和管理方式等因素而各不相同。Odoo的模块化架构允许企业根据自身的具体业务流程,选择和组合不同的模块。例如,一家制造企业可以启用采购、库存、生产和销售模块,并通…...

数字IC后端实现之Innovus specifyCellEdgeSpacing和ICC2 set_placement_spacing_rule的应用
昨天帮助社区IC训练营学员远程协助解决一个Calibre DRC案例。通过这个DRC Violation向大家分享下Innovus和ICC2中如何批量约束cell的spacing rule。 数字IC后端手把手实战教程 | Innovus verify_drc VIA1 DRC Violation解析及脚本自动化修复方案 下图所示为T12nm A55项目的Ca…...

每日小练:Day2
1.乒乓球筐 题目链接:乒乓球筐__牛客网 题目描述: 这道题主要考察B盒是不是A盒的子集,我们可以通过哈希表来做 单哈希表 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public stat…...

ubuntu 安装kafka-eagle
上传压缩包 kafka-eagle-bin-2.0.8.tar.gz 到集群 /root/efak 目录 cd /root/efak tar -zxvf kafka-eagle-bin-2.0.8.tar.gz cd /root/efak/kafka-eagle-bin-2.0.8 mkdir /root/efakmodule tar -zxvf efak-web-2.0.8-bin.tar.gz -C /root/efakmodule/ mv /root/efakmodule/efak…...

深入理解指针
在初步了解了指针的用法之后,我们可以想一想,既然一个变量有地址,而且在上一篇文章中我们知道了一个数组也有地址,那么函数、字符串这些东西有没有地址呢?如果有,那这些地址有什么用?我们又要怎…...

自动驾驶合集(更新中)
文章目录 车辆模型控制路径规划 车辆模型 车辆模型基础合集 控制 控制合集 路径规划 规划合集...

Chapter 14 scoped样式以及data函数
欢迎大家订阅【Vue2Vue3】入门到实践 专栏,开启你的 Vue 学习之旅! 文章目录 1 scoped样式1.1 全局样式1.2 局部样式1.3 工作原理2 data函数 1 scoped样式 1.1 全局样式 全局样式是指作用于整个应用程序的样式,不论在哪个组件中定义&#x…...

Golang | Leetcode Golang题解之第557题反转字符串中的单词III
题目: 题解: func reverseWords(s string) string {length : len(s)ret : []byte{}for i : 0; i < length; {start : ifor i < length && s[i] ! {i}for p : start; p < i; p {ret append(ret, s[start i - 1 - p])}for i < le…...