购物街项目(2)

三、开始完成首页的功能

3.1. 封装顶部NavBar组件

  1. 创建 NavBar 组件
  2. 设置左中右三个插槽
  3. 配置基本样式属性
  4. 在首页home中导入 NavBar 组件并注册
  5. 在home页顶部使用 <nav-bar>,并设置内容显示在中间插槽区域

3.2. 封装轮播图组件

  1. 创建 HomeSwiper、Swiper 和 SwiperItem 组件
  2. 将 Swiper 和 SwiperItem 组件都导入 HomeSwiper 组件中,并注册
  3. 将 HomeSwiper 组件导入首页 Home 并注册,使用 HomeSwiper 组件

3.3 axios请求封装

  1. 安装axios和vue-axios,
npm install --save axios
  1. 创建并设置请求 request.js
  2. 导入 axios ,配置请求 request
  3. 创建 axios 实例=>添加请求拦截器=>添加响应拦截器=>发送真实的网络请求

3.4 封装首页 home.js 的请求

  1. 导入 request.js 请求配置文件
  2. 配置首页的 getHomeMultidata 请求函数
  3. 首页加载 getHomeMultidata 请求函数,来获得所有想要的数据

3.5 首页调用getHomeMultidata方法请求数据

  1. 导入 home.js 请求文件
  2. 在 methods 中创建 getHomeMultidata 方法,并在 生命周期函数created 中调用
  3. 在 data 中初始化 banners 数组
  4. 在 getHomeMultidata 方法中拿到实际的 banner 图片的数据,并赋给 data 中的 banners

3.6 完成轮播图功能(采用Swiper5轮播组件,对3.2进行重构)

  1. 创建 HomeSwiper 组件,并在首页轮播区导入、注册和使用
  2. 首页父组件将获取到的 banners 传给子组件 HomeSwiper
  3. 引入 Swiper4/5 轮播组件
    • 安装 vue-awesome-swiper 轮播UI组件
      npm install vue-awesome-swiper --save

    • 在 HomeSwiper 组件中局部注册,并引入组件

import { Swiper, SwiperSlide } from 'vue-awesome-swiper'
import 'swiper/css/swiper.css'

export default {
  components: {
    Swiper,
    SwiperSlide
  }
}
  1. 通过 v-for 指令进行循环遍历 SwiperSlide 来显示 banners 中的数组值
  2. 每个遍历的 item 中都可以拿到 link 和 image ,并创建 <a> 和 <img> 标签来显示内容
  3. 在 swiper 标签中放入分页器
<div class="swiper-pagination" slot="pagination"></div>
  1. 在 data 中设置轮播参数,分页器的参数
      swiperOptions: {
        loop: true,
        effect: "coverflow", // 3d流
        autoplay: {
          delay: "2000",
          disableOnInteraction: false
        },
        slidesPerView: 1,
        grabCursor: true,
        pagination: {
          el: ".swiper-pagination",
          clickable: true,
          type: "bullets",
          bulletClass: "swiper-pagination-bullet",
          bulletActiveClass: "swiper-pagination-bullet-active"
        }
      }
  1. 完成轮播图的样式和分页器的样式
    注意:想要查看当前 Swiper 实例对象必须要在 updated(){} 函数中去打印;如果是在 mounted(){} 会报错,找不到。

3.8 完成推荐 RecommendView 组件的内容

  1. 创建、导入、注册、使用该组件
  2. 在父组件中获取 recommends 的数组数据并传给 recommendview 子组件
  3. 子组件将拿到的数据渲染到页面,并调试样式

3.9 完成每周流行PopularThisWeek组件的内容

  1. 创建、导入、注册、使用该组件
  2. 完成组件的内容和样式

3.10 完成TabControl组件的功能

  1. 创建、导入、注册、使用该组件 TabControl
  2. 创建 props 接收父组件传过来的 titles 参数,并用 v-for 遍历循环显示所有 title
  3. 通过绑定动态属性 :class:{active: index === currentIndex} 来判断高亮显示
  4. 绑定点击事件 @click=“itemClick(index)” 来判断点击的是哪个 title 标题,并将标题索引的值传给 currentIndex

