ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Vue2外卖总结

2022-03-19 10:58:52  阅读:187  来源: 互联网

标签:总结 vue const 外卖 2x jpg js Vue2 png


Vue2外卖总结

先看一下效果,这是跟随硅谷外卖做的一个小项目。但是很多都是没有接口导致许多不太一致。

请添加图片描述

简介:

​ 这是一个基础Vue2实现的一个外卖项目,部分图如上所示,数据没有调用一个接口,全都是模拟数据。相关视频在哔哩哔哩尚硅谷。链接https://www.bilibili.com/video/BV1hs411E7cB?spm_id_from=333.337.search-card.all.click 。组件部分:axios better-scroll core-js element-ui mockjs swipper vuex xue-router等

目录结构为:

srcApp.vuemain.jssrc.txtapiajax.jsindex.jscommonstylusmixins.stylcomponentsAlertTipAlertTip.vueCartControlCartControl.vueFoodFood.vueFoosterGuideFoosterGuide.vueHeaderTopHeaderTop.vueShopCartShopCart.vueShopHeaderShopHeader.vueShopListShopList.vueimagesshop1.jpg2.jpg3.jpg4.jpgstarsstar24half@2x.pngstar24off@2x.pngstar24on@2x.pngstar36half@2x.pngstar36off@2x.pngstar36on@2x.pngstar48half@2x.pngstar48off@2x.pngstar48on@2x.pngStarstar.vuestarsstar24half@2x.pngstar24off@2x.pngstar24on@2x.pngstar36half@2x.pngstar36on@2x.pngstar48half@2x.pngstar48off@2x.pngstar48on@2x.pngfiltersmockmock.jspagesLoginLogin.vueimagescaptcha.svgMsiteMsite.vueOrderOrder.vueimagesorderperson.pngProfileProfile.vueSearchSearch.vueShopShop.vueShopGoodsShopGoods.vueShopInfoShopInfo.vueShopRatingsShopRating.vuerouterindex.jsstaticstoreactions.jsgetters.jsindex.jsmutations.jsstate.js src │ App.vue │ main.js │ src.txt │ ├─api │ ajax.js │ index.js │ ├─common │ └─stylus │ mixins.styl │ ├─components │ ├─AlertTip │ │ AlertTip.vue │ │ │ ├─CartControl │ │ CartControl.vue │ │ │ ├─Food │ │ Food.vue │ │ │ ├─FoosterGuide │ │ FoosterGuide.vue │ │ │ ├─HeaderTop │ │ HeaderTop.vue │ │ │ ├─ShopCart │ │ ShopCart.vue │ │ │ ├─ShopHeader │ │ ShopHeader.vue │ │ │ ├─ShopList │ │ │ ShopList.vue │ │ │ │ │ └─images │ │ ├─shop │ │ │ 1.jpg │ │ │ 2.jpg │ │ │ 3.jpg │ │ │ 4.jpg │ │ │ │ │ └─stars │ │ star24_half@2x.png │ │ star24_off@2x.png │ │ star24_on@2x.png │ │ star36_half@2x.png │ │ star36_off@2x.png │ │ star36_on@2x.png │ │ star48_half@2x.png │ │ star48_off@2x.png │ │ star48_on@2x.png │ │ │ └─Star │ │ star.vue │ │ │ └─stars │ star24_half@2x.png │ star24_off@2x.png │ star24_on@2x.png │ star36_half@2x.png │ star36_on@2x.png │ star48_half@2x.png │ star48_off@2x.png │ star48_on@2x.png │ ├─filters ├─mock │ mock.js │ ├─pages │ ├─Login │ │ │ Login.vue │ │ │ │ │ └─images │ │ captcha.svg │ │ │ ├─Msite │ │ Msite.vue │ │ │ ├─Order │ │ │ Order.vue │ │ │ │ │ └─images │ │ └─order │ │ person.png │ │ │ ├─Profile │ │ Profile.vue │ │ │ ├─Search │ │ Search.vue │ │ │ └─Shop │ │ Shop.vue │ │ │ ├─ShopGoods │ │ ShopGoods.vue │ │ │ ├─ShopInfo │ │ ShopInfo.vue │ │ │ └─ShopRatings │ ShopRating.vue │ ├─router │ index.js │ ├─static └─store actions.js getters.js index.js mutations.js state.js src│App.vue│main.js│src.txt│├─api│ajax.js│index.js│├─common│└─stylus│mixins.styl│├─components│├─AlertTip││AlertTip.vue│││├─CartControl││CartControl.vue│││├─Food││Food.vue│││├─FoosterGuide││FoosterGuide.vue│││├─HeaderTop││HeaderTop.vue│││├─ShopCart││ShopCart.vue│││├─ShopHeader││ShopHeader.vue│││├─ShopList│││ShopList.vue│││││└─images││├─shop│││1.jpg│││2.jpg│││3.jpg│││4.jpg│││││└─stars││star24h​alf@2x.png││star24o​ff@2x.png││star24o​n@2x.png││star36h​alf@2x.png││star36o​ff@2x.png││star36o​n@2x.png││star48h​alf@2x.png││star48o​ff@2x.png││star48o​n@2x.png│││└─Star││star.vue│││└─stars│star24h​alf@2x.png│star24o​ff@2x.png│star24o​n@2x.png│star36h​alf@2x.png│star36o​n@2x.png│star48h​alf@2x.png│star48o​ff@2x.png│star48o​n@2x.png│├─filters├─mock│mock.js│├─pages│├─Login│││Login.vue│││││└─images││captcha.svg│││├─Msite││Msite.vue│││├─Order│││Order.vue│││││└─images││└─order││person.png│││├─Profile││Profile.vue│││├─Search││Search.vue│││└─Shop││Shop.vue│││├─ShopGoods││ShopGoods.vue│││├─ShopInfo││ShopInfo.vue│││└─ShopRatings│ShopRating.vue│├─router│index.js│├─static└─storeactions.jsgetters.jsindex.jsmutations.jsstate.js

