首页 > 其他分享 >vue3项目-小兔鲜儿笔记-商品详情页01

vue3项目-小兔鲜儿笔记-商品详情页01

时间:2022-09-04 23:22:31浏览次数:64  
标签:遮罩 01 const 鼠标 容器 鲜儿 value 详情页 changeResult

1. 基础布局

完成商品详情基础布局,路由配置,搭好页面架子

 

 

2. 渲染面包屑

编写一个钩子函数useGoods.js,将面包屑获取数据的逻辑抽取出来。

// 拿到商品信息
import { findGoods } from '@/api/product'
import { nextTick, ref, watch } from 'vue'
import { useRoute } from 'vue-router'

const useGoods = () => {
  const route = useRoute()

  const goods = ref(null)

  watch(
    () => route.params.id,
    (newVal) => {
      // 先判断路由是否为/product/id,是这个路由才发送查找商品详情的请求
      if (newVal && `/product/${newVal}` === route.path) {
        findGoods(newVal).then(({ result }) => {
          // 先置空,让依赖于goods的组件(v-if=goods)这些组件可以先销毁再创建
          goods.value = null
          nextTick(() => {
            goods.value = result
          })
        })
      }
    },
    { immediate: true }
  )

  return {
    goods
  }
}

export default useGoods

// 面包屑组件中使用:
// goods-bread:
const { goods } = useGoods()

 

3.图片放大镜

  • 首先准备大图容器和遮罩容器

  • 使用@vueuse/core的useMouseInElement方法获取基于容器的偏移量elementX和elementY,以及是否鼠标在容器范围外isOutside

  • 通过调整遮罩容器的left和top定位以及调整大图容器的背景图片的backgroundPositionX和backgroundPositionY定位,实现图片放大镜的功能。

// 大图容器  
.large {
    position: absolute;
    top: 0;
    left: 412px;
    width: 400px;
    height: 400px;
    box-shadow: 0 0 10px rgba(0, 8, 8, 0.1);
    background-repeat: no-repeat;
    background-size: 800px 800px;
    background-color: #f8f8f8;
  }

// 遮罩容器
 .layer {
      position: absolute;
      left: 0;
      top: 0;
      width: 200px;
      height: 200px;
      background: rgba(0, 0, 0, 0.2);
    }

 

抽取图片放大镜逻辑到usePreviewImage.js中,使得图片预览组件没有那么臃肿

初始数据:
  // 要观察的容器
  const target = ref(null)
  // 是否显示遮罩层和大图背景
  const show = ref(false)
  // 遮罩层坐标(左上角),因为遮罩层是绝对定位,设置成left、top
  const layerPosition = reactive({
    left: 0,
    top: 0
  })
  // 大图背景坐标(左上角),因为大图是背景定位,设置成backgroundPositionX
  const largeImagePosition = reactive({
    backgroundPositionX: 0,
    backgroundPositionY: 0
  })

大致步骤:

  • 明确数据的含义

    • elementX 鼠标基于容器X轴的偏移量

    • elementY 鼠标基于容器Y轴的偏移量

    • isOutside 鼠标是否在容器外部

    • 这三个数据都是响应式变量

  • 监听这三个数据,让遮罩容器的坐标和大图背景坐标随着偏移量的变化而变化

    • 如何让鼠标位于遮罩容器的中心?遮罩容器左移和上移自身的一半,这里是减去100

    • 因为遮罩容器不能超出图片容器的范围,所以遮罩容器的左上角X轴最多移动距离:0~200

    • 因为大图背景显示的就是鼠标指的位置,且受限遮罩容器X轴的范围:0~200,导致鼠标最多移动范围:100~300。而大图背景移动方向是与鼠标相反的,鼠标往右,背景往左移,所以大图背景坐标移动的范围:-300~-100

  // elementX:鼠标基于容器X轴的偏移量
  // elementY: 鼠标基于容器Y轴的偏移量
  // isOutside: 鼠标是否在容器外部,这三个数据都是响应式变量
  const { elementX, elementY, isOutside } = useMouseInElement(target)
  // 监听这三个数据,让遮罩层坐标和大图背景坐标随着偏移量的变化而变化
  watch([elementX, elementY, isOutside], () => {
    show.value = !isOutside.value
    // 让鼠标位于遮罩层中心,就是让遮罩层左移和上移
    // 遮罩层的坐标范围:0~200,大图背景坐标范围:-300~-100,因为大图背景随着鼠标移动而移动,鼠标往右,背景往左移
    layerPosition.left = elementX.value - 100 + 'px'
    layerPosition.top = elementY.value - 100 + 'px'
    largeImagePosition.backgroundPositionX = -elementX.value + 'px'
    largeImagePosition.backgroundPositionY = -elementY.value + 'px'
    if (elementX.value <= 100) {
      layerPosition.left = 0
      largeImagePosition.backgroundPositionX = '-100px'
    }
    if (elementY.value <= 100) {
      layerPosition.top = 0
      largeImagePosition.backgroundPositionY = '-100px'
    }
    if (elementX.value >= 300) {
      layerPosition.left = '200px'
      largeImagePosition.backgroundPositionX = '-300px'
    }
    if (elementY.value >= 300) {
      layerPosition.top = '200px'
      largeImagePosition.backgroundPositionY = '-300px'
    }
  })

 

4. 城市组件的封装

