【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

相关文章
|
2月前
|
JavaScript 数据可视化
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
这篇文章介绍了如何使用vue-cli 2和3版本来创建Vue项目,并详细说明了两者之间的主要区别。
98 5
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
|
2月前
|
JavaScript 容器
乾坤qiankun框架搭建 主应用为vue3的项目。
乾坤qiankun框架搭建 主应用为vue3的项目。
166 2
|
2月前
|
JavaScript
Vue CLi脚手架创建第一个VUE项目
Vue CLi脚手架创建第一个VUE项目
36 3
|
1月前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
25天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
2月前
|
JavaScript 数据可视化
vue-cli学习二:vue-cli3版本 创建vue项目后,Runtime-Compiler和Runtime-only两个模式详解;vue项目管理器;配置文件的配置在哪,以及如何配置
这篇文章详细介绍了Vue CLI 3版本创建项目时的Runtime-Compiler和Runtime-only两种模式的区别、Vue程序的运行过程、render函数的使用、eslint的关闭方法,以及Vue CLI 2和3版本配置文件的不同和脚手架3版本创建项目的配置文件配置方法。
71 3
vue-cli学习二:vue-cli3版本 创建vue项目后,Runtime-Compiler和Runtime-only两个模式详解;vue项目管理器;配置文件的配置在哪,以及如何配置
|
2月前
|
JavaScript
如何在 Vue 项目中选择合适的模块格式
【10月更文挑战第20天】选择合适的模块格式需要综合考虑多个因素,没有一种绝对正确的选择。需要根据项目的具体情况进行权衡和分析。在实际选择过程中,要保持灵活性,根据项目的发展和变化适时调整模块格式。
21 7
|
1月前
Vue3 项目的 setup 函数
【10月更文挑战第23天】setup` 函数是 Vue3 中非常重要的一个概念,掌握它的使用方法对于开发高效、灵活的 Vue3 组件至关重要。通过不断的实践和探索,你将能够更好地利用 `setup` 函数来构建优秀的 Vue3 项目。
|
2月前
|
JavaScript 前端开发 编译器
在 Vue 项目中使用 ES 模块格式的优点
【10月更文挑战第20天】在 Vue 项目中使用 ES 模块格式具有众多优点,这些优点共同作用,使得项目能够更高效、更可靠地开发和运行。当然,在实际应用中,还需要根据项目的具体情况和需求进行合理的选择和配置。
37 6
|
1月前
|
JavaScript 测试技术 UED
解决 Vue 项目中 Tree shaking 无法去除某些模块
【10月更文挑战第23天】解决 Vue 项目中 Tree shaking 无法去除某些模块的问题需要综合考虑多种因素,通过仔细分析、排查和优化,逐步提高 Tree shaking 的效果,为项目带来更好的性能和用户体验。同时,持续关注和学习相关技术的发展,不断探索新的解决方案,以适应不断变化的项目需求。