主要模块

1.登录注册(未注册自动注册)

2.个人中心

3.外卖首页

4.商家部分(商品列表,评价,等等)

功能实现

1.手机号验证,验证码验证,验证码设定时效

2.首页上方轮播图(非自动轮播)

3.购物车部分(查看,修改,遮盖)

4.评价筛选部分(过滤)

5.评价分数星计算

1.注册登录

​ 登录部分两种不同的登录方式,短信登录与密码登录。使用正则对手机号格式验证,格式正确才能够发送验证码,否则发送验证码按钮为disable。验证码通过mock随机数生成,设置指定时间让其消失,实现验证码时效效果。当手机号或者验证码不正确弹出提示框。

2.首页

​ 上方为轮播,需要滑动显示轮播效果。categorysArr页面为挂载时,使用mock获取的数据。通过设置watch监视,来判断categorysArr当中是否已经存在数据。this.$nextTick(), 作用就是等待页面渲染完毕后再去执行当中代码。因为需要计算高度。下方商家列表是v-for循环遍历mock数据,来渲染页面。

    <nav class="msite_nav">
      <div class="swiper">
        <div class="swiper-wrapper">
          <div
            class="swiper-slide"
            v-for="(categorys, index) in categorysArr"
            :key="index"
          >
            <a
              href="javascript:"
              class="link_to_food"
              v-for="(category, index) in categorys"
              :key="index"
            >
              <div class="food_container">
                <img :src='category.img_url' alt="">
              </div>
              <span>{{ category.name }}</span>
            </a>
          </div>
        </div>
        <!-- 如果需要分页器 -->
        <!-- <div class="swiper-pagination"></div> -->
        <!-- 如果需要滚动条 -->
        <!-- <div class="swiper-scrollbar"></div> -->
      </div>
    </nav>
  watch: {
    categorys() {
      if (this.categorysArr.length !== 0) {
        this.$nextTick(() => {
          new Swiper(".swiper", {
            // loop 设置左右滑动模式 如果是true则会无限滑动
            // loop: true, // 循环模式选项
            // 如果需要分页器 pagination指的是分页器
            // pagination: {
            //   el: ".swiper-pagination",
            // },
            // scrollbar: {
            //   el: ".swiper-scrollbar",
            // },
            // 如果需要前进后退按钮
            // navigation: {
            //   nextEl: ".swiper-button-next",
            //   prevEl: ".swiper-button-prev",
            // },
          });
        });
      }
    },
  },

