旅游网站(携程旅行网页学习 vue3+element)

旅游网站

1. 创建项目

  1. 在你要创建项目的路径下打开vscode,新建终端,然后输入vue ui,进入Vue项目管理器。
  2. 选择"创建",确定项目路径,并点击"在此创建新项目"。
  3. 在项目文件夹中输入项目名称,点击下一步;
  4. 选择"手动配置项目",然后点击下一步;
  5. 增加选择"router"和"css"两个配置项,然后点击下一步;
  6. 选择 CSS 预处理器。node-sass 是自动编译实时的,dart-sass 需要保存后才会生效,此处建议选择 Sass/SCSS(with dart-sass);pick a linter / formatter config可以选择第一个,只检查错误。选择完成后就可以创建项目。
  7. 提示创建成功后可以用vscode打开新建的项目。

2. 新建首页

注意:App.vue是整个项目的入口文件,这个文件保持干净,后续内容多了,结构才不出错,所以新建一个首页index.vue

  1. 为避免系统提示要组合词命名文件的错误,在package.json文件中修改"rules"的值:

    json 复制代码
    "rules": {
          "vue/multi-word-component-names": "off"
        }
  2. 在src文件夹下的views文件夹中新建index.vue。在index.vue文件中,先设置一个简单页面,输入如下代码:(安装了插件就可以输入vue,然后选择默认vue结构,会自动补全vue结构)

    html 复制代码
    <template>
      <h1>首页</h1>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
  3. 按照路由的配置方法,在router文件下设置index.js文件,把不需要的路由删除或者注释。两步走,1引入子页面,2设置路由。

    代码如下

    js 复制代码
    import { createRouter, createWebHashHistory } from 'vue-router'
    // 1.引入
    import Index from '../views/index.vue'
    
    const routes = [
      // 2.设置路由
      {
        path: '/',
        name: 'home',
        component: Index
      } 
    ]
    
    const router = createRouter({
      history: createWebHashHistory(),
      routes
    })
    
    export default router

    如果显示index出错
    error Component name "index" should always be multi-word

    解决方式:

    在vue.config.js中添加代码lintOnSave:false

    后重启项目即可

  4. 修改App.vue文件为如下代码,在这个页面中引入需要的页

    html 复制代码
    <template>
      <router-view/>
    </template>

效果图:

3. 引入ElementPlus组件

  1. 用vscode打开项目,然后在终端中,项目路径下运行命令:npm install element-plus --save

  2. 在main.js文件中配置elementplus和ico图标库,导入方法见element官网,

    https://element-plus.org/zh-CN/,修改main.js为如下代码:

    js 复制代码
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    // ElementPlus 相关库的导入
    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
    import zhCn from 'element-plus/es/locale/lang/zh-cn'
    // 导入icon图标库
    import * as ElementPlusIconsVue from '@element-plus/icons-vue'
    // 导入暗黑模式主题,在index.html文件中:需在 html 上添加一个名为 dark 的类 
    import 'element-plus/theme-chalk/dark/css-vars.css'
    
    // 创建一个应用
    const app = createApp(App)
    // 注册elementplus
    app.use(ElementPlus, {
      locale: zhCn,
    })
    // 注册elementplus图标
    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
      app.component(key, component)
    }
    // 注册路由后挂载
    app.use(router).mount('#app')

4. 高仿携程旅游页面,制作index.vue

https://hotels.ctrip.com/?allianceid=4897\&sid=799747\&ouid=xiecheng370\&bd_creative=27771225887\&bd_vid=11944392447257964181\&keywordid=137481675338【携程旅游】

  1. 首页布局。进入element官网,https://element-plus.org/zh-CN/,选择组件,然后选择Basic 基础组件中的Container 布局容器。根据上面的图,选择左上下结构,复制代码。

  2. 粘贴到index.vue中里面并进行修改。此时也可以启动服务器查看布局结果

    代码如下:

    html 复制代码
    <template>
      <!-- <h1>首页</h1> -->
      <div class="common-layout">
        <el-container>
          <el-aside width="200px" class="test1">Aside</el-aside>
          <el-container>
            <el-header class="test2">Header</el-header>
            <el-main class="test3">Main</el-main>
          </el-container>
        </el-container>
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style lang="scss">
    .test1{
        background-color: rgb(177, 208, 255);
        height: 100vh;
    }
    .test2{
        background-color: rgb(110, 160, 235);
    }
    .test3{
        background-color: rgb(187, 239, 255);
    }
    
    </style>

    效果图:

  3. 将index.vue页面中的三个组成部分拆分成menu.vue、logo.vue和main.vue三个页

    (1)在views文件夹中新建menu.vue、logo.vue和main.vue三个页面,然后将这三个组成部分的代码分别输入到对应的页面中。具体如下:

html 复制代码
menu.vue代码:
<template>
   <el-aside width="200px">Aside</el-aside>
</template>

<script>
export default {

}
</script>

<style lang="scss">
.el-aside{
    background-color: rgb(177, 208, 255);
    height: 100vw;
}
</style>

logo.vue代码:
<template>
  <el-header>Header</el-header>
</template>

<script>
export default {

}
</script>

<style lang="scss">

.el-header{
  background-color: rgb(110, 160, 235);
}
</style>

main.vue代码:
<template>
  <el-main>Main</el-main>
</template>

<script>
export default {

}
</script>

<style lang="scss">

.el-main{
  background-color: rgb(187, 239, 255);
}

</style>

(2)修改index.vue,将三个组件页面引入到index.vue中,然后设置组件标签,代码如下:

html 复制代码
<template>
  <!-- <h1>首页</h1> -->
  <div class="common-layout">
    <el-container>
      <MenuView></MenuView>
      <el-container>
        <el-header><LogoView></LogoView></el-header>
        <el-main><MainView></MainView></el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script setup>
// 1.script 里加setup,引入要加载的子页面
    import MenuView from './menu.vue'
    import MainView from './main.vue'
    import LogoView from './logo.vue'
</script>

<style lang="scss">


</style>

效果图:

5. 制作左边菜单栏

功能是可以展开和隐藏菜单栏,所以要在elementplus中找到相对应的组件,想要的效果是munu菜单中的Collapse 折叠面板。

  1. 打开Collapse 折叠面板的代码,分析其哪些功能代码是我们需要的,不要直接全部复制。leftmenu.vue的代码如下:

    html 复制代码
    <template>
      <el-aside width="200px">
        <!-- 1.隐藏展开按钮 -->
          <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
            <el-radio-button :value="false">expand</el-radio-button>
            <el-radio-button :value="true">collapse</el-radio-button>
          </el-radio-group>
          <!-- 2菜单标签 -->
          <el-menu
          default-active="2"
          class="el-menu-vertical-demo"
          :collapse="isCollapse"
          @open="handleOpen"
          @close="handleClose"
        >
          <!-- 3根据页面的布局需要第二组菜单项 -->
          <el-menu-item index="2">
            <el-icon><icon-menu /></el-icon>
            <template #title>酒店</template>
          </el-menu-item>
        </el-menu>
    
      </el-aside>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    // 设置isCollapse的值为true,用于控制展开或隐藏
    const isCollapse = ref(true)
    // 导入icon图标,没用到的组件导入会报错,可以在package.json文件中
    // 增加一条rules:"no-unused-vars": "off"
    import {
      Document,
      Menu as IconMenu,
      Location,
      Setting,
    } from '@element-plus/icons-vue'
    </script>
    
    <style>
    .el-menu-vertical-demo:not(.el-menu--collapse) {
      width: 200px;
      min-height: 400px;
    }
    </style>
  2. 启动服务器,查看此时网页效果

    效果图:

  3. 修改上面的代码,实现与网站几乎相同的效果。

(1)将展开隐藏按钮标签放入到菜单标签,并将展开隐藏的文字提示改为"|||",并且将两个标签设置v-show属性,展开的时候显示,隐藏的时候隐藏标识符号。

