小言_互联网的博客

Vue商城——详情页功能

334人阅读  评论(0)

详情页实现思路

点击商品进去详情页,根据点击请求更加详细的信息,要传过来goodsItem的iid,根据id去服务器请求更加详细的信息;配置路由映射关系,点击进行跳转,带参数传递跳转

itemClick(){
        this.$router.push('/detail/'+this.goodsItem.iid)
        /* this.$router.push({
          path:'/detail',
          query:{
            iid:this.goodsItem.iid
          }
        }) */
      }

但是获取到的iid在更换点击商品时没有改变,并没有发生新的请求,因为发生了路由跳转,router-view由keep-alive包着,不会每次销毁并重新创建,所以不会给iid给新的值,详情页不要使用keep-alive,使用exclude属性

<keep-alive exclude="Detail">
	<router-view></router-view>
</keep-alive>

首页的位置保持不变

指定版本安装better-scroll npm install better-scroll@1.13.2 --save
用keep-alive标签把router-view标签包住,点击其他导航栏,再点击首页,自动回到顶部,不是因为创建了新的Home.vue,获取离开时滚动的位置,再次进入的时候设置保存的位置。【频繁切换还是会自动回到顶部???】

导航栏的封装

1.在childComps中创建组件DetailNavBar.vue,在组件中引入公共组件TabBar,替换TabBar组件中的插槽,在详情页Detail中引入封装好的导航栏DetailNavBar,
2.引入一个返回图标,绑定点击事件,点击之后会返回到之前进入的状态
3.将导航栏中的标题定义成数组titles然后遍历,进行flex布局
4.标题点击谁,谁就变成红色
** 定义一个当前索引currentIndex,动态绑定class,动态绑定点击事件 【此处是否可以直接引入tabControl组件??】

加入滚动的效果Scroll

1.指定版本安装better-scroll npm install better-scroll@1.13.2 --save
2.详情页的底部导航栏NavBar不用展示,可以给详情页相对布局并设置层级关系,给一个白色的背景色,详情页就可以脱离原来的标准流,把底部导航栏隐藏了
3.顶部的导航栏在DetailNavBar组件中设置相对定位层级关系和背景颜色
4.仍然选择better-scroll,引用之前封装好的Scroll,把要滚动的东西用scroll包裹住,替换Scroll里面的插槽
5.scroll需要有固定的高度,让父元素有100%的视口高度

一、滚动的问题

推荐数据使用goodslistitem展示时,用了load监听,图片加载完了会通知首页,但是我们不需要通知首页。我们需要区分。发出事件的时候做一下路由判断。

imageLoad(){
      if(this.$router.path.indexOf('/home')){
        this.$bus.$emit('homeItemImageLoad')
      } else if(this.$router.path.indexOf('/detail')){
        this.$bus.$emit('detailItemImageLoad')
      }
    },

再在详情页监听图片是否加载完成,但是最后离开的时候还是要取消

详情数据请求

1.保存从首页商品展示传入的iid
2.根据iid请求详情数据
** 在network的detail.js中封装getDetail,发出网络请求

一、轮播图的封装

  • 在childComps中创建组件DetailSwiper.vue,在组件中引入公共组件Swiper,SwiperItem,在详情页Detail中引入封装好的DetailSwiper
  • 根据请求到的数据topImages轮播展示商品,定义了一个变量,把topImages进行保存,图片太大了,给swiper设置固定的高度

二、商品基本信息的封装

  • 抽离组件需要的数据,再把抽离的数据传给组件,把杂乱的数据整合成一个对象,导出class类对象Goods保存的一些商品信息
  • 在childComps中创建组件DetailBaseInfo.vue,封装一些商品基本信息,在详情页Detail中引入封装好的DetailBaseInfo
    • 要先判断是否有商品信息,有再渲染,怎么判断呢?
    • v-if="Object.keys(goods).length !== 0" 看goods是不是一个空的对象

三、商家基本信息的封装

  • 导出class类对象Shop保存的一些商品信息
  • 在childComps中创建组件DetailShopInfo.vue,封装一些商家信息,在详情页Detail中引入封装好的DetailShopInfo
  • 在显示总销量时,有个过滤器
filters: {
      sellCountFilter: function (value) {
        if (value < 10000) return value;
        return (value/10000).toFixed(1) + '万'
      }
    }

四、商品详情的封装

  • 在childComps中创建组件DetailGoodsInfo.vue,封装一些商品详细信息,在详情页Detail中引入封装好的DetailGoodsInfo
  • 在滚动的过程中,可能出现不能滚动的现象,是因为better-scroll在计算滚动区域时,图片还没加载出来,所以需要先监听图片是否加载完成
    • 首页要获取图片的个数,然后定义一个计数变量,当两者相等时,就可以发出图片加载完成的事件,
    • 在详情页面中,对滚动区域进行刷新
// 监听detailInfo这个对象的变化
    watch:{
      detailInfo(){
        //获取图片的个数
        this.imageLength=this.detailInfo.detailImage[0].list.length
      }
    },
    methods: {
      imageLoad(){
        // 先判断一下,只发出一次事件,不然有几张图片就发出几次事件
        // 所有的图片都加载完成之后,进行一次回调
        if(++this.counter===this.imageLength){
          this.$emit('imageLoad')
        }
      }
    },

五、商品参数的封装

  • 导出class类对象GoodsParam保存的一些商品参数信息
  • 在childComps中创建组件DetailParamInfo.vue,封装一些商品参数信息,在详情页Detail中引入封装好的DetailParamInfo
  • 参数用table布局

