zoukankan      html  css  js  c++  java
  • Nuxt.js打造旅游网站第2篇_首页开发

    页面效果:

    1.初始化默认布局

    nuxtjs提供了一个公共布局组件layouts/default.vue,该布局组件默认作用于所有页面,所以我们可以在这里加上一些公共样式,在下一小结中还会导入公共组件。

    替换layouts/default.vue代码如下:

    <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>
    layouts/default.vue

    2.新建公共组件

    思路:

    1.在components中新建需要复用的头部组件和页脚组件

    2.在默认布局中layouts/default.vue中导入公共组件

    组件约定:公共组件不需要放到子文件夹中

    下拉组件文档:https://element.eleme.cn/#/zh-CN/component/dropdown#ji-chu-yong-fa

    实现步骤

    头部组件

    components文件夹中新建头部组件components/header.vue

    <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 {
       1000px;
      margin: 0 auto;
      height: 60px;
      line-height: 60px;
      
    }
    
    .logo {
      margin-right: 20px;
      img {
         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{
         36px;
        height: 36px;
        vertical-align: middle;
        border-radius: 50%;
      }
    }
    </style>
    header.vue

    layouts/default.vue中导入头部组件

    <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>
    default.vue

    页脚组件

    components文件夹中新建头部组件components/footer.vue

    <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- 1000px;
      }
      
      .footer{
        padding-top: 30px;
        margin: 0 auto;
         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{
           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>
    footer.vue

    layouts/default.vue中导入页脚组件

    <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>

    总结:

    1. layouts/default.vue是默认的布局组件,会作用于任何页面。

    2. layouts/default.vue中导入全局的头部组件和页脚组件

    3.首页轮播图和TAB栏

    pages/index.vue内容替换成以下代码:

    <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- 1000px;
      margin: 0 auto;
      position: relative; /* 相对定位 */
    
      /deep/ .el-carousel__container {
        height: 700px;
      }
      .banner-image {
         100%;
        height: 100%;
      }
    
      .banner-content {
        z-index: 9;
         1000px;
        position: absolute;
        left: 50%;
        top: 45%;
        margin-left: -500px;
        border-top: 1px transparent solid;
    
        .search-bar {
           552px;
          margin: 0 auto;
        }
    
        .search-tab {
          .active {
            i {
              color: #333;
            }
            &::after {
              background: #eee;
            }
          }
    
          span{
             82px;
            height: 36px;
            display: block;
            position: relative;
            margin-right: 8px;
            cursor: pointer;
            
            i{
              position: absolute;
              z-index: 2;
              display: block;
               100%;
              height: 100%;
              line-height: 30px;
              text-align: center;
              color: #fff;
            }
    
            &::after{
              position: absolute;
              left: 0;
              top: 0;
              display: block;
              content: "";
               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{
           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>
  • 相关阅读:
    GC垃圾回收算法
    Docker+nginx部署Springboot+vue前后端分离项目
    报错 ImportError: cannot import name 'AsyncContextManager'
    Python+Selenium定位不到元素(报错:selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element)
    淘宝网的发展史及其优缺点
    Python旅途——函数(1)
    正则表达式 -允许输入数字和小数点后两位
    表单的resetFileds函数重置为初始值而非清空数据
    做一个全局登录弹窗,任何地方访问
    浏览器到服务器的跨域问题
  • 原文地址:https://www.cnblogs.com/replaceroot/p/11168460.html
Copyright © 2011-2022 走看看