(2)在script里面定义左侧菜单数组

(3)在菜单项中通过v-for去实现显示菜单组

(4)更改icon图标,可以在icon图标库中复制图标名字加到已导入的图标项中

(5)修改菜单项中设置icon图标的代码,实现动态加载图标

leftmenu.vue的代码改动为如下所示:

vue 复制代码
<template>
    <el-aside width="200px">

        <!-- 1.隐藏展开按钮 -->
        <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
            <!-- <el-radio-button :value="false">expand</el-radio-button>
            <el-radio-button :value="true">collapse</el-radio-button> -->
            <!-- 6.修改为:将展开隐藏按钮标签放入到菜单标签,
            并将展开隐藏的文字提示改为"|||",
            并且将两个标签设置v-show属性,展开的时候显示,隐藏的时候隐藏标识符号 -->
            <el-radio-button :value="false" v-show="isCollapse">|||</el-radio-button>
            <el-radio-button :value="true" v-show="!isCollapse">|||</el-radio-button>
        </el-radio-group>
        <!-- 2菜单标签 -->
        <el-menu default-active="2" class="el-menu-vertical-demo" 
        :collapse="isCollapse" @open="handleOpen" @close="handleClose">
        <!-- 3根据页面的布局需要第二组菜单项 -->
            <!-- <el-menu-item index="2">
                <el-icon><icon-menu /></el-icon>
                <template #title>酒店</template>
            </el-menu-item> -->
            <!-- 8.需要多个这个菜单项就用v-for实现-->
            <el-menu-item index="v.id" v-for="v in asidelist" :key="v.id">
                <!-- 11.实现动态icon图标 -->
                <el-icon><component :is="v.icon"></component></el-icon>
                <template #title>{{v.title}}</template>
            </el-menu-item>
        </el-menu>
    </el-aside>
</template>

<script setup>
import { ref } from "vue";

// 设置isCollapse的值为true,用于控制展开或隐藏
const isCollapse = ref(true)
// 导入icon图标,没用到的组件导入会报错,可以在package.json文件中
// 增加一条rules:"no-unused-vars": "off"
import {
    Document,
    Menu as IconMenu,
    Location,
    Setting,
    // 9.增加新的图标
    OfficeBuilding,
    Bowl
} from '@element-plus/icons-vue'

// 7.定义左侧菜单数组,10.增加icon
let asidelist=ref([
    {id:1,title:'酒店',icon:OfficeBuilding},
    {id:2,title:'机票',icon:Document},
    {id:3,title:'火车票',icon:Setting},
    {id:4,title:'旅游',icon:Bowl},
    {id:5,title:'景点',icon:Location},
    {id:6,title:'汽车票',icon:Document},
    {id:7,title:'船票',icon:IconMenu},
    {id:8,title:'门票',icon:OfficeBuilding},
])
</script>

<style lang="scss">
.el-aside{
    background-color: rgb(177, 208, 255);

}
.el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    min-height: 400px;
}
</style>
  1. 启动服务器,查看此时的显示效果

  2. 调整按钮位置

    vue 复制代码
    <template>
        <el-aside width="200px">
    
            
            <!-- 菜单标签 -->
            <el-menu 
                default-active="2" 
                class="el-menu-vertical-demo" 
                :collapse="isCollapse" 
                @open="handleOpen" 
                @close="handleClose"
            >
                <!-- 隐藏展开按钮 -->
                <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
                    <el-radio-button :value="false" v-show="isCollapse">|||</el-radio-button>
                    <el-radio-button :value="true" v-show="!isCollapse">|||</el-radio-button>
                </el-radio-group>
    
                <!-- 需要多个这个菜单项就用v-for实现-->
                <el-menu-item index="v.id" v-for="v in asidelist" :key="v.id">
                    <!-- 实现动态icon图标 -->
                    <el-icon><component :is="v.icon"></component></el-icon>
                    <template #title>{{v.title}}</template>
                </el-menu-item>
            </el-menu>
        </el-aside>
    </template>
    
    <script setup>
    import { ref } from "vue";
    
    // 设置isCollapse的值为true,用于控制展开或隐藏
    const isCollapse = ref(true)
    // 导入icon图标,没用到的组件导入会报错,可以在package.json文件中
    // 增加一条rules:"no-unused-vars": "off"
    import {
        Document,
        Menu as IconMenu,
        Location,
        Setting,
        // 9.增加新的图标
        OfficeBuilding,
        Bowl
    } from '@element-plus/icons-vue'
    
    // 定义左侧菜单数组,10.增加icon
    let asidelist=ref([
        {id:1,title:'酒店',icon:OfficeBuilding},
        {id:2,title:'机票',icon:Document},
        {id:3,title:'火车票',icon:Setting},
        {id:4,title:'旅游',icon:Bowl},
        {id:5,title:'景点',icon:Location},
        {id:6,title:'汽车票',icon:Document},
        {id:7,title:'船票',icon:IconMenu},
        {id:8,title:'门票',icon:OfficeBuilding},
    ])
    </script>
    
    <style lang="scss">
    .el-aside{
        background-color: rgb(177, 208, 255);
    
    }
    .el-menu-vertical-demo:not(.el-menu--collapse) {
        width: 200px;
        min-height: 400px;
    }
    </style>

    效果:

6. 字体图标的引入

  1. 下载第三方图标,进入阿里巴巴矢量图库https://www.iconfont.cn/?spm=a313x.manage_type_myprojects.i3.2.74bc3a812ze26a,并保存在src中

  2. 全局引入

    在main.js中加上代码import '@/assets/font/iconfont.css'

  3. 修改menu中代码

    vue 复制代码
    <template>
        <el-aside width="200px">
    
            
            <!-- 菜单标签 -->
            <el-menu 
                default-active="2" 
                class="el-menu-vertical-demo" 
                :collapse="isCollapse" 
                @open="handleOpen" 
                @close="handleClose"
            >
                <!-- 隐藏展开按钮 -->
                <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
                    <el-radio-button :value="false" v-show="isCollapse">|||</el-radio-button>
                    <el-radio-button :value="true" v-show="!isCollapse">|||</el-radio-button>
                </el-radio-group>
    
                <!-- 需要多个这个菜单项就用v-for实现-->
                <el-menu-item index="v.id" v-for="v in asidelist" :key="v.id">
                    <!-- 实现动态icon图标 -->
                    <!-- <el-icon><component :is="v.icon"></component></el-icon> -->
                    <i class="iconfont" :class="v.icon"></i>
                    <template #title>{{v.title}}</template>
                </el-menu-item>
            </el-menu>
        </el-aside>
    </template>
    
    <script setup>
    import { ref } from "vue";
    
    // 设置isCollapse的值为true,用于控制展开或隐藏
    const isCollapse = ref(true)
    
    // 导入icon图标,没用到的组件导入会报错,可以在package.json文件中
    // 增加一条rules:"no-unused-vars": "off"
    import {
        Document,
        Menu as IconMenu,
        Location,
        Setting,
        // 9.增加新的图标
        OfficeBuilding,
        Bowl
    } from '@element-plus/icons-vue'
    
    // 定义左侧菜单数组,10.增加icon
    // let asidelist=ref([
    //     {id:1,title:'酒店',icon:OfficeBuilding},
    //     {id:2,title:'机票',icon:Document},
    //     {id:3,title:'火车票',icon:Setting},
    //     {id:4,title:'旅游',icon:Bowl},
    //     {id:5,title:'景点',icon:Location},
    //     {id:6,title:'汽车票',icon:Document},
    //     {id:7,title:'船票',icon:IconMenu},
    //     {id:8,title:'门票',icon:OfficeBuilding},
    // ])
    
    // 引入第三方图标
    let asidelist = ref([
        {id:1,title:'酒店',icon:'icon-jiudian'},
        {id:2,title:'机票',icon:'icon-lvxing'},
        {id:3,title:'火车票',icon:'icon-huoche'},
        {id:4,title:'旅游',icon:'icon-lvyou1'},
        {id:5,title:'景点',icon:'icon-jingdian'},
        {id:6,title:'汽车票',icon:'icon-tuijianqiche'},
        {id:7,title:'船票',icon:'icon-lunchuan'},
        {id:8,title:'门票',icon:'icon-menpiao'},
    ])
    </script>
    
    <style lang="scss">
    .el-aside{
        background-color: rgb(177, 208, 255);
    
    }
    .el-menu-vertical-demo:not(.el-menu--collapse) {
        width: 200px;
        min-height: 400px;
    }
    </style>
  4. 图标效果