3.11 完成商品列表内容

  1. 创建 GoodsList 和 GoodsItem 组件

  2. 将 GoodsList 组件导入 Home 中并注册和使用,将 GoodsItem 组件导入 GoodsList 中注册、使用

  3. 在 home.js 中封装用来请求商品数据的请求 getHomeGoods

    • type 参数表示请求的是:流行、新款还是精选的商品数据
    • page 参数表示请求的数据页数
  4. 初始化商品数据对象,在 data 中创建 goods 对象,由 pop、new 和 sele 对象数据组成

  5. 在 methods中创建请 goods 的方法 getHomeGoods()

    • 定义 pages 常亮,表示拿到的 data 中 goods 对象的对应 type 的那条数据
    • page 是当前已加载的页面数量,并对其自动加1
    • 在请求数据时获取的就是对应 type 当前已加载页面的总数据
  6. 将商品数据 goods 数据传给子组件 GoodsList,并完成子组件中 商品数据的 渲染

    • 定义 props 中的 goods 数据
    • 用 v-for 遍历 goods 中的数据在 GoodsItem 组件上
    • 完成 GoodsList 组件中的样式
  7. 将每个 item 对象数据通过 :goods-item 属性传递给子组件 GoodsItem

    • 完成 GoodsItem 组件中的数据结构和样式的渲染
    • 将图片数据通过计算属性中的 showImage() 返回

3.12 通过TabControl组件上的点击来实现商品列表的内容切换

  1. 在首页的 TabControl 组件上绑定 @tabclick 点击事件
  2. 在 TabControl 组件内的 itemClick 方法中使用 $emit 方法将获取的 currentIndex 的值传给 @tabclick 点击事件
  3. 在首页创建 tabClick() 方法来监听点击的 currentIndex 索引的对应的 title 名,也就是 currentType 的值
  4. tabClick() 使用 switch 条件判断
  5. 创建 计算属性 showGoods() 的值为, 对应点击 this.currentType 的goods 的商品数据
  6. showGoods() 的值会通过绑定的 :goods 属性传递给子组件 GoodsList
  7. 由于进入首页时 TabControl是点击选中的第一 tab 位置,
    • 方法一:在 created 函数中增加一次点击事件,即调用一次 tabClick(0)
    • 因此在 tabClick() 方法中需要通过 if判断 this.$refs.tabControl !== undefined
    • 方法二:在 mounted 中进行点击就不需要 if 判断

3.13 使用 better-scroll 插件完成局部滚动

  1. 创建并引入 scroll 组件
    npm install better-scroll --save
  2. 初始化代码,创建 BScroll 对象,使用 probeType 参数来监听滚动
  3. 监听滚动事件并获取滚动的位置 position
  4. 使用 pullUpLoad 参数做上拉加载的功能
    • 判断 this.pullUpLoad 是否为 true,如果为 true就使用 on 方法监听 pullingUp 事件
    • 在首页该事件下调用加载更多方法 loadMore(),去掉 getHomeGoods 请求方法获取数据
  5. 当上拉加载数据加载完毕后,需要调用 finishPullUp 告诉 better-scroll 数据已加载

3.14 封装backtop组件,回到顶部

  1. 创建并引入 backTop 组件
  2. 完成回到顶部的图片结构和样式
  3. 在首页通过 @click.native 监听点击事件 backClick() 方法
    • native 修饰符:监听组件根元素的原生事件
  4. 在 scroll 组件中封装 scrollTo() 方法,通过 backClick 方法去调用 scrollTo 方法回到顶部
  5. 在首页 backTop 组件中 使用指令 v-show 来控制按钮的显示和隐藏
    • 定义 isShowBackTop 初始化值为 false
    • 并在 scroll 组件上绑定 contentScroll 方法来实现:当滚动到某一位置时按钮显示,也就是 -position.y > 1000 时 isShowBackTop 为 true

3.15 解决部分图片未加载出来导致的滚动首页区域卡顿的问题

事件总线.png
  1. 使用事件总线技术:

    • 在子组件中 GoodsItem 通过 this.$bus.$emit("事件名") 发射事件给事件总线
    • 再在首页中通过 this.$bus.$on("事件名", 回调函数) 来监听事件总线
  2. 在 GoodsItem 组件中使用 @load="imageLoad" 监听图片加载完成事件 itemImageLoad

  3. 通过 this.$bus.$emit("itemImageLoad") 将其发送给事件总线

  4. 在首页 mounted() 中监听事件总线中 itemImageLoad 事件的变化,

