【Vue3.0移动端项目--旅游网】-- 首页分类和热门精选展示(2)

简介: 【Vue3.0移动端项目--旅游网】-- 首页分类和热门精选展示(2)

展示热门精选


1. 发送请求

微信图片_20221011224611.png

2. 分类数据存入Store中

微信图片_20221011224655.png


3. 页面渲染(布局处理)微信图片_20221011224728.png

下面分别是组件v9和v3代码

//component/house-item-v9
<template>
  <div class="house-item-v9">
    <div class="item-inner">
      <div class="cover">
        <img :src="itemData.image.url">
      </div>
      <div class="info">
        <div class="summary">{{itemData.summaryText}}</div>
        <div class="name">{{itemData.houseName}}</div>
        <div class="price">
          <van-rate
            :model-value="itemScore"
            color="#fff"
            :size="15"
            readonly
            allow-half
          />
          <div class="new">¥ {{itemData.finalPrice}}</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { computed } from "@vue/runtime-core"
const props = defineProps({
  itemData: {
    type: Object,
    default: () => ({})
  }
})
const itemScore = computed(() => {
  return Number(props.itemData.commentScore)
})
</script>
<style lang="less" scoped>
.house-item-v9 {
  width: 50%;
  .item-inner {
    position: relative;
    margin: 5px;
    background-color: #fff;
    border-radius: 6px;
    overflow: hidden;
    .cover {
      img {
        width: 100%;
      }
    }
    .info {
      position: absolute;
      bottom: 0;
      padding: 8px 10px;
      color: #fff;
      .summary {
        font-size: 12px;
      }
      .name {
        margin: 5px 0;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
      }
      .price {
        display: flex;
        justify-content: space-between;
        margin-top: 10px;
      }
    }
  }
}
</style>
//component/house-item-v3
<template>
  <div class="house-item-v3">
    <div class="item-inner">
      <div class="cover">
        <img
          :src="itemData?.image?.url"
          alt=""
        >
      </div>
      <div class="info">
        <div class="location">
          <img
            src="@/assets/img/home/location.png"
            alt=""
          >
          <span>{{ itemData.location }}</span>
        </div>
        <div class="name">{{ itemData.houseName }}</div>
        <div class="summary">{{ itemData.summaryText }}</div>
        <div class="price">
          <div class="new"> ¥ {{ itemData.finalPrice }}</div>
          <div class="old"> ¥ {{ itemData.productPrice }}</div>
          <div
            class="tip"
            v-if="itemData.priceTipBadge"
          >
            {{ itemData.priceTipBadge.text }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
defineProps({
  itemData: {
    type: Object,
    default: () => ({})
  }
})
</script>
<style lang="less" scoped>
.house-item-v3 {
  width: 50%;
  .item-inner {
    margin: 5px;
    background: #fff;
    border-radius: 6px;
    overflow: hidden;
    .cover {
      img {
        width: 100%;
      }
    }
    .info {
      padding: 8px 10px;
      color: #666;
      font-size: 12px;
    }
    .location {
      display: flex;
      align-items: center;
      img {
        width: 12px;
        height: 12px;
      }
      .text {
        margin-left: 2px;
        font-size: 12px;
        color: #666;
      }
    }
    .name {
      margin: 5px 0;
      font-size: 14px;
      color: #333;
      overflow: hidden;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
    }
    .price {
      display: flex;
      align-items: flex-start;
      margin: 8px 0;
      .new {
        color: #ff9645;
        font-size: 14px;
      }
      .old {
        margin: 0 3px;
        color: #999;
        font-size: 12px;
        text-decoration: line-through;
      }
      .tip {
        background-image: linear-gradient(270deg, #f66, #ff9f9f);
        color: #fff;
        padding: 0 6px;
        border-radius: 8px;
      }
    }
  }
}
</style>

效果:

微信图片_20221011224828.png

5. 滚动到底部 加载更多(再次请求数据)


监听页面的滚动,当滚动到底部的时候,发送请求数据,渲染页面,离开页面时,需要移除监听

这里我们封装一个 hooks

因为监听页面滚动,滚动频率过高会频繁触发hooks,这里引入 underscore 库中的节流函数

安装underscore


npm install underscore

相关概念

scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数

clientHeight 属性(只读)元素的像素高度

  • 如果当前元素没有滚动条,那么 clinetHeight = scrollHeight
  • 如果当前元素存在滚动条,那么scrollHeight > clientHeight

scrollHeight = scrollTop + clientHeight

微信图片_20221011224953.png

// hooks/useScroll.js
import { onMounted, onUnmounted, ref } from "vue"
import { throttle } from "underscore"
export default function useScroll() {
  // 用变量判断是否到达底部
  const isReachBottom = ref(false)
  // scrollHeight = scrollTop + clientHeight
  const scrollHeight = ref(0)
  const clientHeight = ref(0)
  const scrolltop = ref(0)
  // 节流处理
  const scrollListenerHandler = throttle(() => {
    clientHeight.value = document.documentElement.clientHeight
    scrillTop.value = document.documentElement.scrollTop
    scrollHeight.value = document.documentElement.scrollHeight
    if (clientHeight.value + scrollTop.value >= scrollHeight.value) {
      // 已经滚到底部了
      console.log("滚动到底部了")
      isReachBottom.value = true
    }
  }, 100)
  onMounted(() => {
    window.addEventListener("scroll", scrollListenerHandler)
  })
  onUnmounted(() => {
    window.removeEventListener("scroll", scrollListenerHandler)
  })
  return {
    isReachBottom,
    scrollHeight,
    clientHeight,
    scrolltop
  }
}

微信图片_20221011225101.png

存储日期信息


1. 将日期信息存入 mainStore

微信图片_20221011225145.png

2. 修改之前展示的日期信息微信图片_20221011225207.png

搜索框展示


1. 控制搜索框显示微信图片_20221011225245.png

2. 搜索框布局

<template>
  <div class="search">
    <div class="select-time">
      <div class="item start">
        <div class="name">住</div>
        <div class="date">{{ startDateStr }}</div>
      </div>
      <div class="item end">
        <div class="name">离</div>
        <div class="date">{{ endDateStr }}</div>
      </div>
    </div>
    <div class="content">
      <div class="keyword">关键字/位置/民宿</div>
    </div>
    <div class="right">
      <i class="icon-search"></i>
    </div>
  </div>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { computed } from "@vue/runtime-core";
import { formatMonthDay } from "@/utils/format-time";
import { useMainStore } from "@/stores/modules/main";
const mainStore = useMainStore()
const { startDate, endDate } = storeToRefs(mainStore)
const startDateStr = computed(() => formatMonthDay(startDate.value, "MM.DD"))
const endDateStr = computed(() => formatMonthDay(endDate.value, "MM.DD"))
</script>
<style lang="less" scoped>
.search {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 45px;
  line-height: 45px;
  padding: 0 10px;
  font-size: 14px;
  color: #999;
  border-radius: 6px;
  background-color: #f2f4f6;
  .select-time {
    display: flex;
    flex-direction: column;
    .item {
      display: flex;
      flex-direction: row;
      align-items: center;
      line-height: normal;
      font-size: 10px;
      .name {
        font-size: 10px;
      }
      .date {
        position: relative;
        color: #333;
        margin: 0 10px 0 3px;
      }
    }
  }
  .end .date::after {
    content: ' ';
    width: 0;
    height: 0;
    border: 4px solid #666;
    border-color: rgba(0, 0, 0, 0) rgba(0, 0, 0, 0) rgba(0, 0, 0, 0) #666;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    -webkit-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    transform: rotate(45deg);
    position: absolute;
    bottom: 0px;
    right: -12px;
  }
}
.content {
  position: relative;
  flex: 1;
  padding: 0 6px;
  text-align: left;
  border-left: 1px solid #fff;
  .keyword {
    max-width: 155px;
    font-size: 12px;
  }
}
.right {
  display: flex;
  align-items: center;
  .icon-search {
    width: 24px;
    height: 24px;
    display: inline-block;
    background-image: url(../../assets/img/home/home-sprite.png);
    background-position: -29px -151px;
    background-size: 207px 192px;
  }
}
</style>

效果:

image.png


Git 管理和代码托管(github)


1.添加到暂存区

git add .

2.添加到仓库

git commit -m "home02分支"

3.推送代码

git push -u origin home02

4.将本地的tabbar 分支 合并到主分支上master (注意要先切换在主分支上)

git checkout mater

5.分支合并

git merge home02

6.更新远程仓库 master 分支

git push

7.删除tabbar分支

git branch -d home02

微信图片_20221011225618.png

相关文章
|
18天前
|
JSON 数据可视化 数据库
vue3+threejs+koa可视化项目——实现登录注册(第三步)
vue3+threejs+koa可视化项目——实现登录注册(第三步)
40 5
|
18天前
|
数据可视化 前端开发 JavaScript
vue3+threejs可视化项目——引入threejs加载钢铁侠模型(第二步)
vue3+threejs可视化项目——引入threejs加载钢铁侠模型(第二步)
73 3
|
18天前
|
JavaScript 数据可视化 算法
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
37 6
|
1月前
|
JavaScript 前端开发 C++
Vue项目创建
Vue项目创建
20 0
|
4天前
|
资源调度 JavaScript 前端开发
vue 项目运行过程中出现错误的问题解决
vue 项目运行过程中出现错误的问题解决
10 1
|
5天前
|
JavaScript
vue项目切换页面白屏的解决方案
vue项目切换页面白屏的解决方案
6 0
|
5天前
|
XML JavaScript 前端开发
Vue3 项目中怎么使用 jsx——易懂
Vue3 项目中怎么使用 jsx——易懂
6 0
|
18天前
|
JSON 数据可视化 前端开发
vue3+threejs+koa可视化项目——模型文件上传(第四步)
vue3+threejs+koa可视化项目——模型文件上传(第四步)
18 7
|
18天前
|
JavaScript 安全 前端开发
Vue 项目中的权限管理:让页面也学会说“你无权访问!
Vue 项目中的权限管理:让页面也学会说“你无权访问!
31 3
|
20天前
|
资源调度 JavaScript Linux
VueCLI:Vue项目脚手架与构建工具技术详解
【4月更文挑战第24天】VueCLI是Vue.js官方的项目脚手架,简化创建与配置,提供丰富的插件系统,支持全生命周期功能,如代码编译、打包部署。它具有易于配置、跨平台支持等优势。通过安装、创建项目、运行及构建命令,开发者能快速搭建Vue应用。VueCLI允许自定义配置(vue.config.js)和安装各类插件,如vue-router、vuex,以适应不同项目需求,提高开发效率。