7. 左侧导航栏样式

  1. 新建样式index.css

  2. 代码

    index.css

    css 复制代码
    /* 左侧导航栏 */
    .aside {
        width: 200px;
    }
    .aside-list {
         /* 固定定位 */
        position: fixed;
        left: 0;
        width: 200px;
    }
    .aside .el-menu {
        height:100vh;
    
    }
    /* 字体图标的样式 */
    .aside i {
        font-size: 24px;
        font-weight: 500;
        margin-right: 5px;
    }
    .aside .el-radio-button__inner {
        border:none;
        font-size: 20px;
    }

​ menu.vue

vue 复制代码
<template>
    
    <el-aside width="200px" class="aside">
        <div class="aside-list">
            <!-- 菜单标签 -->
            <el-menu 
                default-active="2" 
                class="el-menu-vertical-demo" 
                :collapse="isCollapse" 
                @open="handleOpen" 
                @close="handleClose"
            >
                <!-- 隐藏展开按钮 -->
                <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
                    <el-radio-button :value="false" v-show="isCollapse">|||</el-radio-button>
                    <el-radio-button :value="true" v-show="!isCollapse">|||</el-radio-button>
                </el-radio-group>

                <!-- 需要多个这个菜单项就用v-for实现-->
                <el-menu-item index="v.id" v-for="v in asidelist" :key="v.id">
                    <!-- 实现动态icon图标 -->
                    <!-- <el-icon><component :is="v.icon"></component></el-icon> -->
                    <i class="iconfont" :class="v.icon"></i>
                    <template #title>{{v.title}}</template>
                </el-menu-item>
            </el-menu>
        </div>
        
    </el-aside>
</template>

<script setup>
import { ref } from "vue";

// 设置isCollapse的值为true,用于控制展开或隐藏
const isCollapse = ref(true)

// 导入icon图标,没用到的组件导入会报错,可以在package.json文件中
// 增加一条rules:"no-unused-vars": "off"
import {
    Document,
    Menu as IconMenu,
    Location,
    Setting,
    // 9.增加新的图标
    OfficeBuilding,
    Bowl
} from '@element-plus/icons-vue'

// 定义左侧菜单数组,10.增加icon
// let asidelist=ref([
//     {id:1,title:'酒店',icon:OfficeBuilding},
//     {id:2,title:'机票',icon:Document},
//     {id:3,title:'火车票',icon:Setting},
//     {id:4,title:'旅游',icon:Bowl},
//     {id:5,title:'景点',icon:Location},
//     {id:6,title:'汽车票',icon:Document},
//     {id:7,title:'船票',icon:IconMenu},
//     {id:8,title:'门票',icon:OfficeBuilding},
// ])

// 引入第三方图标
let asidelist = ref([
    {id:1,title:'酒店',icon:'icon-jiudian'},
    {id:2,title:'机票',icon:'icon-lvxing'},
    {id:3,title:'火车票',icon:'icon-huoche'},
    {id:4,title:'旅游',icon:'icon-lvyou1'},
    {id:5,title:'景点',icon:'icon-jingdian'},
    {id:6,title:'汽车票',icon:'icon-tuijianqiche'},
    {id:7,title:'船票',icon:'icon-lunchuan'},
    {id:8,title:'门票',icon:'icon-menpiao'},
])
</script>

<style lang="scss">