六、商品评论信息的封装

  • 评论信息的获取
    ** 在接口的result->rate里面
    ** cRate 当前商品一共有多少评论 点击更多按钮跳转到另一个页面 展示更多评论信息
    ** list[0] 取出一条评论信息在详情页进行展示
    ** 定义commentInfo对象 保存取出来的评论信息 有可能没有评论信息 先判断
  • 评论信息的展示
    ** 在childComps中创建组件DetailCommentInfo.vue,封装一些评论信息,在详情页Detail中引入封装好的DetailCommentInfo
    ** 过滤器将时间格式化 formatDate 从utils中引入
filters: {
		  showDate: function (value) {
        // 将时间戳转成Date对象
        let date = new Date(value*1000);
        // 将date进行格式化
        return formatDate(date, 'yyyy/MM/dd')
      }
    }

七、商品推荐信息的封装

  • 推荐数据的获取
    ** 在detail.js中弄一个接口,不用传参数
export function getRecommend() {
  return request({
    url: '/recommend',
  })
}

** 在详情页中将接口函数导入,定义一个recommends数组,在created中请求推荐数据

  • 推荐数据的展示
    ** 不需要创建一个新的子组件,可以直接用之前的GoodsList组件,
    ** 在详情页中导入GoodsList组件并注册使用
    ** 弄个计算属性computed,取展示的图片数据

首页和详情页监听全局事件的mixin的使用

** mixin 混入

底部工具栏

一、底部工具栏的封装

二、将商品添加到购物车

** 1.给“加入购物车”添加点击事件,发送一个事件,因为是在子组件中监听,
** 2.在详情页中监听点击,先获取商品的信息,这些信息要展示在购物车页面中;
** 3.将商品添加进购物车,在详情页将商品添加到某个位置,在购物车界面将信息进行展示,用到vuex

addToCart(){
      // 1.获取购物车需要展示的信息
      const product={}
      product.image=this.topImages[0]
      product.title=this.goods.title
      product.desc=this.goods.desc
      product.cartPrice=this.goods.cartPrice
      product.iid=this.iid
      // 2.将商品添加到购物车
      this.$store.dispatch('addCart',product)
    }

三、将商品添加到store中

** 0.安装vuex npm install vuex --save
** 1.在文件夹store中新建一个文件,导入vue,vuex,安装插件,创建store对象,挂载到Vue实例上,在main.js中导入store
** 2.定义一个数组变量cartList在其中存放商品,修改任何state中的状态都要通过mutations,mutations中每一个方法完成的事件尽可能单一

[ADD_COUNTER](state, payload) {
    payload.count++;
  },
[ADD_TO_CART](state, payload) {
    state.cartList.push(payload);
  }

** 3.逻辑判断在actions中

addCart(context, payload) {
    // 1.查找之前的数组中是否有该商品
    let oldProduct = context.state.cartList.find(
      item => item.iid === payload.iid
    );
    // 2.判断oldProduct
    if (oldProduct) {
      context.commit(ADD_COUNTER, oldProduct);
    } else {
      payload.count = 1;
      context.commit(ADD_TO_CART, payload);
    }
  }

四、添加购物车弹窗


** 1.在components的common文件夹中新建一个toast文件夹,因为还可以在其他项目中使用,创建一个Toast组件,
** 2.让弹窗垂直水平居中布局,
** 3.控制弹窗的显示和隐藏,v-show定义一个变量isShow,默认不显示,属性值设置为false,还定义个弹窗显示内容的变量message,点击“加入购物车”后显示,过一会儿就隐藏,使用定时器
** 4.在Detail组件中导入,注册并使用
** 5.点击“加入购物车”后显示,过一会儿就隐藏,使用定时器

if (oldProduct) {
        context.commit(ADD_COUNTER, oldProduct);
        resolve('当前的商品数量+1')
      } else {
        payload.count = 1;
        context.commit(ADD_TO_CART, payload);
        resolve('添加购物车成功')
      }
this.$store.dispatch('addCart',product).then(res=>{
        this.isShow=true;
        this.message=res
        setTimeout(() => {
          this.isShow=false;
          this.message=''
        }, 1500);

另一种封装:
** 0.把这个组件封装在一个插件里面,先创建这个组件,最开始的时候就把这个组件添加进body里面,然后安装这个插件,安装这个插件就预备好了
** 1.在main.js文件里面导入toast,安装插件,执行install函数,
** 2.在toast文件夹里面新建index文件,在index中导入Toast组件,在install函数里面把需要的东西预备好

obj.install=function(Vue){
  // 1.创建组件构造器
  const toastContrustor = Vue.extend(Toast)
  // 2.new的方式,根据组件构造器,可以创建一个组件对象
  const toast = new toastContrustor()
  // 3.将组件对象,手动挂载到某一个元素上
  toast.$mount(document.createElement('div'))
  // 4.toast.$el对应的就是div
  document.body.appendChild(toast.$el)
  Vue.prototype.$toast = toast
}

** 3.在Toast组件中写一个show方法

show(message,duration=2000){
      // duration=duration || 3000
      this.isShow=true;
      this.message=message
      setTimeout(() => {
        this.isShow=false;
        this.message=''
      }, duration);
    }

** 4.在Detail组件中调用show方法

this.$store.dispatch('addCart',product).then(res=>{
        this.$toast.show(res,2000)
      })

转载:https://blog.csdn.net/qq_41217480/article/details/105632335
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场