this.$bus.$on("itemImageLoad", () => {}) 

注意:是在 mounted() 中调用而不是在 created() 中调用

  1. 此时需要在 main.js 中创建一个原型属性 Vue.prototype.$bus = new Vue() ,给 $bus 赋值一个vue实例,他是可以作为事件总线的。那么就可用这个vue实例发射事件和监听事件
  2. 再在首页的 this.$bus.$on() 中掉 refresh() 方法来重新拿到滚动区域的高度

3.16 防抖操作,解决refresh非常频繁调用的问题

  1. 创建防抖函数 debounce(){}
debounce(func, delay) {
      let timer = null;
      return function(...args) {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(this, args);
        }, delay);
      };
    }
  1. 防抖函数起作用的过程:
    • 如果我们直接执行 refresh ,那么 refresh 函数会被执行30次
    • 可以将 refresh 函数传入 debounce 函数中,生成新的函数
    • 之后在调用非常频繁的时候,就使用新生成的函数
    • 而新生成的函数,并不会频繁调用,如果下一次执行来的非常快,那么会将上一次取消掉
  2. 防抖的目的:为了让我们执行非常频繁的函数等一会,等一会是否还要执行该函数,如果要执行就合并到一起,一起等;等到 delay 时间内没有下一次函数要执行,再真正执行某一个函数。这样可以该函数的执行频率很低。

3.17 TabControl 组件的吸顶效果

  1. 必须知道向上滚动多少,才会有吸顶效果
  2. 先获取到 TabControl 的 offsetTop
    • this.$refs.centerTabcontrol.offsetTop 该方式获取不到 offsetTop,因为组件是没有 offsetTop
    • 需要去获取组件里面的元素的 offsetTop 值
    • 所有的组件都有一个 $el 属性,用来获取组件中的元素
    • 但是在 mounted() 函数中去获取 offsetTop 时首页的图片还未加载完,此时的值是不准确的
  3. 在首页轮播监控图片是否加载完
    • 在组件 HomeSwiper 中添加图片监控 @Load=“imageLoad”
    • 在 methods 中添加该 imageLoad 方法
    • 将监听方法 swiperImageload 发送给首页 this.$emit(“swiperImageload”)
    • 为了防止有多张图片发送多次,使用 isload 来做判断:通过 if 当已经发送过一次后,设置 isload 为 true,就会停止发送 swiperImageload
  4. 监听滚动,动态的改变 tabControl 组件的样式
    • 如果通过 position: fixed 来改变 tabControl 组件的样式来达到吸顶效果会有问题
    • 问题1:下面的商品列表内容会突然上移;
    • 问题2:tabControl 组件会随着滚动组件一起滚出屏幕
  5. 通过在 navbar 组件下面再复制一份 tabControl 组件,控制滚动时 tabControl 的显示隐藏
    • 设置一个 class:“top-tabcontrol” 用来控制顶部的 tabControl 组件显示的样式
    • 设置 isTabFixed: false 用来判断当他为 true 时,顶部的 tabControl组件显示
    • 通过监听滚动位置函数 contentScroll(position) 中判断滚动的位置是否大于 tabOffsetTop,当滚动的位置大于 tabOffsetTop 时,顶部的 tabControl 显示
    this.isTabFixed = -position.y > this.tabOffsetTop;
    
    • 为了保证吸顶后顶部的 tabControl 的功能正常,需要在 tabClick() 中同样监控顶部的 tabControl 的点击,将 index 的值赋给 currentIndex

3.18 离开首页后再回来保持原来的位置

  1. 用户离开首页再回来,会重新回到首页顶部,这是应为离开首页后,首页被销毁执行了 destroyed() 生命周期函数导致
  2. 此时需要在 App.vue 中 <router-view /> 前面包一个 <keep-alive>
  3. 当我们离开首页时,保存一个 saveY
  4. 进来时,将位置设置为原来保存的位置 saveY 信息即可
  5. 使用 deactivated(){} 函数来记录离开首页时的位置 this.saveY
  6. 使用 activated(){} 函数当回到首页时瞬间滚动到记录的 this.saveY ,并刷新让下次从新记录位置
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容