Nuxt.js打造旅游网站第2篇_首页开发
页面效果:
1.初始化默认布局
<template> <div> <!-- 内容占位组件 --> <nuxt /> </div> </template> <script> export default { } </script> <style lang="less"> html { font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 16px; word-spacing: 1px; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; box-sizing: border-box; } *{ margin:0; padding:0; } ul, li, ol{ list-style:none; } a{ text-decoration:none; color:inherit; } a:hover{ } em,i{ font-style: normal; } </style>
2.新建公共组件
思路:
1.在components中新建需要复用的头部组件和页脚组件
2.在默认布局中layouts/default.vue中导入公共组件
组件约定:公共组件不需要放到子文件夹中
下拉组件文档:https://element.eleme.cn/#/zh-CN/component/dropdown#ji-chu-yong-fa
实现步骤
头部组件
<template> <div class="container"> <el-row type="flex" class="main" justify="space-between"> <!-- logo --> <div class="logo"> <nuxt-link to="/"> <img src="http://157.122.54.189:9093/images/logo.jpg" alt /> </nuxt-link> </div> <!-- 菜单 --> <el-row type="flex" class="navs"> <nuxt-link to="/">首页</nuxt-link> <nuxt-link to="/post">旅游攻略</nuxt-link> <nuxt-link to="/hotel">酒店</nuxt-link> <nuxt-link to="/air">机票</nuxt-link> </el-row> <!-- 右侧登录注册 --> <div class="right-login"> <div v-if="false"> <nuxt-link to="/user/login">登录/注册</nuxt-link> </div> <div> <el-dropdown> <span class="el-dropdown-link"> <img src="http://157.122.54.189:9095/assets/images/avatar.jpg" alt=""> 托马斯 <i class="el-icon-arrow-down el-icon--right"></i> <!-- 小箭头 --> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>个人中心</el-dropdown-item> <el-dropdown-item>退出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </div> </div> </el-row> </div> </template> <script> export default {}; </script> <style lang="less" scoped> .container { box-shadow: 0 2px 2px #ddd; } .main { width: 1000px; margin: 0 auto; height: 60px; line-height: 60px; } .logo { margin-right: 20px; img { width: 156px; height: 42px; margin-top: 9px; } } .navs { margin: 0 20px; flex: 1;/* 让所有弹性盒模型对象的子元素都有相同的长度,且忽略它们内部的内容: */ a { display: block; padding: 0 20px; height: 60px; box-sizing: border-box; &:hover { color: #409eff; border-bottom: 5px #409eff solid; } } /deep/ .nuxt-link-exact-active { /* /deep/ 是为了重置element-ui组件中的样式*/ background: #409eff; color: #fff; &:hover { color: #fff; } } } .el-dropdown-link{ img{ width: 36px; height: 36px; vertical-align: middle; border-radius: 50%; } } </style>
<template> <div> <Header></Header> <!-- 内容的占位符,类似router-view --> <nuxt /> </div> </template> <script> import Header from '@/components/header' export default { // 注册组件 components: { Header } } </script> <style> html { font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 16px; word-spacing: 1px; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; box-sizing: border-box; } *{ margin:0; padding:0; } ul, li, ol{ list-style: none; } a{ color:inherit; text-decoration: none; } em,i{ font-style: normal; } </style>
<template> <div class="footer-wrapper"> <div class="footer"> <el-row class="info-list"> <el-col :span="6" :offset="1"> <h5>闲云旅游网</h5> <p>上亿旅行者共同打造的旅游神器</p> <p> <span>60,000</span>多个全球旅游目的地 </p> <p> <span>60,000</span>个细分目的地新玩法 </p> <p> <span>760,000,000</span>次攻略下载 </p> <p> <span>38,000</span>家旅游产品供应商 </p> </el-col> <el-col :span="5"> <h5>关于我们</h5> <p>隐私政策 商标声明</p> <p>服务协议 游记协议</p> <p>商城平台服务协议</p> <p>网络信息侵权通知指引</p> <p>闲云旅游旅游网服务监督员</p> <p>网站地图加入闲云旅游</p> </el-col> <el-col :span="5"> <h5>旅行服务</h5> <p>旅游攻略 酒店预订</p> <p>旅游特价 国际租车</p> <p>旅游问答 旅游保险</p> <p>旅游指南 订火车票</p> <p>旅游资讯 APP下载</p> </el-col> <el-col :span="6" class="scan"> <p> <img src="http://157.122.54.189:9093/images/1556522965.png" alt /> </p>关注我们 </el-col> </el-row> <div class="licence"> 京ICP备08001421号 京公网安备110108007702 Copyright © 2016-2019 博学谷 All Rights Reserved </div> </div> </div> </template> <script> export default {}; </script> <style lang="less" scoped> .footer-wrapper{ background: #333; color: #ccc; min-width: 1000px; } .footer{ padding-top: 30px; margin: 0 auto; width: 1000px; } .info-list{ h5{ font-weight: normal; font-size: 16px; margin-bottom: 10px; } p{ font-size: 12px; line-height: 1.8; span{ color: skyblue; font-weight: bold; font-style: italic; } } } .scan{ text-align: center; img{ width: 140px; height: 140px; } font-size: 12px; } .licence{ border-top: 1px #666 solid; margin-top: 20px; padding: 50px 0; text-align: center; font-size: 12px; } </style>
<template> <div> <Header></Header> <!-- 内容的占位符,类似router-view --> <nuxt /> <Footer></Footer> </div> </template> <script> import Header from '@/components/header' import Footer from '@/components/footer' export default { // 注册组件 components: { Header, Footer } } </script>
总结:
-
-
在
layouts/default.vue
中导入全局的头部组件和页脚组件
3.首页轮播图和TAB栏
<template> <div class="container"> <!-- 轮播图 --> <el-carousel :interval="3000" arrow="hover"> <el-carousel-item v-for="(item,index) in banners" :key="index"> <div class="banner-image" :style="` background: url(${$axios.defaults.baseURL + item.url}) center center no-repeat; background-size:contain contain; `" ></div> </el-carousel-item> </el-carousel> <!-- 搜索框 --> <div class="banner-content"> <div class="search-bar"> <!-- tab栏 --> <el-row type="flex" class="search-tab"> <span v-for="(item, index) in tabs" :key="index" :class="{active: currentTab === index}" @click="handleChangeTab(index)" > <i>{{item.name}}</i> </span> </el-row> <!-- 输入框 --> <el-row type="flex" align="middle" class="search-input"> <input :placeholder="tabs[currentTab].placeholder" /> <i class="el-icon-search"></i> </el-row> </div> </div> </div> </template> <script> export default { // data是一个函数,返回一个对象 data() { return { banners: [], currentTab: 0, // tab栏的数据 tabs: [ { name: "攻略", placeholder: "搜索城市" }, { name: "酒店", placeholder: "请输入搜索酒店的城市" }, { name: "机票", placeholder: "", pageUrl: "/air" } ] }; }, methods: { // tab栏切换 handleChangeTab(index) { // 如果点击的是机票,跳转到机票页面 if (index === 2) { this.$router.push("/air"); } // 修改当前高亮显示 this.currentTab = index; } }, // 页面加载时自动执行的生命周期函数 mounted() { // 这里可以使用this.$axios是因为框架已经自动帮我们把axios绑定到原型上了 // 手动将axios绑定到原型上的方法:Vue.prototype.$axios = axios this.$axios({ url: "/scenics/banners", method: "GET" }).then(res => { const { data } = res.data; this.banners = data; }); } }; </script> <style lang="less" scoped> .container { min-width: 1000px; margin: 0 auto; position: relative; /* 相对定位 */ /deep/ .el-carousel__container { height: 700px; } .banner-image { width: 100%; height: 100%; } .banner-content { z-index: 9; width: 1000px; position: absolute; left: 50%; top: 45%; margin-left: -500px; border-top: 1px transparent solid; .search-bar { width: 552px; margin: 0 auto; } .search-tab { .active { i { color: #333; } &::after { background: #eee; } } span{ width: 82px; height: 36px; display: block; position: relative; margin-right: 8px; cursor: pointer; i{ position: absolute; z-index: 2; display: block; width: 100%; height: 100%; line-height: 30px; text-align: center; color: #fff; } &::after{ position: absolute; left: 0; top: 0; display: block; content: ""; width: 100%; height: 100%; border: 1px rgba(255, 255, 255, .2) solid; border-bottom: none; transform: scale(1.1,1.3) perspective(.7em) rotateX(2.2deg); transform-origin: bottom left; background: rgba(0, 0, 0, .5); border-radius: 1px 2px 0 0; box-sizing: border-box; } } } .search-input{ width: 550px; height: 46px; background: #ffffff; border-radius: 0 4px 4px 4px; border: 1px rgba(255, 255, 255, .2) solid; border-top: none; box-sizing: unset; input{ flex: 1; height: 20px; padding: 13px 15px; outline: none; border: 0; font-size: 16px; } .el-icon-search{ cursor: pointer; font-size: 22px; padding: 0 10px; font-weight: bold; } } } } </style>