</style>
```
  1. 引入样式

    在main.js中import '@/assets/css/index.css'

  2. 效果图

    遇到问题:

    1. 隐藏张开按钮会跟随移动

    解决方式:

    ​ 修改#appde 样式

    ​ 删除text-align: center

    如不清楚,请看12.位置区域中的解决方式

8. 头部导航栏

  1. 修改logo.vue中的代码

    vue 复制代码
    <template>
      <div>
        <div class="headerNav">
          <!-- logo -->
          <div class="header-logo">logo</div>
          <!-- 搜索框 -->
          <div class="header-search">搜索框</div>
          <!-- 导航菜单 -->
          <div class="header-right">导航菜单</div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style lang="scss">
    
    .el-header{
      background-color: rgb(110, 160, 235);
    }
    </style>

​ 效果图:

  1. 横向排列、固定定位

    修改index.css文件

    css 复制代码
    /* 页面头部 */
    /* 宽度响应 */
    .el-header {
        min-width: 1280px;
    }
    .headerNav {
        display: flex;
        justify-content: space-between;
        align-items: center;
        /* 水平垂直对齐 */
        height: 70px;
        width:1620px;
        /* 固定定位 */
        position:fixed;
        top:0;
        background-color: #fff;
        z-index: 999;
        padding: 10px 0;
    }

    删除logo.vue中定义的css样式

  2. 效果图

  3. logo图

  4. 修改代码

    vue 复制代码
    <template>
      <div>
        <div class="headerNav">
          <!-- logo -->
          <div class="header-logo">
            <img src="@/assets/images/logo.png" alt="">
          </div>
          <!-- 搜索框 -->
          <div class="header-search">搜索框</div>
          <!-- 导航菜单 -->
          <div class="header-right">导航菜单</div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style lang="scss">
    
    </style>
  5. 修改样式

    css 复制代码
    .headerNav {
        display: flex;
        justify-content: space-between;
        align-items: center;
        /* 水平垂直对齐 */
        height: 70px;
        width:1400px;
        /* 固定定位 */
        position:fixed;
        top:0;
        background-color: #fff;
        z-index: 999;
        padding: 10px 0;
    }
    .headerNav img {
        width: 100%;
        height: 50px;
    }

    效果图:

9. 搜索框

  1. 官网地址Input 输入框 | Element Plus (element-plus.org)

  2. 修改代码

    logo.vue

    vue 复制代码
    <template>
      <div>
        <div class="headerNav">
          <!-- logo -->
          <div class="header-logo">
            <img src="@/assets/images/logo.png" alt="">
          </div>
          <!-- 搜索框 -->
          <div class="header-search">
            <el-input
                v-model="input3"
                placeholder="请输入内容"
                class="input-with-select"
                >
                <template #append>
                    <el-button :icon="Search" />
                </template>
            </el-input>
          </div>
          <!-- 导航菜单 -->
          <div class="header-right">导航菜单</div>
        </div>
      </div>
    </template>
    
    <script setup>
    //引入搜索图标
    import { Search } from '@element-plus/icons-vue'
    </script>
    
    <style lang="scss">
    
    </style>

    index.css

    css 复制代码
    .header-search {
        flex: 1;
        margin: 0 2rem;
    }
    /* 按钮的颜色  */
    .headerNav .el-input-group__append {
        background-color: var(--el-color-primary);
        color: #fff;
    }
    .heaer-right .el-link {
        margin: 0 20px;
    }

    效果图:

10. 头部下拉菜单

  1. 官网Link 链接 | Element Plus (element-plus.org)

  2. 修改代码

    logo.vue

    vue 复制代码
    <template>
      <div>
        <div class="headerNav">
          <!-- logo -->
          <div class="header-logo">
            <img src="@/assets/images/logo.png" alt="">
          </div>
          <!-- 搜索框 -->
          <div class="header-search">
            <el-input
                v-model="input3"
                placeholder="请输入内容"
                class="input-with-select"
                >
                <template #append>
                    <el-button :icon="Search" />
                </template>
            </el-input>
          </div>
          <!-- 导航菜单 -->
          <div class="header-right">
            <el-link :icon="Avatar">请登录</el-link>
            <el-link target="_blank">注册</el-link>
            <el-link>
              <el-dropdown>
                  <span class="el-dropdown-link">
                  我的订单
                  <el-icon class="el-icon--right">
                      <arrow-down />
                  </el-icon>
                  </span>
                  <template #dropdown>
                    <el-dropdown-menu>
                        <el-dropdown-item v-for="v in Myorder" :key="v.id">{{v.title}}</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
              </el-dropdown>
            </el-link>
          </div>
        </div>
      </div>
    </template>
    
    <script setup>
    //引入搜索图标
    import { Search,Avatar,ArrowDown } from '@element-plus/icons-vue'
    import { ref } from 'vue'
    //下拉列表
    let Myorder = ref([
        {id:1,title:'酒店订单'},
        {id:2,title:'火车票订单'},
        {id:3,title:'飞机票订单'},
        {id:4,title:'旅游订单'},
        {id:5,title:'全部订单'}
    ])
    </script>
    
    <style lang="scss">
    
    </style>

    index.css

    css 复制代码
    .header-right .el-link {
        margin: 0 20px;
    }
    /* 伪类选择器:可以用来选取获得焦点的元素
    当鼠标移入上去后取消黑色边框 */
    .el-dropdown-link:focus{
       outline: none;
    }

    效果图:

11. 区域模块

  1. 修改代码

    main.vue

    vue 复制代码
    <template>
      <div class="searchlist">
        <div class="searchlist-item">1</div>
        <div class="searchlist-item">2</div>
        <div class="searchlist-item">3</div>
        <div class="searchlist-item">4</div>
        <div class="searchlist-item">5</div>
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style lang="scss">
    
    </style>

    index.css

    css 复制代码
    /* 区域展示部分 */
    .searchlist {
        width: 1400px;
        display: grid;
        grid-template-columns: repeat(5,auto);
        margin-top: 15px;
    }
    .searchlist-item {
        border: 1px solid #dadada;
        margin-left: -1px;
    }

    效果图:

  2. 内部搜索框、时间选择器

    遇到问题

    输入框一直有黑边

    解决方式

    css中增加input样式

    main.vue

    vue 复制代码
    <template>
      <div class="searchlist">
        <div class="searchlist-item">
            <div class="search-box">
              <!-- 使用for和id进行表单绑定 -->
                <label for="hotels-destination">目的地/酒店名称</label>
                <input class="input" type="text" id="hotels-destination" placeholder="北京">
            </div>
        </div>
        <div class="searchlist-item">
            <div class="search-box">
                <label>入住时间/退房时间</label>
                <el-date-picker
                    v-model="value1"
                    type="datetimerange"
                    start-placeholder="Start Date"
                    end-placeholder="End Date"
                    :default-time="defaultTime1"
                    />
            </div>
        </div>
        <div class="searchlist-item">
              <div class="search-box">
                <label for="room-guest">房间及住客</label>
                <input class="input" type="text" id="room-guest" placeholder="1间/1位">
            </div>
        </div>
        <div class="searchlist-item">
              <div class="search-box">
                <label for="keyword">关健词(选填)</label>
                <input class="input" type="text" id="keyword" placeholder="火车/酒店名称或区域">
            </div>
        </div>
        <div class="searchlist-item">
            <el-button type="primary" :icon="Search"></el-button>
        </div>
      </div>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    import {Search} from '@element-plus/icons-vue'
    </script>
    
    <style lang="scss">
    
    </style>

    index.css

    css 复制代码
    /* 右侧下面展示 */
    .el-main {
        min-width: 1280px;
        overflow: hidden;
    }
    /* 目的地/酒店名称 */
    .search-box {
        padding: 8px 12px;
    }
    .search-box label {
        color: #999;
        display: block;
    }
    .search-box input {
        border:none;
        font-size: 16px;
        font-weight: 700;
        padding-top: 15px;
    }
    
    .input{
        outline: none;
    }
    /* 伪类选择器,当元素获得焦点的时候,能够控制父元素的样式 */
    .searchlist-item:focus-within {
        border-bottom: 2px solid var(--el-color-primary);
    }
    /* 入住时间/退房时间 取消边框的颜色 */
    .search-box .el-date-editor.el-input__wrapper {
        box-shadow:none;
    }
    .search-box .el-date-editor.el-input__wrapper:hover {
        box-shadow:none;
    }
    /* 搜索按钮的样式 */
    .searchlist-item .el-button {
        width: 100%;
        height:100%;
        border-radius: 0;
    }
    .searchlist-item .el-button .el-icon {
        font-size: 30px;
    }

    效果图:

12. 位置区域

使用网格布局

  1. 新建页面,并在index.vue中加入页面

    vue 复制代码
    <template>
      <!-- <h1>首页</h1> -->
     
      <div class="common-layout">
        <el-container>
          <MenuView></MenuView>
          <el-container>
            <el-header><LogoView></LogoView></el-header>
            <el-main><MainView></MainView></el-main>
            <el-top><Toplist></Toplist></el-top>
          </el-container>
        </el-container>
      </div>
    </template>
    
    <script setup>
        // 1.script 里加setup,引入要加载的子页面
        import MenuView from './menu.vue'
        import MainView from './main.vue'
        import LogoView from './logo.vue'
        import Toplist from './toplist.vue';
    </script>
    
    <style lang="scss">
    
    
    </style>
  2. 修改代码

    toplist.vue

    vue 复制代码
    <template>
      <div class="topfilter">
        <div>
          <h4>位置区域</h4>
        </div>
        <!-- tabs切换 -->
        <div class="topfilter-tab">
          <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
            <!-- 数据绑定 -->
            <el-tab-pane :label="v.label" :name="v.name" v-for="v in topfilterlist" :key="v.id">
              <el-button  v-for="(k,i) in v.list" :key="i" size="small" type="info" plain>{{k}}</el-button>
            </el-tab-pane>
          </el-tabs>
        </div>
        <div>
          <h4>星级价格</h4>
        </div>
        <div class="topfilter-price">
            <el-button size="small" type="info" plain v-for="(v,i) in pricelist" :key="i">{{v}}</el-button>
        </div>
        <div>
          <h4>高级筛选</h4>
        </div>
        <div class="topfilter-filter">
            <el-dropdown v-for="(v,i) in filterlist" :key="i">
                <span class="el-dropdown-link">
                  {{v.title}}
                  <el-icon class="el-icon--right">
                    <!-- 箭头按钮 -->
                    <arrow-down />
                  </el-icon>
                </span>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item v-for="(k,i) in v.list" :key="i">{{k}}</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
          </el-dropdown>
        </div>
      </div>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    //箭头图标
    import { ArrowDown } from '@element-plus/icons-vue'
    const activeName = ref('first')
    let topfilterlist = ref([
      {id:1,name:'first',label:'热门筛选',list:['天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家']},
      {id:2,name:'second',label:'机场车站',list:['北京南站','北京西站','北京火车站','北京南站','北京西站','北京火车站','北京南站','北京西站','北京火车站']},
      {id:3,name:'third',label:'商业区',list:['三里屯','国贸地区','西直门','三里屯','国贸地区','西直门','三里屯','国贸地区','西直门']},
      {id:4,name:'fourth',label:'景点',list:['什刹海','前门大街','五道口','什刹海','前门大街','五道口','什刹海','前门大街','五道口']}
    ])
    let pricelist = ref(['五星(钻级)','四星(钻级)','三星(钻级)','两星(钻级)','一星(钻级)'])
    let filterlist = ref([
      {title:'早餐',list:['含早餐','单份早餐','多份早餐']},
      {title:'支付方式',list:['在线付款','到店付款','闪住']},
      {title:'房型',list:['双床房','三床房','单人床房','大床房','特大床房']},
      {title:'酒店设施',list:['免费停车','室内游泳','单人床房','大床房','特大床房']},
      {title:'住宿类型',list:['免费停车','室内游泳','单人床房','大床房','特大床房']},
      {title:'酒特色主题',list:['免费停车','室内游泳','单人床房','大床房','特大床房']},
    ])
    </script>
    
    <style>
    
    </style>

遇到问题:

按钮居中对齐,不靠左

解决方式:

修改#app中的样式(如果在之前隐藏展开框中改过则不会出现问题)

在App.vue中,注释掉text-align: center;

vue 复制代码
<template>
  
  <router-view/>
</template>

<style lang="scss">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  // text-align: center;
  color: #2c3e50;
}

nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

为防止应样式继承产生的问题,将App.vue中的样式都注销
遇到问题:

星级价格中的按钮以及高级筛选的下拉菜单不垂直居中

解决方式:

在index.css中增加样式

css 复制代码
.topfilter-price{
    display: flex;
    align-items: center;
}
.topfilter-filter{
    display: flex;
    align-items: center;
}
  1. indext.css(根据页面大小,修改了其他样式)

    css 复制代码
    /* 左侧导航栏 */
    .aside {
        width: 200px;
    }
    .aside-list {
        /* 固定定位 */
        position: fixed;
        left: 0;
        width: 200px;
    }
    .aside .el-menu {
        height:100vh;
    
    }
    /* 字体图标的样式 */
    .aside i {
        font-size: 24px;
        font-weight: 500;
        margin-right: 5px;
    }
    .aside .el-radio-button__inner {
        border:none;
        font-size: 20px;
    }
    
    
    /* 页面头部 */
    /* 宽度响应 */
    .el-header {
        min-width: 1280px;
    }
    .headerNav {
        display: flex;
        justify-content: space-between;
        align-items: center;
        /* 水平垂直对齐 */
        height: 70px;
        width:1300px;
        /* 固定定位 */
        position:fixed;
        top:0;
        background-color: #fff;
        z-index: 999;
        padding: 10px 0;
    }
    .headerNav img {
        width: 100%;
        height: 50px;
    }
    .header-search {
        flex: 1;
        margin: 0 2rem;
    }
    /* 按钮的颜色  */
    .headerNav .el-input-group__append {
        background-color: var(--el-color-primary);
        color: #fff;
    }
    .header-right .el-link {
        margin: 0 20px;
    }
    /* 伪类选择器:可以用来选取获得焦点的元素
    当鼠标移入上去后取消黑色边框 */
    .el-dropdown-link:focus{
       outline: none;
    }
    /* 右侧下面展示 */
    .el-main {
        min-width: 1280px;
        overflow: hidden;
    }
    /* 区域展示部分 */
    .searchlist {
        width: 1300px;
        display: grid;
        grid-template-columns: repeat(5,auto);
        margin-top: 15px;
    }
    .searchlist-item {
        border: 1px solid #dadada;
        margin-left: -1px;
    }
    /* 目的地/酒店名称 */
    .search-box {
        padding: 8px 12px;
    }
    .search-box label {
        color: #999;
        display: block;
    }
    .search-box input {
        border:none;
        font-size: 16px;
        font-weight: 700;
        padding-top: 15px;
    }
    
    .input{
        outline: none;
    }
    /* 伪类选择器,当元素获得焦点的时候,能够控制父元素的样式 */
    .searchlist-item:focus-within {
        border-bottom: 2px solid var(--el-color-primary);
    }
    /* 入住时间/退房时间 取消边框的颜色 */
    .search-box .el-date-editor.el-input__wrapper {
        box-shadow:none;
    }
    .search-box .el-date-editor.el-input__wrapper:hover {
        box-shadow:none;
    }
    /* 搜索按钮的样式 */
    .searchlist-item .el-button {
        width: 100%;
        height:100%;
        border-radius: 0;
    }
    .searchlist-item .el-button .el-icon {
        font-size: 30px;
    }
    
    /* topfilter开始  */
    .topfilter {
        width: 1300px;
        display:grid;
        grid-template-columns: 130px 1fr;
        /* 列 */
        grid-template-rows:repeat(3,auto);
        /* 3行 */
    }
    .topfilter>div {
        border-bottom:1px solid #ddd;
        padding: 0.2rem 1rem;
    }
    .topfilter h4 {
        line-height: 17px;
        text-align: center;
    }
    .topfilter .el-button:hover {
        background-color: var(--el-color-primary);
        border: 1px solid var(--el-color-primary);
    }
    
    .topfilter-price{
        display: flex;
        align-items: center;
    }
    
    .topfilter-filter{
        display: flex;
        align-items: center;
    }
    
    /* 按钮的间距: */
    .topfilter .el-button {
        margin: 7px;
    }
    /* 高级筛选 */
    .topfilter-filter .el-dropdown {
        margin: 10px 15px;
        /* 下拉菜单间距 */
    }
  2. 效果图

13. 走马灯和列表

  1. 新建文件,并引入

    recommend.vue

    vue 复制代码
    <template>
      <div class="recommend">
        <div class="recommend-left">推荐酒店</div>
        <div class="recommend-left">轮播图</div>
      </div>
    </template>
    
    <script setup>
    import { ref } from "vue";
    
    </script>
    
    <style>
    
    </style>

    index.vue

    vue 复制代码
    <template>
      <!-- <h1>首页</h1> -->
     
      <div class="common-layout">
        <el-container>
          <MenuView></MenuView>
          <el-container>
            <el-header><LogoView></LogoView></el-header>
            <el-main>
              <MainView></MainView>
              <Toplist></Toplist>
              <Recommend></Recommend>
            </el-main>
          </el-container>
        </el-container>
      </div>
    </template>
    
    <script setup>
        // 1.script 里加setup,引入要加载的子页面
        import MenuView from './menu.vue'
        import MainView from './main.vue'
        import LogoView from './logo.vue'
        import Toplist from './toplist.vue'
        import Recommend from './recommend.vue'
    </script>
    
    <style lang="scss">
    
    
    </style>
  2. 效果图

  3. 修改代码,增加视图Recommend-left和Banner

    recommend.vue

vue 复制代码
<template>
  <div class="recommend">
    <div class="recommend-left">
        <h2>推荐酒店</h2>
        <Recommendlist></Recommendlist>
    </div>
    <div class="recommend-right">
        <Banner></Banner>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";

</script>

<style>

</style>

index.css

css 复制代码
/* 推荐酒店 */
.recommend {
    width:1300px;
    display:flex;
    gap: 0 20px;
    padding: 10px 0;
}
.recommend-left {
    width: 900px;
}
.recommend-right {
    width: 400px;
}
  1. 修改代码
    banner.vue
vue 复制代码
<template>
<div class="banner">
    <el-carousel height="620px">
        <el-carousel-item v-for="item in bannerlist" :key="item.id">
           <img :src="`/src/assets/images/${item.img_url}`" alt="">
        </el-carousel-item>
    </el-carousel>
</div>
</template>

<script setup>
import {ref} from 'vue'

let bannerlist = ref([
    {id:1,img_url:'banner1.jpg'},
    {id:2,img_url:'banner2.jpg'},
    {id:3,img_url:'banner3.jpg'},
    {id:4,img_url:'banner4.jpg'},
    {id:5,img_url:'banner5.jpg'},
])
</script>

<style>

</style>

index.css

css 复制代码
.banner {
    width: 400px;
    height: 620px;
}
/* 轮播图 */
.banner img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

遇到问题:

banner.vue中图片不显示

找不到路径

解决方式:

vue 复制代码
<!--相对路径引用 webpack 帮我们解析时需要使用 require() 把图片路径包裹起来 -->
<!-- 在public文件夹下是绝对路径,不需要经过webpack -->

<img :src="require(`/src/assets/images/${item.img_url}`)" alt="">

5.完善代码

recommend.vue

vue 复制代码
<template>
  <div class="recommend">
    <div class="recommend-left">
        <h2>推荐酒店</h2>
        <Recommendlist></Recommendlist>
    </div>
    <div class="recommend-right">
        <Banner></Banner>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import Banner from './banner.vue'
import Recommendlist from './recommend-list.vue'
</script>

<style>

</style>

recommend-list.vue

vue 复制代码
<template>
<div class="recommend-list">
    <ul>
        <li v-for="v in recommendlist" :key="v.id"> 
            <div class="list-left">
                <div class="list-left-img">
                    <img :src="require(`/src/assets/images/${v.img_url}`)" alt="">
                </div>
                <div class="list-left-title">
                    <div class="list-left-tagandtitle">
                        <h4>{{v.name}}</h4>
                        <img :src="require(`/src/assets/images/${v.starimg_url}`)" alt="">
                        <span class="badge-thumb"></span>
                    </div>
                    <div class="list-left-transport">
                        <p>{{v.transport}}</p>
                    </div>
                    <div class="list-left-tag">
                        <el-tag class="ml-2" type="danger" effect="plain" v-for="(k,i) in v.tag" :key="i">{{k}}</el-tag>
                    </div>
                </div>
            </div>
            <!-- 右侧 -->
            <div class="list-right">
                <div class="list-right-comment">
                    <div class="list-right-describe">
                        <div class="p1">好</div>
                
                        <a href="#">3333条点评</a>
                    </div>
                    <div class="list-right-score">
                        <p>4.5</p>
                    </div>
                </div>
                <div class="list-right-price">
                    <p>¥3333</p>
                     <el-button type="primary">查看详情</el-button>
                </div>
            </div>
        </li>
    </ul>
</div>
</template>

<script setup>
import {ref} from 'vue'

let recommendlist = ref([
    {id:1,name:'北京首都宾馆',img_url:'1.jpg',transport:'天安门/王府井 | 距市中心直线310米',starimg_url:'star5.png',tag:['网球场','商务中心','会议厅']},
    {id:2,name:'北京京伦饭店',img_url:'2.jpg',transport:'国贸CBD | 距市中心直线4.1公里',starimg_url:'star4.png',tag:['停车场','健身室','SPA']},
    {id:3,name:'北京新世界中心同派酒店',img_url:'3.jpg',transport:'前门/天坛公园/崇文门 | 距市中心直线1公里',starimg_url:'star4.png',tag:['桌球室','闪住','酒吧','行李寄存']},
    {id:4,name:'北京新世界中心同派酒店',img_url:'4.jpg',transport:'前门/天坛公园/崇文门 | 距市中心直线1公里',starimg_url:'star4.png',tag:['桌球室','闪住','酒吧','行李寄存']},
])
</script>

<style>

</style>

banner.vue

vue 复制代码
<template>
<div class="banner">
    <el-carousel height="620px">
        <el-carousel-item v-for="item in bannerlist" :key="item.id">
            <!--相对路径引用 webpack 帮我们解析时需要使用 require() 把图片路径包裹起来 -->
            <!-- 在public文件夹下是绝对路径,不需要经过webpack -->
            <!-- <img :src="require(`../assets/${item.img_url}`)" alt=""> -->
            <img :src="require(`/src/assets/images/${item.img_url}`)" alt="">
        </el-carousel-item>
    </el-carousel>
</div>
</template>

<script setup>
import {ref} from 'vue'

let bannerlist = ref([
    {id:1,img_url:'banner1.jpg'},
    {id:2,img_url:'banner2.jpg'},
    {id:3,img_url:'banner3.jpg'},
    {id:4,img_url:'banner4.jpg'},
    {id:5,img_url:'banner5.jpg'},
])
</script>

<style>

</style>

index.css

vue 复制代码
/* 左侧导航栏 */
.aside {
    width: 200px;
}
.aside-list {
    /* 固定定位 */
    position: fixed;
    left: 0;
    width: 200px;
}
.aside .el-menu {
    height:100vh;

}
/* 字体图标的样式 */
.aside i {
    font-size: 24px;
    font-weight: 500;
    margin-right: 5px;
}
.aside .el-radio-button__inner {
    border:none;
    font-size: 20px;
}


/* 页面头部 */
/* 宽度响应 */
.el-header {
    min-width: 1280px;
}
.headerNav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    /* 水平垂直对齐 */
    height: 70px;
    width:1300px;
    /* 固定定位 */
    position:fixed;
    top:0;
    background-color: #fff;
    z-index: 999;
    padding: 10px 0;
}
.headerNav img {
    width: 100%;
    height: 50px;
}
.header-search {
    flex: 1;
    margin: 0 2rem;
}
/* 按钮的颜色  */
.headerNav .el-input-group__append {
    background-color: var(--el-color-primary);
    color: #fff;
}
.header-right .el-link {
    margin: 0 20px;
}
/* 伪类选择器:可以用来选取获得焦点的元素
当鼠标移入上去后取消黑色边框 */
.el-dropdown-link:focus{
   outline: none;
}
/* 右侧下面展示 */
.el-main {
    min-width: 1280px;
    overflow: hidden;
}
/* 区域展示部分 */
.searchlist {
    width: 1300px;
    display: grid;
    grid-template-columns: repeat(5,auto);
    margin-top: 15px;
}
.searchlist-item {
    border: 1px solid #dadada;
    margin-left: -1px;
}
/* 目的地/酒店名称 */
.search-box {
    padding: 8px 12px;
}
.search-box label {
    color: #999;
    display: block;
}
.search-box input {
    border:none;
    font-size: 16px;
    font-weight: 700;
    padding-top: 15px;
}

.input{
    outline: none;
}
/* 伪类选择器,当元素获得焦点的时候,能够控制父元素的样式 */
.searchlist-item:focus-within {
    border-bottom: 2px solid var(--el-color-primary);
}
/* 入住时间/退房时间 取消边框的颜色 */
.search-box .el-date-editor.el-input__wrapper {
    box-shadow:none;
}
.search-box .el-date-editor.el-input__wrapper:hover {
    box-shadow:none;
}
/* 搜索按钮的样式 */
.searchlist-item .el-button {
    width: 100%;
    height:100%;
    border-radius: 0;
}
.searchlist-item .el-button .el-icon {
    font-size: 30px;
}

/* topfilter开始  */
.topfilter {
    width: 1300px;
    display:grid;
    grid-template-columns: 130px 1fr;
    /* 列 */
    grid-template-rows:repeat(3,auto);
    /* 3行 */
}
.topfilter>div {
    border-bottom:1px solid #ddd;
    padding: 0.2rem 1rem;
}
.topfilter h4 {
    line-height: 17px;
    text-align: center;
}
.topfilter .el-button:hover {
    background-color: var(--el-color-primary);
    border: 1px solid var(--el-color-primary);
}

.topfilter-price{
    display: flex;
    align-items: center;
}

.topfilter-filter{
    display: flex;
    align-items: center;
}

/* 按钮的间距: */
.topfilter .el-button {
    margin: 7px;
}
/* 高级筛选 */
.topfilter-filter .el-dropdown {
    margin: 10px 15px;
    /* 下拉菜单间距 */
}

/* 推荐酒店 */
.recommend {
    width:1300px;
    display:flex;
    gap: 0 20px;
    padding: 10px 0;
}
.recommend-left {
    width: 880px;
}
.recommend-right {
    width: 420px;
}
.banner {
    width: 420px;
    height: 650px;
    margin-top: 57px;
}

h2{
    font-size: 1.2em;
    margin-left: 30px;
}

/* 轮播图 */
.banner img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.recommend-list ul li {
    display: flex;
    background-color: #F4F6F9;
    padding: 10px;
    margin-bottom: 10px;
    height: 127px;
}
.list-left {
    /* 设置了弹性项目如何增大或缩小以适应其弹性容器中可用的空间 */
    flex: 2;
    display: flex;
}
.list-right {
    flex: 1;
    border-left: 1px solid #ddd;
    text-align: right;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}       
/* 图片的大小 */
.list-left-img {
    flex: 0.7;
}
.list-left-img img {
    width: 100%;
}
.list-left-title {
    flex: 3;
    margin-left: 30px;
}
/* 标题 */
.list-left-tagandtitle {
    font-size: 16px;
    line-height: 3px;
    display: flex;
    margin-bottom: 8px;
    align-items: center;
}
.list-left-tagandtitle img {
    height: 20px;
    width: auto;
    margin: 0 10px;
}
.badge-thumb {
    background:url(@/assets/images/help.png) no-repeat;
    width: 16px;
    height: 16px;
}
.list-left-transport {
    margin-bottom: 8px;
}
.list-left-tag .el-tag {
    margin: 3px;
}
.list-right-comment {
    display:flex;
    justify-content: flex-end;
    margin-bottom: 10px;
    height: 40px;
}
.list-right-describe{
    height: 60px;
}
.p1 {
    color: var(--el-color-primary);
    font-size:16px;
    font-weight: 700;
    align-items: center;
    margin-top: 0px;
    
}
.list-right-describe a {
    color: #999;
    font-size: 11px;
    margin-top: 0px;
}
.list-right-score {
    background-color: var(--el-color-primary);
    color: #fff;
    border-radius: 4px;
    padding: 3px;
    font-size: 18px;
    font-weight: 800;
    margin-left: 9px;
    display: flex;
    align-items: center;
}
.list-right-price p {
    color: var(--el-color-primary);
    font-size:20px;
    font-weight: 700;
    margin-top: 0px;
    margin-bottom: 9px;
}

样式根据电脑屏幕进行了修改

  1. 效果图

代码整合

1. index.vue

vue 复制代码
<template>
  <!-- <h1>首页</h1> -->
  <div class="common-layout">
    <el-container>
      <MenuView></MenuView>
      <el-container>
        <el-header><LogoView></LogoView></el-header>
        <el-main>
          <MainView></MainView>
          <Toplist></Toplist>
          <Recommend></Recommend>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script setup>
    // 1.script 里加setup,引入要加载的子页面
    import MenuView from './menu.vue'
    import MainView from './main.vue'
    import LogoView from './logo.vue'
    import Toplist from './toplist.vue'
    import Recommend from './recommend.vue'
</script>

<style lang="scss">


</style>

2. banner.vue

vue 复制代码
<template>
<div class="banner">
    <el-carousel height="620px">
        <el-carousel-item v-for="item in bannerlist" :key="item.id">
            <!--相对路径引用 webpack 帮我们解析时需要使用 require() 把图片路径包裹起来 -->
            <!-- 在public文件夹下是绝对路径,不需要经过webpack -->
            <!-- <img :src="require(`../assets/${item.img_url}`)" alt=""> -->
            <img :src="require(`/src/assets/images/${item.img_url}`)" alt="">
        </el-carousel-item>
    </el-carousel>
</div>
</template>

<script setup>
import {ref} from 'vue'

let bannerlist = ref([
    {id:1,img_url:'banner1.jpg'},
    {id:2,img_url:'banner2.jpg'},
    {id:3,img_url:'banner3.jpg'},
    {id:4,img_url:'banner4.jpg'},
    {id:5,img_url:'banner5.jpg'},
])
</script>

<style>

</style>

3. logo.vue

vue 复制代码
<template>
  <div>
    <div class="headerNav">
      <!-- logo -->
      <div class="header-logo">
        <img src="@/assets/images/logo.png" alt="">
      </div>
      <!-- 搜索框 -->
      <div class="header-search">
        <el-input
            v-model="input3"
            placeholder="请输入内容"
            class="input-with-select"
            >
            <template #append>
                <el-button :icon="Search" />
            </template>
        </el-input>
      </div>
      <!-- 导航菜单 -->
      <div class="header-right">
        <el-link :icon="Avatar">请登录</el-link>
        <el-link target="_blank">注册</el-link>
        <el-link>
          <el-dropdown>
              <span class="el-dropdown-link">
              我的订单
              <el-icon class="el-icon--right">
                  <arrow-down />
              </el-icon>
              </span>
              <template #dropdown>
                <el-dropdown-menu>
                    <el-dropdown-item v-for="v in Myorder" :key="v.id">{{v.title}}</el-dropdown-item>
                </el-dropdown-menu>
              </template>
          </el-dropdown>
        </el-link>
      </div>
    </div>
  </div>
</template>

<script setup>
//引入搜索图标
import { Search,Avatar,ArrowDown } from '@element-plus/icons-vue'
import { ref } from 'vue'
//下拉列表
let Myorder = ref([
    {id:1,title:'酒店订单'},
    {id:2,title:'火车票订单'},
    {id:3,title:'飞机票订单'},
    {id:4,title:'旅游订单'},
    {id:5,title:'全部订单'}
])
</script>

<style lang="scss">

</style>

3. main.vue

vue 复制代码
<template>
  <div class="searchlist">
    <div class="searchlist-item">
        <div class="search-box">
          <!-- 使用for和id进行表单绑定 -->
            <label for="hotels-destination">目的地/酒店名称</label>
            <input class="input" type="text" id="hotels-destination" placeholder="北京">
        </div>
    </div>
    <div class="searchlist-item">
        <div class="search-box">
            <label>入住时间/退房时间</label>
            <el-date-picker
                v-model="value1"
                type="datetimerange"
                start-placeholder="Start Date"
                end-placeholder="End Date"
                :default-time="defaultTime1"
                />
        </div>
    </div>
    <div class="searchlist-item">
          <div class="search-box">
            <label for="room-guest">房间及住客</label>
            <input class="input" type="text" id="room-guest" placeholder="1间/1位">
        </div>
    </div>
    <div class="searchlist-item">
          <div class="search-box">
            <label for="keyword">关健词(选填)</label>
            <input class="input" type="text" id="keyword" placeholder="火车/酒店名称或区域">
        </div>
    </div>
    <div class="searchlist-item">
        <el-button type="primary" :icon="Search"></el-button>
    </div>
  </div>
</template>

<script setup>
import {ref} from 'vue'
import {Search} from '@element-plus/icons-vue'
</script>

<style lang="scss">

</style>
vue 复制代码
<template>
    
    <el-aside width="200px" class="aside">
        <div class="aside-list">
            <!-- 菜单标签 -->
            <el-menu 
                default-active="2" 
                class="el-menu-vertical-demo" 
                :collapse="isCollapse" 
                @open="handleOpen" 
                @close="handleClose"
            >
                <!-- 隐藏展开按钮 -->
                <el-radio-group v-model="isCollapse" style="margin-bottom: 20px" >
                    <el-radio-button :value="false" v-show="isCollapse">|||</el-radio-button>
                    <el-radio-button :value="true" v-show="!isCollapse">|||</el-radio-button>
                </el-radio-group>

                <!-- 需要多个这个菜单项就用v-for实现-->
                <el-menu-item index="v.id" v-for="v in asidelist" :key="v.id">
                    <!-- 实现动态icon图标 -->
                    <!-- <el-icon><component :is="v.icon"></component></el-icon> -->
                    <i class="iconfont" :class="v.icon"></i>
                    <template #title>{{v.title}}</template>
                </el-menu-item>
            </el-menu>
        </div>
        
    </el-aside>
</template>

<script setup>
import { ref } from "vue";

// 设置isCollapse的值为true,用于控制展开或隐藏
const isCollapse = ref(true)

// 导入icon图标,没用到的组件导入会报错,可以在package.json文件中
// 增加一条rules:"no-unused-vars": "off"
import {
    Document,
    Menu as IconMenu,
    Location,
    Setting,
    // 9.增加新的图标
    OfficeBuilding,
    Bowl
} from '@element-plus/icons-vue'

// 定义左侧菜单数组,10.增加icon
// let asidelist=ref([
//     {id:1,title:'酒店',icon:OfficeBuilding},
//     {id:2,title:'机票',icon:Document},
//     {id:3,title:'火车票',icon:Setting},
//     {id:4,title:'旅游',icon:Bowl},
//     {id:5,title:'景点',icon:Location},
//     {id:6,title:'汽车票',icon:Document},
//     {id:7,title:'船票',icon:IconMenu},
//     {id:8,title:'门票',icon:OfficeBuilding},
// ])

// 引入第三方图标
let asidelist = ref([
    {id:1,title:'酒店',icon:'icon-jiudian'},
    {id:2,title:'机票',icon:'icon-lvxing'},
    {id:3,title:'火车票',icon:'icon-huoche'},
    {id:4,title:'旅游',icon:'icon-lvyou1'},
    {id:5,title:'景点',icon:'icon-jingdian'},
    {id:6,title:'汽车票',icon:'icon-tuijianqiche'},
    {id:7,title:'船票',icon:'icon-lunchuan'},
    {id:8,title:'门票',icon:'icon-menpiao'},
])
</script>

<style lang="scss">

</style>

5. recommend-list.vue

vue 复制代码
<template>
<div class="recommend-list">
    <ul>
        <li v-for="v in recommendlist" :key="v.id"> 
            <div class="list-left">
                <div class="list-left-img">
                    <img :src="require(`/src/assets/images/${v.img_url}`)" alt="">
                </div>
                <div class="list-left-title">
                    <div class="list-left-tagandtitle">
                        <h4>{{v.name}}</h4>
                        <img :src="require(`/src/assets/images/${v.starimg_url}`)" alt="">
                        <span class="badge-thumb"></span>
                    </div>
                    <div class="list-left-transport">
                        <p>{{v.transport}}</p>
                    </div>
                    <div class="list-left-tag">
                        <el-tag class="ml-2" type="danger" effect="plain" v-for="(k,i) in v.tag" :key="i">{{k}}</el-tag>
                    </div>
                </div>
            </div>
            <!-- 右侧 -->
            <div class="list-right">
                <div class="list-right-comment">
                    <div class="list-right-describe">
                        <div class="p1">好</div>
                
                        <a href="#">3333条点评</a>
                    </div>
                    <div class="list-right-score">
                        <p>4.5</p>
                    </div>
                </div>
                <div class="list-right-price">
                    <p>¥3333</p>
                     <el-button type="primary">查看详情</el-button>
                </div>
            </div>
        </li>
    </ul>
</div>
</template>

<script setup>
import {ref} from 'vue'

let recommendlist = ref([
    {id:1,name:'北京首都宾馆',img_url:'1.jpg',transport:'天安门/王府井 | 距市中心直线310米',starimg_url:'star5.png',tag:['网球场','商务中心','会议厅']},
    {id:2,name:'北京京伦饭店',img_url:'2.jpg',transport:'国贸CBD | 距市中心直线4.1公里',starimg_url:'star4.png',tag:['停车场','健身室','SPA']},
    {id:3,name:'北京新世界中心同派酒店',img_url:'3.jpg',transport:'前门/天坛公园/崇文门 | 距市中心直线1公里',starimg_url:'star4.png',tag:['桌球室','闪住','酒吧','行李寄存']},
    {id:4,name:'北京新世界中心同派酒店',img_url:'4.jpg',transport:'前门/天坛公园/崇文门 | 距市中心直线1公里',starimg_url:'star4.png',tag:['桌球室','闪住','酒吧','行李寄存']},
])
</script>

<style>

</style>

6. recommend.vue

vue 复制代码
<template>
  <div class="recommend">
    <div class="recommend-left">
        <h2>推荐酒店</h2>
        <Recommendlist></Recommendlist>
    </div>
    <div class="recommend-right">
        <Banner></Banner>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import Banner from './banner.vue'
import Recommendlist from './recommend-list.vue'
</script>

<style>

</style>

7. toplist.vue

vue 复制代码
<template>
  <div class="topfilter">
    <div>
      <h4>位置区域</h4>
    </div>
    <!-- tabs切换 -->
    <div class="topfilter-tab">
      <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
        <!-- 数据绑定 -->
        <el-tab-pane :label="v.label" :name="v.name" v-for="v in topfilterlist" :key="v.id">
          <el-button  v-for="(k,i) in v.list" :key="i" size="small" type="info" plain>{{k}}</el-button>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div>
      <h4>星级价格</h4>
    </div>
    <div class="topfilter-price">
        <el-button size="small" type="info" plain v-for="(v,i) in pricelist" :key="i">{{v}}</el-button>
    </div>
    <div>
      <h4>高级筛选</h4>
    </div>
    <div class="topfilter-filter">
        <el-dropdown v-for="(v,i) in filterlist" :key="i">
            <span class="el-dropdown-link">
              {{v.title}}
              <el-icon class="el-icon--right">
                <!-- 箭头按钮 -->
                <arrow-down />
              </el-icon>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item v-for="(k,i) in v.list" :key="i">{{k}}</el-dropdown-item>
              </el-dropdown-menu>
            </template>
      </el-dropdown>
    </div>
  </div>
</template>

<script setup>
import {ref} from 'vue'
//箭头图标
import { ArrowDown } from '@element-plus/icons-vue'
const activeName = ref('first')
let topfilterlist = ref([
  {id:1,name:'first',label:'热门筛选',list:['天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家','天安门广场','王府井','北京大家']},
  {id:2,name:'second',label:'机场车站',list:['北京南站','北京西站','北京火车站','北京南站','北京西站','北京火车站','北京南站','北京西站','北京火车站']},
  {id:3,name:'third',label:'商业区',list:['三里屯','国贸地区','西直门','三里屯','国贸地区','西直门','三里屯','国贸地区','西直门']},
  {id:4,name:'fourth',label:'景点',list:['什刹海','前门大街','五道口','什刹海','前门大街','五道口','什刹海','前门大街','五道口']}
])
let pricelist = ref(['五星(钻级)','四星(钻级)','三星(钻级)','两星(钻级)','一星(钻级)'])
let filterlist = ref([
  {title:'早餐',list:['含早餐','单份早餐','多份早餐']},
  {title:'支付方式',list:['在线付款','到店付款','闪住']},
  {title:'房型',list:['双床房','三床房','单人床房','大床房','特大床房']},
  {title:'酒店设施',list:['免费停车','室内游泳','单人床房','大床房','特大床房']},
  {title:'住宿类型',list:['免费停车','室内游泳','单人床房','大床房','特大床房']},
  {title:'酒特色主题',list:['免费停车','室内游泳','单人床房','大床房','特大床房']},
])
</script>

<style>

</style>

8. 最终效果

相关推荐
澄澈i6 分钟前
设计模式学习[9]---模板方法模式
c++·学习·设计模式·模板方法模式
池佳齐26 分钟前
《AI大模型开发笔记》——Prompt提示词最佳实践
人工智能·笔记·prompt
Ice16627 分钟前
算法学习笔记(十):位运算、数论等
笔记·学习
ZZZ_O^O43 分钟前
【贪心算法入门第一题——860.柠檬水找零】
学习·算法·leetcode·贪心算法
我们的五年1 小时前
【Linux课程学习】:命令行参数,环境变量
linux·c语言·学习
梅子酱~1 小时前
Vue 学习随笔系列十七 -- 表格样式修改
javascript·vue.js·学习
开心工作室_kaic1 小时前
ssm150旅游网站的设计与实现+jsp(论文+源码)_kaic
java·开发语言·旅游
一位资深码农2 小时前
弹幕发送功能‘简单’实现
spring boot·vue
尘佑不尘2 小时前
蓝队基础,了解企业安全管理架构
数据库·笔记·安全·web安全·蓝队
我真的太难了啊2 小时前
学习QT第二天
开发语言·qt·学习