3.个人中心

​ 首先就是判断用户使用哪种登录方式来显示登录页面的不同内容。以及首页右上角是显示登录还是已经登录。未登录不会显示立即退出按钮。未绑定手机号显示手机号为绑定。如果绑定则不显示。

4.商家

(1)商品列表

​ 单击加号放入购物车,当购物车当中没有该商品数据则减号不显示。价格对应下方计算,三种显示模式,未选中商品,显示 ¥20起送;选中但是为满20元起送显示 还差¥XX元起送 ;>=20元,则显示为绿色结算。购物车部分对应显示商品列表,并且小圆点显示购物车当中数量。

​ 左侧导航栏点击后,会跳转到对用商品列表,跳转过程商品列表滑动显示。需要先获取对用列表的top值,然后为每一个li添加点击事件,让top值修改为对应top值的高度。

​ 对应购物车当中的数据也是存储在vuex当中,相关vuex的讲解我也有文章讲解,感兴趣的各位可以去查看我的vuex当中的解释。

methods: {
    // 相关better-scroll都能够在官网查找到相关的api

    //  初始化滑动
    initScroll() {
      this.scroll =  new BScroll(".menu-wrapper",{
        mouseWheel: true,
        click: true
      });
      this.foodScroll = new BScroll(".foods-wrapper", {
        probeType: 2, // 惯性滑动不会触发
        mouseWheel: true,
        // 可能会出现兼容性的问题,所以在此处最好还是加上
        click: true,
      });
      // 绑定滚动监听
      this.foodScroll.on("scroll", ({ x, y }) => {
        // console.log(y);
        this.scrollY = Math.abs(y); //返回绝对值
      });
      //  解决惯性滑动不刷新的bug
      this.foodScroll.on("scrollEnd", ({ x, y }) => {
        // console.log(y);
        this.scrollY = Math.abs(y); //返回绝对值
      });
      this.scroll.refresh();
      this.foodScroll.refresh();
    },
    //  初始获取top
    initTops() {
      let top = 0;
      this.tops.push(top);
      const lis = this.$refs.foodsUl.getElementsByClassName("food-list-hook");
      Array.prototype.slice.call(lis).forEach((li) => {
        top += li.clientHeight;
        this.tops.push(top);
        // console.log(this.tops);
      });
    },
    //  获取索引  左侧点击切换 scroolTo(x, y, time, easing(缓动函数,一般不建议修改))
    clickMenu(index) {
      this.scrollY = -this.tops[index];
        // scrollTo显而易见滚动到,后面300位时间 
      this.foodScroll.scrollTo(0, this.scrollY, 300);
    },
    //  点击显示Food,小图切换大图显示
    showFood(food) {
      this.food = food;
      this.$refs.food.toggleShow();
    },
  },
      // 挂载的时候调用上方方法,this.$nextTick等获取到数据后执行
   mounted() {
    this.$store.dispatch("get_restaurant", () => {
      this.$nextTick(() => {
        this.initScroll();
        this.initTops();
      });
    });
  },

