简介:在Web开发领域,HTML、CSS和JavaScript构成了构建现代网页的基石,它们分别负责结构、样式和交互。理解这三者的协同工作原理,是前端工程师入门的关键。通过语义化标签、Flexbox/Grid布局以及原生JavaScript事件处理,开发者能够创建出结构清晰、响应迅速且交互友好的用户界面。这种技术组合在构建展示型网站、企业官网等静态页面时具有极高的实用价值,能有效提升开发效率与代码可维护性。本文以一份完整的旅游网站源码为例,深入剖析了其目录结构、响应式设计策略及轮播图、表单验证等核心功能的实现细节,为初学者提供了从学习到二次开发的清晰路径。
1. 项目概述:一份旅游网站源码的价值与定位
最近在整理硬盘时,翻出了几年前自己刚入行前端时,为了练手做的一个旅游网站项目。当时为了它熬了好几个通宵,从设计稿到一行行代码敲出来,踩了不少坑,也学到了很多东西。现在看,这个项目的代码可能算不上多么“高大上”,但它的结构清晰、功能完整,包含了从HTML骨架、CSS样式到JavaScript交互的完整实现,非常适合前端新手作为学习模板,或者作为二次开发的起点。所以,我决定把这个项目的核心源码和搭建思路整理出来,分享给大家。
这个项目本质上是一个静态的、展示型的旅游网站。它不涉及后端数据库和服务器逻辑,纯粹由HTML、CSS和JavaScript(也就是我们常说的前端三件套)构建而成。这意味着你拿到源码后,不需要配置复杂的PHP、Java或Node.js环境,只需要一个浏览器和一个代码编辑器(比如VSCode、Sublime Text甚至记事本)就能直接运行和修改。对于想学习网页制作基础、理解前端代码如何协同工作,或者想快速拥有一个可定制化网站模板的朋友来说,这是一个非常理想的“练手素材”。
它能做什么?简单来说,它模拟了一个旅游公司或个人的品牌展示网站。你通常会看到:一个吸引人的首页轮播图(Banner),展示热门目的地;清晰的产品分类导航,比如“国内游”、“出境游”、“自由行”;详细的目的地介绍页面,图文并茂;一个模拟的“联系我们”表单;以及适应不同屏幕尺寸的响应式布局。所有这些功能,都是用最基础的HTML、CSS和JS实现的,没有使用任何像Vue、React这样的重型框架,这让它的学习曲线非常平缓,你能清晰地看到每一行代码是如何影响最终页面的。
2. 源码结构与核心文件拆解
拿到一个源码包,第一件事就是理清它的目录结构。这就像看一张地图,能让你快速找到想去的地方。我这个旅游网站的源码结构遵循了最常见、也最推荐给新手的组织方式。
2.1 目录树与文件职责
travel-website/ ├── index.html # 网站首页,入口文件 ├── about.html # “关于我们”页面 ├── destinations.html # “旅游目的地”列表页 ├── contact.html # “联系我们”页面 ├── css/ # 存放所有样式表文件 │ ├── style.css # 全局主样式文件 │ ├── responsive.css # 响应式布局样式(针对手机、平板) │ └── normalize.css # 标准化样式,消除浏览器默认差异 ├── js/ # 存放所有JavaScript脚本文件 │ ├── main.js # 全局通用交互逻辑 │ ├── slider.js # 首页轮播图专属逻辑 │ └── form-validation.js # 联系表单的简单验证逻辑 ├── images/ # 存放网站所有图片资源 │ ├── banner/ # 首页轮播大图 │ ├── destinations/ # 各目的地展示图 │ └── icons/ # 图标素材(如logo、社交图标) └── assets/ # 其他静态资源(可选) └── fonts/ # 自定义字体文件为什么这样组织?
- 分离关注点:这是Web开发的核心原则之一。HTML负责结构(骨架),CSS负责表现(皮肤和衣服),JS负责行为(动作)。分文件夹存放,逻辑清晰,便于维护。你绝不会想在一个几百行的HTML文件里同时写样式和脚本,那会是场灾难。
- 模块化CSS/JS:将CSS和JS按功能拆分。比如,
slider.js只管理轮播图,form-validation.js只处理表单。这样,当你想修改轮播功能时,不需要在庞大的main.js里大海捞针,直接找到对应文件即可。这也为后续可能的模块化打包(如使用Webpack)打下了基础。 - 资源分类:图片按用途分文件夹,找图、换图都方便。使用
normalize.css或reset.css是专业做法,它能抹平不同浏览器(Chrome, Firefox, Safari)对默认标签样式的微小差异,让你的样式从一个更一致的起点开始,减少很多莫名其妙的布局问题。
2.2 HTML骨架:语义化标签的实践
我们打开index.html,看看它的基本结构。一个好的HTML结构不仅是为了浏览器渲染,更是为了可读性和可访问性。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>探索世界 | 您的专属旅行顾问</title> <link rel="stylesheet" href="css/normalize.css"> <link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/responsive.css" media="screen and (max-width: 768px)"> <link rel="icon" href="images/icons/favicon.ico" type="image/x-icon"> </head> <body> <header class="site-header"> <nav class="main-nav">...</nav> </header> <main> <section class="hero-banner">...</section> <section class="featured-destinations">...</section> <section class="services">...</section> </main> <footer class="site-footer">...</footer> <script src="js/main.js"></script> <script src="js/slider.js" defer></script> </body> </html>核心要点解析:
<!DOCTYPE html>:这是文档类型声明,告诉浏览器这是一个HTML5文档。必须放在第一行。<html lang=“zh-CN”>:指定文档语言为简体中文。这对搜索引擎优化(SEO)和屏幕阅读器等辅助工具非常重要。- Viewport Meta标签:
<meta name=“viewport” ...>是实现响应式设计的基石。width=device-width告诉浏览器使用设备宽度作为视口宽度,initial-scale=1.0设置初始缩放比例为1。没有它,在移动设备上你的页面可能会被缩得很小。 - 语义化标签:注意我使用了
<header>,<nav>,<main>,<section>,<footer>,而不是一堆<div>。语义化标签能让代码结构一目了然,也利于SEO爬虫理解页面结构。 - CSS引入顺序:先引入
normalize.css重置默认样式,再引入主样式style.css,最后通过媒体查询引入responsive.css。这个顺序保证了样式的正确覆盖。 - JS引入与
defer属性:main.js放在</body>前引入,避免阻塞页面渲染。对于slider.js这种不依赖DOM完全加载的脚本,可以使用defer属性,让它等到HTML解析完毕后再执行,且顺序得到保证。
注意:很多新手会把所有CSS和JS都堆在
<head>里。JS放<head>会阻塞渲染,导致页面长时间白屏。最佳实践是CSS放<head>(尽早加载样式),JS放</body>前或使用async/defer属性。
3. 核心样式(CSS)设计与技巧
CSS是把设计稿变成网页的关键。这个项目中,我主要运用了Flexbox布局、CSS Grid进行局部排版,并精心设计了一套响应式方案。
3.1 布局系统的选择:Flexbox vs. Grid
对于整个页面的宏观布局(如头部导航、页脚列),我选择了Flexbox。因为它在一维布局(沿水平或垂直方向排列项目)上非常直观和强大。
/* css/style.css 中导航栏示例 */ .main-nav { display: flex; justify-content: space-between; /* 左右两端对齐 */ align-items: center; /* 垂直居中对齐 */ padding: 1rem 5%; background-color: #fff; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .nav-links { display: flex; list-style: none; gap: 2rem; /* 项目之间的间隙,现代且简洁的写法 */ } .nav-links a { text-decoration: none; color: #333; font-weight: 500; transition: color 0.3s ease; }为什么用Flexbox?justify-content和align-items几乎可以解决所有常见的对齐需求,代码简洁。gap属性直接设置间距,比用margin更优雅,且不会产生外边距合并的问题。
对于产品展示区这种二维布局(同时控制行和列),我使用了CSS Grid。
/* css/style.css 中目的地网格示例 */ .destinations-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.5rem; padding: 2rem 5%; }auto-fill和minmax()的妙用:这行代码的意思是,创建尽可能多的列,每列的最小宽度是280px,最大是1fr(等分剩余空间)。当容器宽度变化时,它会自动调整列数。在宽屏下可能显示4列,在窄屏下自动变为2列甚至1列,这是实现响应式布局的“魔法”之一,无需编写多个媒体查询。
3.2 响应式设计的实现策略
响应式设计不是可选项,而是现代网站的标配。我的策略是“移动优先”,即先编写移动端的基本样式,再通过媒体查询(Media Queries)为更大屏幕添加或覆盖样式。
/* css/responsive.css - 针对平板及以下设备 */ @media screen and (max-width: 768px) { .main-nav { flex-direction: column; /* 移动端导航改为垂直排列 */ padding: 0.5rem; } .nav-links { flex-direction: column; gap: 1rem; width: 100%; text-align: center; } .hero-banner h1 { font-size: 2rem; /* 移动端标题缩小 */ } .destinations-grid { grid-template-columns: 1fr; /* 移动端单列显示 */ gap: 1rem; } } /* 在css/style.css中,可能还有针对更大屏幕的补充 */ @media screen and (min-width: 1200px) { .container { max-width: 1140px; /* 在大屏幕上限制最大宽度,避免一行文字过长 */ margin: 0 auto; } }实操心得:
- 断点选择:不要盲目跟风使用 Bootstrap 的断点(如 576px, 768px)。应根据你实际内容的布局断裂点来设置。用浏览器开发者工具拖动窗口大小,观察内容在哪个宽度下变得不美观或难以使用,那个宽度就是你的断点。
remvspx:我大量使用了rem作为字体和间距单位。1rem等于根元素(<html>)的字体大小。我通常设置html { font-size: 62.5%; },这样1rem = 10px(因为浏览器默认16px * 62.5% = 10px),计算起来非常方便。使用rem还能更好地支持用户调整浏览器字体大小。
3.3 常见CSS问题与调试技巧
盒子模型塌陷(Margin Collapse):当两个垂直相邻块级元素的上下外边距相遇时,它们会合并成一个外边距,其大小为两者中的较大者。这经常导致布局与预期不符。
- 解决方案:使用
padding替代margin,或者为父元素添加overflow: hidden或display: flow-root(创建新的BFC),或者使用Flexbox/Grid布局(它们的子项不会发生外边距合并)。
- 解决方案:使用
Flex/Grid项目宽度超出容器:有时设置了
flex: 1或grid-template-columns: 1fr 1fr,但内容(比如一张很宽的图片或一个长单词)会把项目撑开。- 解决方案:为项目设置
min-width: 0。这看起来有点反直觉,但它告诉浏览器:“这个项目可以收缩到小于其内容的最小宽度”。或者对内容本身使用overflow: hidden; text-overflow: ellipsis;或word-break: break-all。
- 解决方案:为项目设置
CSS特异性(Specificity)战争:你写了一个样式规则,但就是不生效,因为被另一个更“具体”的选择器覆盖了。
- 调试技巧:使用浏览器开发者工具的“元素检查”(Inspect)。它会清晰显示所有应用到该元素上的样式规则,并用删除线标出被覆盖的规则。优先使用类选择器(
.class),避免过度使用ID选择器(#id)和行内样式,它们特异性太高,难以覆盖。
- 调试技巧:使用浏览器开发者工具的“元素检查”(Inspect)。它会清晰显示所有应用到该元素上的样式规则,并用删除线标出被覆盖的规则。优先使用类选择器(
4. 交互功能(JavaScript)实现详解
静态页面是骨架,JavaScript赋予了它生命。这个项目中的JS代码都是原生(Vanilla JS)编写,没有依赖jQuery,这能让你更好地理解浏览器原生API。
4.1 首页轮播图(Slider)实现
轮播图是展示类网站的常见组件。我实现了一个简单的“渐隐渐现”效果轮播。
// js/slider.js document.addEventListener('DOMContentLoaded', function() { const slides = document.querySelectorAll('.slide'); const dots = document.querySelectorAll('.dot'); const prevBtn = document.querySelector('.slider-prev'); const nextBtn = document.querySelector('.slider-next'); let currentSlide = 0; const totalSlides = slides.length; let slideInterval; // 初始化:显示第一张,激活第一个指示点 function showSlide(n) { // 隐藏所有幻灯片和取消所有激活点 slides.forEach(slide => slide.classList.remove('active')); dots.forEach(dot => dot.classList.remove('active')); // 计算正确的索引(处理循环) currentSlide = (n + totalSlides) % totalSlides; // 显示当前幻灯片和激活对应点 slides[currentSlide].classList.add('active'); dots[currentSlide].classList.add('active'); } // 下一张/上一张 function nextSlide() { showSlide(currentSlide + 1); } function prevSlide() { showSlide(currentSlide - 1); } // 指示点点击事件 dots.forEach((dot, index) => { dot.addEventListener('click', () => { clearInterval(slideInterval); // 点击后暂停自动轮播 showSlide(index); // 可以在这里重新启动自动轮播,设置一个延时 // restartAutoSlide(); }); }); // 按钮事件 nextBtn.addEventListener('click', () => { clearInterval(slideInterval); nextSlide(); // restartAutoSlide(); }); prevBtn.addEventListener('click', () => { clearInterval(slideInterval); prevSlide(); // restartAutoSlide(); }); // 自动轮播(可选) function startAutoSlide() { slideInterval = setInterval(nextSlide, 5000); // 每5秒切换 } // 初始化显示和启动自动轮播 showSlide(0); startAutoSlide(); // 鼠标悬停暂停(提升用户体验) const sliderContainer = document.querySelector('.slider-container'); sliderContainer.addEventListener('mouseenter', () => clearInterval(slideInterval)); sliderContainer.addEventListener('mouseleave', startAutoSlide); });关键点解析:
DOMContentLoaded事件:确保脚本在DOM树构建完成后执行,这样才能正确找到.slide等元素。- 状态管理:用
currentSlide变量记录当前显示的是第几张,这是核心状态。 - CSS类控制显示:通过添加或移除
.active类来控制幻灯片的显示/隐藏和指示点的激活状态。对应的CSS可能是这样的:.slide { opacity: 0; transition: opacity 0.8s ease; position: absolute; width: 100%; } .slide.active { opacity: 1; position: relative; } - 用户体验细节:实现了鼠标悬停暂停、点击指示点或按钮后暂停自动轮播。这很重要,因为用户可能正在仔细看某张图片,突然的自动切换会打断他。
4.2 表单验证与交互反馈
“联系我们”页面有一个简单的表单,前端验证可以即时给用户反馈,避免提交明显错误的数据到后端(虽然这个静态项目没有后端)。
// js/form-validation.js const contactForm = document.getElementById('contactForm'); const nameInput = document.getElementById('name'); const emailInput = document.getElementById('email'); const messageInput = document.getElementById('message'); function showError(input, message) { const formGroup = input.parentElement; formGroup.classList.add('error'); const errorDisplay = formGroup.querySelector('.error-message') || document.createElement('small'); if(!formGroup.querySelector('.error-message')) { errorDisplay.className = 'error-message'; errorDisplay.style.color = '#e74c3c'; formGroup.appendChild(errorDisplay); } errorDisplay.textContent = message; } function showSuccess(input) { const formGroup = input.parentElement; formGroup.classList.remove('error'); formGroup.classList.add('success'); const errorDisplay = formGroup.querySelector('.error-message'); if(errorDisplay) { errorDisplay.textContent = ''; } } function isValidEmail(email) { const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(String(email).toLowerCase()); } contactForm.addEventListener('submit', function(e) { e.preventDefault(); // 阻止表单默认提交行为 let isValid = true; // 验证姓名 if(nameInput.value.trim() === '') { showError(nameInput, '姓名不能为空'); isValid = false; } else { showSuccess(nameInput); } // 验证邮箱 if(emailInput.value.trim() === '') { showError(emailInput, '邮箱不能为空'); isValid = false; } else if (!isValidEmail(emailInput.value.trim())) { showError(emailInput, '邮箱格式不正确'); isValid = false; } else { showSuccess(emailInput); } // 验证留言 if(messageInput.value.trim() === '') { showError(messageInput, '留言内容不能为空'); isValid = false; } else if (messageInput.value.trim().length < 10) { showError(messageInput, '留言内容至少10个字符'); isValid = false; } else { showSuccess(messageInput); } // 如果全部验证通过 if(isValid) { // 在实际项目中,这里应该是Ajax提交到后端 // 此处模拟提交成功 alert('感谢您的留言!我们会尽快与您联系。'); contactForm.reset(); // 清空表单 // 移除所有成功状态 document.querySelectorAll('.form-group').forEach(group => group.classList.remove('success')); } }); // 实时验证(提升用户体验) nameInput.addEventListener('input', () => { if(nameInput.value.trim() !== '') { showSuccess(nameInput); } }); emailInput.addEventListener('blur', () => { // 失去焦点时验证 if(emailInput.value.trim() !== '' && isValidEmail(emailInput.value.trim())) { showSuccess(emailInput); } else if (emailInput.value.trim() !== '') { showError(emailInput, '邮箱格式不正确'); } });经验之谈:
- 正则表达式验证邮箱:上面的正则是一个比较通用的模式,但请注意,没有正则能100%匹配所有有效的RFC标准邮箱。在实际生产环境中,更常见的做法是:前端做一个基础格式校验(如包含
@和.),把更严格的校验交给后端,或者直接发送验证邮件。 trim()方法:非常重要!它去除用户输入首尾的空格,避免因为不小心多打了空格导致验证失败。- 用户体验:除了提交时验证,我还添加了
input和blur事件的实时验证。input事件在用户输入时触发,可以即时清除错误状态;blur事件在用户离开输入框时触发,适合做格式校验(如邮箱)。这比只在提交时一次性报错友好得多。 - CSS配合:
.error和.success类会对应改变输入框的边框颜色,并显示/隐藏错误信息。这需要提前在CSS中定义好样式。
4.3 移动端导航菜单切换
在移动端,导航栏通常会折叠成一个“汉堡包”菜单图标。
// 在js/main.js中 const hamburger = document.querySelector('.hamburger-menu'); const navLinks = document.querySelector('.nav-links'); hamburger.addEventListener('click', () => { navLinks.classList.toggle('active'); hamburger.classList.toggle('is-active'); // 用于动画图标(如变成X) }); // 点击菜单外区域关闭菜单(提升体验) document.addEventListener('click', (e) => { if (!hamburger.contains(e.target) && !navLinks.contains(e.target)) { navLinks.classList.remove('active'); hamburger.classList.remove('is-active'); } });对应的CSS需要控制移动端下.nav-links的显示与隐藏,以及汉堡图标到关闭图标的动画变换。
5. 二次开发与学习指南
拿到源码后,如何让它变成你自己的项目?这里提供几个明确的方向和步骤。
5.1 如何定制化修改
更换内容(文字与图片):
- 文字:直接用编辑器打开各个
.html文件,找到对应的段落、标题进行修改。 - 图片:将你的图片放入
images/对应的文件夹,然后在HTML或CSS中修改图片路径。注意图片优化:网页图片应使用jpg(照片)、png(透明背景)、webp(更优的现代格式)或svg(图标、Logo)。使用工具(如TinyPNG、Squoosh)压缩图片,在不明显损失质量的前提下减小文件体积,能极大提升页面加载速度。
- 文字:直接用编辑器打开各个
修改样式(主题色、字体、布局):
- 主题色:在
css/style.css文件顶部,定义CSS变量(Custom Properties)来管理颜色是个好习惯。例如:
然后在整个CSS中使用这些变量(:root { --primary-color: #3498db; /* 主色调 */ --secondary-color: #2ecc71; /* 次要色调 */ --text-color: #333; --light-bg: #f9f9f9; }color: var(--primary-color);)。想换主题?只需修改这几个变量的值。 - 字体:通过Google Fonts或中文的站酷字库、方正字库引入喜欢的字体。在CSS的
@import或<link>引入后,在body或特定选择器中设置font-family。 - 布局:通过调整
.container的max-width、网格的grid-template-columns、Flex容器的justify-content等属性来改变布局结构。
- 主题色:在
增加新页面:
- 复制一个现有的
.html文件(如about.html),重命名为newpage.html。 - 修改
<title>和<main>标签内的内容。 - 别忘了在主导航
nav-links中添加指向这个新页面的链接。
- 复制一个现有的
5.2 从学习到进阶:下一步可以做什么
这个静态网站是一个完美的起点,但Web开发的世界远不止于此。基于此,你可以尝试以下挑战:
引入构建工具:手动管理CSS和JS文件在项目变大后会变得混乱。学习使用Vite或Webpack。它们可以帮你:
- 将多个JS文件打包成一个,减少HTTP请求。
- 使用Sass/Less等CSS预处理器,编写更强大、可维护的样式。
- 自动添加CSS浏览器前缀(Autoprefixer)。
- 压缩代码,优化图片。
添加简单的“动态”功能:
- 用本地存储(LocalStorage)实现“收藏”功能:在目的地卡片上添加一个心形图标,点击后,使用
localStorage.setItem()将目的地ID存储起来。即使页面刷新,收藏状态也能保持。 - 从公共API获取数据:学习使用JavaScript的
fetch()API,从一个免费的旅游数据API(需自行搜索可用的公共API)获取目的地列表,并动态渲染到页面上,替代硬编码在HTML里的数据。这会让你初步接触前后端分离的概念。
- 用本地存储(LocalStorage)实现“收藏”功能:在目的地卡片上添加一个心形图标,点击后,使用
连接后端,变成全栈项目:
- 学习Node.js + Express:搭建一个简单的后端服务器,将“联系我们”的表单数据真正保存到数据库(如MongoDB)或发送到你的邮箱。
- 学习一门后端语言:如Python(Django/Flask)、PHP等,实现用户登录、评论、订单管理等更复杂的功能。
- 部署上线:使用Vercel、Netlify(静态托管)或Heroku、Railway(全栈托管)等平台,将你的网站部署到公网,让所有人都能访问。
5.3 常见问题排查(Q&A)
在复现或修改这个项目时,你可能会遇到以下问题:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 页面打开是空白或样式混乱 | 1. 文件路径错误。 2. 浏览器缓存。 | 1. 检查开发者工具Console和Network面板,看是否有404错误。确保href=“css/style.css”的路径相对于当前HTML文件是正确的。2. 按 Ctrl+F5或Cmd+Shift+R强制刷新。 |
| 轮播图不自动播放或点击没反应 | 1. JS文件未正确引入或路径错误。 2. JS代码中存在语法错误。 3. DOM元素类名与JS选择器不匹配。 | 1. 检查Console是否有“Uncaught ReferenceError”或“Failed to load resource”错误。 2. 检查Console是否有红色错误信息,定位到具体行号修改。 3. 用开发者工具检查元素,确认 .slide、.dot等类名是否与JS代码中的querySelector参数一致。 |
| 在手机上布局错乱 | 1. 缺少Viewport meta标签。 2. 响应式CSS媒体查询未生效或写错。 3. 图片宽度未做限制。 | 1. 确认<head>中有<meta name=“viewport” ...>。2. 检查 responsive.css是否被引入,媒体查询条件(如max-width: 768px)是否正确。3. 为图片添加 max-width: 100%; height: auto;样式。 |
| 表单验证总是失败 | 1. 输入值首尾有空格。 2. 验证逻辑条件太严格。 | 1. 确保在JS比较值之前使用了.trim()方法。2. 检查正则表达式或长度判断条件,可以先 console.log()输出值进行调试。 |
| 字体或图标不显示 | 1. 字体文件路径错误。 2. 网络字体加载慢或跨域问题。 | 1. 检查字体文件路径。 2. 考虑将网络字体(如Google Fonts)下载到本地 assets/fonts/目录,使用@font-face引入,提升加载速度和稳定性。 |
这个项目源码就像一本打开的书,每一行代码都讲述着前端基础是如何组合在一起创造一个完整产品的故事。我建议你不要只停留在“看”和“运行”,动手去改,去“破坏”它——比如故意删掉一行关键的CSS,看看页面会变成什么样;或者尝试用另一种方式实现轮播图。在这个过程中遇到的问题和解决问题的经历,才是你真正学到的东西。
本文还有配套的精品资源,点击获取