初始数据:
const target = ref(null)
const visible = ref(false) // 控制窗口是否显示
const loading = ref(false) // 数据加载中状态
const cityData = ref([]) // 地区数组
// 根据点击的地区列表的按钮动态更改选择的地区结果
const changeResult = reactive({
  provinceCode: '',
  provinceName: '',
  cityCode: '',
  cityName: '',
  countyCode: '',
  countyName: '',
  fullLocation: ''
})
// 获取地址数据
// 1.地址在窗口打开的时候才获取
// 2.获取了地址之后要做全局缓存,因为数据量太大
// 3.获取了缓存之后下次打开窗口就直接从缓存中取,因此数据有可能是异步也有可能是同步获取,需要使用promise判断
const getCityData = () => {
  return new Promise((resolve, reject) => {
    if (window.cityData) {
      resolve(window.cityData)
    } else {
      const url =
        'https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json'
      axios.get(url).then(({ data }) => {
        window.cityData = data
        resolve(data)
      })
    }
  })
}
开关窗口的逻辑
const open = () => {
  visible.value = true
  // 获取地址数据
  loading.value = true
  getCityData().then((res) => {
    cityData.value = res
    loading.value = false
  })
}
const close = () => {
  visible.value = false
}
// 控制窗口是否显示
const toggleDialog = () => {
  visible.value ? close() : open()
}
// 当鼠标点击外部,关闭窗口
onClickOutside(target, () => {
  close()
})
点击地区组件的逻辑
// 点击地区列表的按钮时,根据点的是省还是市还是区做判断
const changeItem = (item) => {
  if (item.level === 0) {
      // 如果点击的是省,就拿到这个省的代码
    changeResult.provinceCode = item.code
    changeResult.provinceName = item.name
  }
  if (item.level === 1) {
      // 如果是点击的是市,就拿到这个市的代码
    changeResult.cityCode = item.code
    changeResult.cityName = item.name
  }
  // 如果已经点到区了,就说明是地址已经全部点完,可生成完整地址,并通知父组件地址已改变
  if (item.level === 2) {
    changeResult.countyCode = item.code
    changeResult.countyName = item.name
    changeResult.fullLocation = `${changeResult.provinceName} ${changeResult.cityName} ${changeResult.countyName}`
    // 把点击完生成的地址结果传给父组件
    emit('change', changeResult)
    close()
  }
}
地区列表的显示:
// 地区列表中显示的不一定是省的数据,可能会是市和区
// 但是会依赖于cityData来动态显示,根据已动态更改的地区结果改变渲染的地区列表
const currList = computed(() => {
  let list = cityData.value // 一开始默认展示的省列表
  // 可能是市,如果点击了某个省,就通过省代码找到这个省,获得这个省下的市列表进行展示
  if (changeResult.provinceCode) {
    list = list.find(
      (province) => province.code === changeResult.provinceCode
    ).areaList
  }
  // 可能是区,如果点击了某个市,就通过市代码找到这个市,获得这个市下的区列表进行展示
  if (changeResult.cityCode) {
    list = list.find((city) => city.code === changeResult.cityCode).areaList
  }
  return list
})

 

标签:遮罩,01,const,鼠标,容器,鲜儿,value,详情页,changeResult
From: https://www.cnblogs.com/jzhFlash/p/16656487.html

相关文章

  • 2022-2023-1 20201324《信息安全系统设计与实现(上)》第2章
    第2章编程背景目录第2章编程背景1Linux中的文本编辑器vim①简介②操作过程2程序开发(1)程序开发步骤(2)静态与动态链接静态链接动态链接(3)可执行文件(4)程序执行过程3链接库......
  • 20201330马榕辰第一,二章学习笔记
    第一章: 一.知识点归纳:第一章前半部分重在介绍课程和书本的基本情况,包括Unix / Linux的历史,其各种发行版,我了解到了一些基本情况。后半部分主要是 Linux的使用,Lin......
  • 20201306吴龙灿学习笔记
    一、知识点归纳:第一章:引言主要内容:第一章是本书的引子,因为本书意在让我们学会Unix以及Linux相关只是,在高级语言的基础上进一步学习创造编程平台的基本语言,让我们学会硬......
  • 20201329魏赫学习笔记一
    20201329信息安全系统设计与实现学习笔记①作业信息作业要求https://www.mosoteach.cn/web/index.php?c=interaction_homework&m=s_write&clazz_course_id=7C854F......
  • 20201322陈俊池 学习笔记1
    一、知识点归纳第一章:引言1.3本书目标(1)强化学生的编程背景知识(2)动态数据结构的作用(3)进程概念和进程管理(4)并发编程(5)定时器和定时功能(6)信号、信号处理和进程间通信(7......
  • D - path || 2019CCPC网络赛 || 贪心,优先队列,vector
    题意:求无起止点的k短路多组数据,效率约为nlogn解法:由于无起止点,就可以用类似kruskal的贪心思路,优先考虑最短的道路并计数。每使用一个当前最短道路,就入队一个次短道路......
  • 20201305学习笔记1
    第一章引言总述:在第一章刚开始这本书引入了Linux系统,告诉了我们Linux系统的发展历程和它的一些运行模式,他的版本,其中最主要讲的就是unbuntuLinux版本,讲了他的一些常用......
  • SQL server 2012 安装教程
    server2012安装教程链接:https://pan.baidu.com/s/1TgS0FHB_Rc9mvpO89QiUtQ?pwd=gyiq提取码:gyiq--来自百度网盘超级会员V3的分享点击“setup.exe”点击左侧"安装",......
  • 《Unix/Linux系统编程》第1,2章学习笔记 20201209戴骏
    一.知识点归纳第一章引言1.本书目标编程背景知识详细介绍了程序开发步骤,包括汇报器、编译器、链接器等。动态数据结构的应用字符串标记化、搜索树节点、插入和......
  • pycharm2017安装pygal
    1.pycharm2017安装pygal库   2.在Terminal对话框输入 python-mpipinstallpygal点击Enter即可自动安装。    ......