这是相关html当中的内容

      <div class="foods-wrapper">
        <ul ref="foodsUl">
          <li
            class="food-list-hook"
            v-for="(good, index) in goods"
            :key="index"
          >
            <h1 class="title">{{ good.name }}</h1>
            <ul>
              <li
                class="food-item bottom-border-1px"
                v-for="(food, index) in good.foods"
                :key="index"
              >
                <div class="icon">
                  <img
                    width="57"
                    height="57"
                    :src="food.image"
                    @click="showFood(food)"
                  />
                </div>
                <div class="content">
                  <h2 class="name">{{ food.name }}</h2>
                  <p class="desc">{{ food.description }}</p>
                  <div class="extra">
                    <span class="count">月售{{ food.sellCount }}份11</span>
                    <span>好评率{{ food.rating }}%</span><br /><br />
                    <span class="now">¥{{ food.price }}</span>
                    <span class="old" v-if="food.oldPrice"
                      >¥{{ food.oldPrice }}</span
                    >
                  </div>
                  <div class="cartcontrol-wrapper"></div>
                  <CartControl :food="food" />
                </div>
              </li>
            </ul>
          </li>
        </ul>
      </div>
(2)评价

​ 需要计算星星,该部分为一个通用组件,计算方法如下代码,读者自行查看结构挺简单的。

<template>
  <!-- 接收参数 -->
  <div class="star" :class="'star-' + size">
    <span
      class="star-item"
      v-for="(sc, index) in starClasses"
      :class="sc"
      :key="index"
    ></span>
  </div>
</template>

export default {
  name: "Star",
    // 组件调用需要传过来参数,评价分数,以及星星大小
  props: {
      // 传过来的分数
    score: Number,
      // 使用星星的大小
    size: Number,
  },
  computed: {
    starClasses() {
      const score = this.score;
      const scs = [];
        // ons代表满星几颗
      const ons = Math.floor(score);
      for (let i = 0; i < ons; i++) {
        scs.push("on");
      }
        // 首先半星只会出现 0 或 1 个由于小数部分计算会出现问题,所以采用*10计算
      const halfs = (score * 10) % 10;
      if (halfs > 5) {
        scs.push("half");
      }
        // 总分为5颗星,其他的(满星,半星)添加进来后剩下的都是灰色星星
      while (scs.length < 5) {
        scs.push("off");
      }
      return scs;
    },
  },
};

​ 下方评价现实就是一个过滤器,拿到mock模拟的评价数组,根据不同的点击事件,来显示不同的内容。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J7k1RuuH-1647658347669)(C:\Users\86150\AppData\Roaming\Typora\typora-user-images\image-20220319104201722.png)]

(3)商家信息

​ 首先还是拿到由mock模拟的数据,然后渲染页面。值得一提的是,图片的左右滑动。

      <section class="section">
        <h3 class="section-title">商家实景</h3>
        <div class="pic-wrapper">
          <ul class="pic-list" ref="picsUl">
            <li class="pic-item" v-for="(pic, index) in info.pics" :key="index">
              <img width="120" height="90" :src="pic" />
            </li>
          </ul>
        </div>
      </section>
  methods: {
    initScroll() {
      new BScroll(".shop-info", {
        click: true,
      });
        // 首先拿到ref
      const ul = this.$refs.picsUl;
        // 每张图片大小 120px
      const Width = 120;
        // 间隔 6px
      const space = 6;
        // 用来动态计算数组长度,来设置宽度
      const count = this.info.pics.length;
      ul.style.width = (Width + space) * count - space + "px";
      new BScroll(".pic-wrapper", {
        click: true,
        scrollX: true,
      });
    },
  },

o", {
click: true,
});
// 首先拿到ref
const ul = this.$refs.picsUl;
// 每张图片大小 120px
const Width = 120;
// 间隔 6px
const space = 6;
// 用来动态计算数组长度,来设置宽度
const count = this.info.pics.length;
ul.style.width = (Width + space) * count - space + “px”;
new BScroll(".pic-wrapper", {
click: true,
scrollX: true,
});
},
},


标签:总结,vue,const,外卖,2x,jpg,js,Vue2,png
来源: https://blog.csdn.net/qq_53157160/article/details/123590666

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有