
简介一款以Vue和Scss构建的西安游玩主题网页设计源码面向前端学习者与旅游类站点开发者用于展示城市文化、特色景点与美食信息并传达“我爱大西安”的主题。资源共24个文件压缩包约61KB包含5个Vue组件、4个JSON配置、3个JavaScript脚本以及HTML页面、SCSS样式表和9张PNG图片组件化结构便于理解页面拆分与模块复用Scss样式以变量和混合功能提升维护效率脚本与配置负责交互适配与功能设置。已有104人学习浏览。从内容预览看页面涵盖首页、游玩、个人、问答等模块JSON配置可分别实现应用与页面路由的设置状态管理脚本用于维护用户信息图片资源则覆盖导航图标、轮播展示和景点素材。开发者可借此掌握Vue组件组织方式、页面配置思路、基于Scss的主题样式写法并参考readme说明快速搭建或改造自己的城市旅游宣传页面。1. 一个西安游玩页为什么值得用 Vue Scss 重做这类页面在课程设计、文旅作品集和企业内部展示页里都常见但很多人拿着“基于Vue和Scss的西安游玩主题网页设计源码”跑起来第一眼往往是样式没生效、图片资源丢失、拖进浏览器直接白屏。原因不是Vue本身难而是工程侧细节没接住Scss变量没有进全局、资源路径写成绝对路径、样式覆盖顺序冲突。下面基于 Vite Vue3 sass 把景点数据、主题变量、响应式断点分层讲清楚每段配置都能直接复用到你自己的主题页面。内容不依赖后端接口纯静态数据也能撑起完整页面适合正在做课程设计或想快速搭一个文旅类型静态站的读者。2. 搭建 Vue Scss 工程依赖安装与变量接入2.1 为什么选 Vue 写内容页而不是 htmlcssjs 硬扛内容型网页的特征是结构重复、数据批量、视觉统一。纯 htmlcssjs 虽然能写但每加一个景点就复制一段 DOM后续维护成本指数上涨。Vue 的组件化把“景点卡片”“路线条目”“美食卡片”变成同一份模板改样式只动一处。Scss 则补上原生 CSS 缺少的变量、嵌套和 mixin适合把西安主题的配色与断点抽成一套令牌。两者结合正好回应标题里“西安游玩主题”最核心的诉求把内容、样式、逻辑分离想换城市时只需替换数据文件和主题变量。很多团队的 Vue 项目实战里Scss 只是被当作“能嵌套的 CSS”来用这其实浪费了它最值得用的能力。真正能拉开差距的是变量体系、混合宏和模块化组织。下面从工程初始化开始把这条链路完整走一遍。2.2 vue 安装及环境配置的正确命令先确认 node 版本在 16 以上。用 Vite 创建项目再补装 sass 依赖npm create vitelatest xian-tour -- --template vue cd xian-tour npm install npm install -D sass npm run dev这里每一行都有明确作用第一行从 npm 仓库拉取 create-vite 脚手架--template vue生成最小 Vue3 项目npm install安装基础依赖npm install -D sass把 sass 编译器装进开发依赖Vite 识别.scss文件时自动调用它编译npm run dev启动本地开发服务器默认端口 5173。注意-D别写成--savesass 只在构建期需要不该进入生产依赖。如果 node 版本较新安装依赖时可能遇到依赖损坏的情况常见补救是删掉node_modules和锁文件后重装rm -rf node_modules package-lock.json npm install这是 vue 安装依赖阶段最容易踩到的问题。还有一个版本兼容点sass 主版本建议选 1.77 以上如果公司镜像源较旧可以指定版本安装npm install -D sass1.77.8装完用npx sass --version验证。2.3 Scss 全局变量进入全部组件的配置方式Vue 单文件组件里写 Scss直接在 style 标签加langscss即可style langscss scoped .card { background: $wall-gray; } /style但每个组件都手动use一次变量文件就太啰嗦。常见做法是在vite.config.js里配置 additionalData让所有组件自动拿到主题变量和 mixinimport { defineConfig } from vite import vue from vitejs/plugin-vue import path from path export default defineConfig({ plugins: [vue()], resolve: { alias: { // 让 import 和 use 都能用短路径 : path.resolve(__dirname, src) } }, css: { preprocessorOptions: { scss: { // 每个组件的 style 块都会自动注入这段引用 additionalData: use /assets/styles/variables.scss as *; } } } })说明as *让变量名进来后不必写前缀直接使用$wall-gray。注意 additionalData 里只放变量、mixin、函数这类无实际输出的内容如果把具体选择器样式写进去每个组件都会复制一份打包体积会明显膨胀。变量名取值用途$wall-gray#6b6b6b城墙砖灰正文主色$palace-red#a63b2e宫墙红主按钮与高亮$copper-green#00755e碑林铜绿辅助点缀$glass-yellow#d5a021琉璃黄标签和标记变量命名建议用语义词而非颜色名词。取名为$palace-red比$red更直观后面换一套城市配色时只需改变量文件组件代码一行不用动。这套结构决定了 Scss 在项目里不是装饰品而是真正的主题层。3. 西安游玩主题的组件拆解与景点数据组织3.1 页面层级怎么切这种内容单页我一般按这个层级拆分App.vue只负责布局骨架包含页头、Hero 区、内容主体和页脚区块级组件放进src/components每个业务域一个子目录sights/管景点、food/管美食、route/管路线。组件之间靠 props 单向传数据不搞复杂状态管理。src/ assets/styles/ variables.scss mixins.scss components/ layout/ SiteHeader.vue SiteFooter.vue sights/ SightList.vue SightCard.vue route/ RouteTabs.vue data/ spots.js App.vue main.js这个目录在“西安游玩主题”场景下足够清晰。SightCard 是纯展示组件接收一个景点对象SightList 负责拿到数组后循环渲染。纯展示组件不写业务逻辑后续改为请求接口时只需替换数据来源视图层完全不动。3.2 景点数据的静态组织方式没有后端时用一个src/data/spots.js导出静态数据export const spots [ { id: 1, name: 秦始皇兵马俑, category: 遗址, district: 临潼区, duration: 3, price: 120, recommend: true }, { id: 2, name: 大雁塔北广场, category: 古迹, district: 雁塔区, duration: 2, price: 0, recommend: true } // 更多数据... ]字段设计上有讲究字段类型说明idNumber唯一标识v-for 的 keynameString景点名称categoryString分类用于筛选标签districtString所属行政区路线规划用durationNumber建议游玩小时priceNumber门票参考价0 表示免费recommendBoolean是否标记为推荐在组件里渲染时key 的写法常被忽略。v-forspot in spots一定要配:keyspot.id用 index 做 key 在筛选和排序后会让 DOM 复用错位轻则样式错乱重则事件绑定混乱。template section classsight-list aria-label西安推荐景点 article v-forspot in spots :keyspot.id classsight-card :class{ sight-card--hot: spot.recommend } img v-ifspot.cover :srcspot.cover :altspot.name loadinglazy div classsight-card__body h3{{ spot.name }}/h3 p{{ spot.category }} · 建议 {{ spot.duration }} 小时/p p classsight-card__price{{ spot.price ? ¥ spot.price : 免费 }}/p /div /article /section /template数据渲染之外筛选功能用一个 computed 就能解决不需要额外依赖import { ref, computed } from vue const activeCategory ref(全部) const showSpots computed(() activeCategory.value 全部 ? spots : spots.filter((spot) spot.category activeCategory.value) )把activeCategory绑定到一组按钮上点击时切换值列表自动过滤。这里的细节是 computed 返回的是一个新数组不会修改原数据源这种写法在切换筛选条件时不会残留脏数据。3.3 主题样式怎么落到组件上样式按模块划分后组件内只写局部样式共用间距统一从全局变量里拿。比如在variables.scss里定义$spacing-unit: 8px组件内写padding: $spacing-unit * 2要调整整站间距时只改一个变量。如果希望限定 class 语义更明确可以做个占位背景色函数但在这个项目里容易过度设计。比这更实际的做法是在mixins.scss里放常用复用块比如卡片的圆角与阴影、正文截断组件直接引入mixin text-ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }这里要说清楚一个边界Scss 工具化能提升效率但不代表要把所有东西都抽象成 mixin。页面只有三五处text-overflow时直接写样式反而更好读抽象过多会让后续维护的人在多个文件之间跳转。4. Scss 响应式适配与图片地图落地细节4.1 用 min-width 断点做移动优先布局内容型页面面向手机端浏览响应式应该优先保证小屏可用。我习惯用min-width而非max-width默认样式服务手机媒体查询里只放大屏差异。断点通过 Sass Map 集中管理use sass:map; $breakpoints: ( md: 768px, lg: 1024px, xl: 1280px ); mixin respond($bp) { media (min-width: map.get($breakpoints, $bp)) { content; } }组件里这样使用卡片列表在手机端单列平板上双列桌面三列.sight-list { display: grid; grid-template-columns: 1fr; gap: 16px; include respond(md) { grid-template-columns: repeat(2, 1fr); } include respond(lg) { grid-template-columns: repeat(3, 1fr); } }这里有个容易翻车的顺序问题基础样式必须写在媒体查询之前否则同等优先级下后写的规则会覆盖断点样式导致断点完全不生效。断点区间适用设备典型布局0 - 767px手机单列导航折叠768px - 1023px平板双列导航展开1024px - 1279px桌面三列内容居中1280px 以上大屏内容区限制最大宽度4.2 图片懒加载与首屏占位景点页面图片多不懒加载时首屏会一次性发几十个请求移动端体验很差。原生loadinglazy已经足够不需要引第三方库也不用手写 IntersectionObserver。Vue 里的写法就是普通的:src绑定后加一个属性。但注意首屏图不要加懒加载。首屏之上的图片如果懒加载部分浏览器会推迟请求反而造成闪白或跳动。更稳妥的做法是给 Hero 区容器设置背景色和最小高度.hero { background-color: $wall-gray; min-height: 240px; }等图片加载完成后由 img 自身撑开高度视觉上从灰底平滑过渡到图片。进一步可以给图片容器设aspect-ratio提前占据版面位置避免布局偏移影响页面稳定性评分。4.3 地图接入的取舍方案西安游玩页大多想放一张地图。接百度地图或高德地图都需要先申请 Key再引 SDK域名白名单没配会导致地图区域空白这类问题在本地开发和部署环境之间反复出现。课程设计或静态演示场景下用静态示意图加列表坐标更稳妥。如果确实要接交互地图建议把初始化逻辑封装进组件Key 通过环境变量注入const mapKey import.meta.env.VITE_MAP_AK地图初始化在onMounted里执行组件卸载时注意销毁地图实例。否则在页面切换时旧实例没有释放内存会持续增长最终表现为页面越来越卡。封装地图组件的另一个好处是以后换地图供应商时只需要替换组件内部实现页面其它代码不需要改。我个人的倾向是没有明确的路线规划需求时先用 Scss 画一个示意区块景点名称配合所在行政区展示即可。外部依赖越少项目拿给别人复现时跑通率越高这对一个以“源码”为卖点的项目来说比花哨能力更关键。5. 打包后布局异常排查与 Vue DevTools 验证这也对应了搜索里最高频的“vue 打包后布局异常”。打包产物不等同于开发环境以下三个问题在拿到源码后最常遇到。5.1 资源路径 base 配置开发时 Vite 默认base是/构建产物扔到服务器子目录或直接用file://打开时脚本和样式路径完全对不上页面只剩空白或骨架。先在vite.config.js里改成相对路径export default defineConfig({ base: ./ })设置后 dist 里的资源引用都变成相对index.html的路径。但要注意如果项目用了createWebHistory路由刷新子路由会 404。当前这个游玩主题页是单页结构没引入 vue-router所以直接用相对路径没有副作用。凡是遇到构建后样式丢失、脚本 404第一排查项就是 base脚本异常校验可以等这一步完成后再做。5.2 构建与预览验证验证生产产物的命令npm run build npm run preview -- --port 4173build 会生成 dist 目录preview 用本机临时服务器加载构建产物端口可换成任意未占用值。重点看三件事控制台有无 404 资源、页面是否出现横向滚动、首屏图片是否正常展示。这里--port指定预演端口避免和其它端口冲突。Network 面板里同样值得过一遍JS 和 CSS 文件重复注入的问题能直接从文件体积上暴露。5.3 Vue DevTools 插件下载后的生效条件vue devtools 插件下载后看不到 Vue 标签页绝大多数情况不是插件坏了而是它只对开发环境生效。直接打开 dist 里的 index.html 或生产域名时面板不会出现只有访问 vite dev server 页面时才显示。想要快速确认源头在 main.js 里临时输出构建环境的根路径console.log(import.meta.env.BASE_URL)dev 环境输出/如果base: ./已生效产物中资源引用会变成./assets/...而不是/assets/...。每改一次 vite.config.js 都必须重新执行npm run buildpreview 只负责加载已经生成的 dist不会自动重建。这个顺序搞清楚后绝大多数 vue 打包后布局异常和资源丢失问题都能在十分钟内定位。本文还有配套的精品资源点击获取