zoukankan      html  css  js  c++  java
  • 从零开始,搭建一个简单的购物平台(十四)前端商城部分

    从零开始,搭建一个简单的购物平台(十三)前端商城部分:
    https://blog.csdn.net/time_____/article/details/108514710
    项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

    本篇文章介绍实现部分组件和首页部分,首页组件如下,首页中的数据通过分批异步加载,也就是每个组件的数据单独请求,减少数据请求堵塞,下面介绍一下实现过程

    pageTitle(页面标题)

    • 首先要考虑到标题的返回功能,在methods里写个路由返回函数
       methods: {
          goBack() {
            this.$router.go(-1);
          }
        }
    • 接着通过组件属性传参数(标题内容,是否有返回按钮) ,通过props将组件属性放在当前data中

      props: ["title", "isBack"],
    • 标签中根据isBack决定是否有返回按钮,并显示title值

      <template>
        <div id="top">
          <span v-if="isBack" class="back iconfont icon-fanhui" @click="goBack"></span>
          <span class="title">{{title}}</span>
        </div>
      </template>

    banner(主页轮播)

    • 轮播图组件中的图片是单独请求的,所以用了model管理数据,bussiness进行请求,后面的组件有数据请求交互都是用这种写法
    • model.js内容,保存banner列表,vue实例,页面配置信息
      export default class BannerModel {//banner数据存取
        constructor() {
          this._bannerList = []
          this._pageConfig = {}
        }
        static getInstance() { //单例写法
          if (!BannerModel._instance) {
            Object.defineProperty(BannerModel, "_instance", {
              value: new BannerModel()
            })
          }
          return BannerModel._instance;
        }
        set vueComponent(val) {
          this._vueComponent = val
        }
        get vueComponent() {
          return this._vueComponent
        }
        set pageConfig(val) {
          this._pageConfig = val
          this._pageConfig.picType = 1
        }
        get pageConfig() {
          return this._pageConfig
        }
        set bannerList(val) {
          this._bannerList = val
          this._vueComponent.list = this.bannerList
        }
        get bannerList() {
          return this._bannerList
        }
      }
      
    • bussiness.js 做请求和逻辑处理
      import Vue from 'vue'
      import config from "../../config/config"
      import BannerModel from "./model";
      import Clone from "../../utils/clone"
      const {
        DefaultPageConfig,
        ServerApi
      } = config
      export default class BannerBussiness extends Vue {//业务处理
        constructor(_vueComponent) {
          super()
          BannerModel.getInstance().vueComponent = _vueComponent//取到显示层vue实例
          this.initPageConfig()
          this.getBanner()
        }
        initPageConfig() {//拷贝分页默认配置,并且不更改原常量
          BannerModel.getInstance().pageConfig = Clone.shallowClone(DefaultPageConfig)
        }
        getBanner() {//请求处理,this.$crypto.setCrypto加密
          this.$axios
            .get(ServerApi.shop.shopList, {
              params: {
                crypto: this.$crypto.setCrypto(BannerModel.getInstance().pageConfig)
              },
            }).then(res => {
              switch (res.result) {
                case 1:
                  BannerModel.getInstance().bannerList = res.data.list
                  break;
                default:
                  break;
              }
            })
        }
      }
      
    • banner.vue页面展示
      <template>
        <div class="swiper">
          <mt-swipe :auto="3000">
            <mt-swipe-item v-for="(item,index) in list" :key="index">
              <img class="imgs" :src="imgPath+item.shopPic" @click="clickHandler(item)" />
            </mt-swipe-item>
          </mt-swipe>
        </div>
      </template>
      
      <script>
      import { Swipe, SwipeItem } from "mint-ui";
      import Config from "../../config/config";
      import BannerBussiness from "./bussiness";
      export default {
        name: "banner",
        data() {
          return {
            list: [],//图片列表
            imgPath: Config.RequestPath//图片根路径
          };
        },
        created() {
          this.init();
        },
        methods: {
          init() {
            new BannerBussiness(this);//初始化banner请求
          },
          clickHandler(_shop) {//banner点击跳转
            this.$router.push({
              name: "ShopTheme",
              query: { _type: _shop.shopType, _shopName: _shop.shopName }
            });
          }
        }
      };
      </script>
      
      <style lang="less" scoped>
      @import "../../style/init.less";
      .imgs {
        .h(500);
         100%;
      }
      .swiper {
         100%;
        .h(500);
      }
      </style>

     tableBar(导航栏)

    • 在iconfont下载相对应的图标字体资源,我这里直接下载在style目录下,用类名的方式显示,在tabbar文件夹新建model.js用于取数据(其实这个可以放到config)
      export default class TableBarModel {
        static MenuList = [{
            name: "主页",
            path: "/Home",
            icon: "icon-shouye li iconfont"
          },
          {
            name: "分类",
            path: "/Kind",
            icon: "icon-fenlei li iconfont"
          },
          {
            name: "购物车",
            path: "/ShopCar",
            icon: "icon-daohang-gouwuche li iconfont"
          },
          {
            name: "我的",
            path: "/Info",
            icon: "icon-wode li iconfont"
          }
        ]
      }
      
    • tabbar.vue ,通过列表
      <template>
        <ul id="tab">
          <router-link
            v-for="(item, index) in menuList"
            :key="index"
            :to="item.path"
            tag="li"
            :class="item.icon"
            active-class="change"
            replace
          >
            <br />
            {{item.name}}
          </router-link>
        </ul>
      </template>
      
      <script>
      import tableBarModel from "./model";
      export default {
        name: "tabBar",
        data() {
          return {
            menuList: tableBarModel.MenuList
          };
        }
      };
      </script>
      
      <style lang='less' scoped>
      @import "../../style/init.less";
      #tab {
        display: flex;
        
        box-shadow: -1px 0 8px #999;
        z-index: 100;
        justify-content: space-around;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        .h(130);
        .bcolor();
        .li {
          .h(130);
          box-sizing: border-box;
          padding-top: unit(10 / @pxtorem, rem);
           25%;
          text-align: center;
          .fontColorOff();
        }
        .li::before {
          .f_s(58);
        }
        .li {
          .f_s(26);
        }
        .change {
          .fontColorOn();
        }
      }
      </style>

    title(标题)

    • title用h2简单做了个样式修改
      <template>
        <div>
          <h2>{{title}}</h2>
        </div>
      </template>
      
      <script>
      export default {
        props: ["title"]
      };
      </script>
      
      <style lang="less" scoped>
      @import "../../style/init.less";
      h2 {
        .h2Font();
      }
      </style>

    shopItem(商品列表) 

    • 新建model.js存放可读写商品列表,vue组件实例和默认分页配置
      export default class ItemModel {//存放可读写商品列表,vue组件实例和默认分页配置
        constructor() {
          this._shopList = []//商品列表
          this._pageConfig = {}//默认分页配置
        }
        static getInstance() { //单例写法
          if (!ItemModel._instance) {
            Object.defineProperty(ItemModel, "_instance", {
              value: new ItemModel()
            })
          }
          return ItemModel._instance;
        }
        set vueComponent(val) {
          this._vueComponent = val
        }
        get vueComponent() {
          return this._vueComponent
        }
        set pageConfig(val) {
          this._pageConfig = val
          this._pageConfig.picType = 0//默认商品类型:单个商品
        }
        get pageConfig() {
          return this._pageConfig
        }
        set shopList(val) {
          this._shopList = val
          this._vueComponent.list = this._shopList//获取到商品列表后重新渲染
        }
        get shopList() {
          return this._shopList
        }
      }
      
    • 新建做业务处理的bussiness.js
      import Vue from 'vue';
      import config from "../../config/config";
      import ItemModel from "./model";
      import Clone from "../../utils/clone";
      const {
        DefaultPageConfig,
        ServerApi
      } = config
      export default class ItemBussiness extends Vue {
        constructor(_vueComponent) {
          super()
          ItemModel.getInstance().vueComponent = _vueComponent//Vue组件实例
          this.initPageConfig(_vueComponent.shopType)
          this.getShopItem()
        }
        initPageConfig(_shopType) {//获取默认分页配置
          ItemModel.getInstance().pageConfig = Clone.shallowClone(DefaultPageConfig)
          ItemModel.getInstance().pageConfig.shopType = _shopType
        }
        getShopItem() {//获取商品列表
          this.$axios
            .get(ServerApi.shop.shopList, {
              params: {
                crypto: this.$crypto.setCrypto(ItemModel.getInstance().pageConfig)
              },
            }).then(res => {
              switch (res.result) {
                case 1:
                  ItemModel.getInstance().shopList = res.data.list//渲染页面
                  break;
                default:
                  break;
              }
            })
        }
      }
      
    • 在shopItem.vue中进行列表渲染,并添加点击事件,跳转至商品详情页
      <template>
        <ul class="more">
          <li v-for="(item,index) in list" :key="index" @click="clickHandler(item)">
            <img :src="imgPath+item.shopPic" alt :class="'imgs'+index" />
            <span>{{item.shopName}} {{item.shopScale}}克</span>
            <div>¥{{item.shopPrice}}</div>
          </li>
        </ul>
      </template>
      <script>
      import ShopBussiness from "./bussiness";
      import Config from "../../config/config";
      export default {
        name: "shopItem",
        props: ["shopType"],
        data() {
          return {
            list: [],
            imgPath: Config.RequestPath
          };
        },
        mounted() {
          new ShopBussiness(this);
        },
        methods: {
          clickHandler(data) {
            this.$router.push({ name: "ShopInfo", query: { ...data } });
          }
        }
      };
      </script>
      
      <style lang="less" scoped>
      @import "../../style/init.less";
      .more {
        li {
          .shopItem();
        }
      }
      </style>

    最后的商品主题组件和商品列表相似,添加点击事件跳转至主题详情页

    home页面

    在page文件夹下新建home文件夹以及home.vue文件,将以上组件在home中引入并构成页面,效果如下

    home.vue

    <template>
      <div>
        <Top title="零食商贩"></Top>
        <div class="content">
          <Banner></Banner>
          <H2 title="精选主题"></H2>
          <Theme></Theme>
          <H2 title="最近新品"></H2>
          <ShopItem :shopType="shopType"></ShopItem>
        </div>
        <TabBar></TabBar>
      </div>
    </template>
    
    <script>
    import TabBar from "../../components/tabBar/tabBar";
    import Top from "../../components/top/top";
    import Banner from "../../components/banner/banner";
    import Theme from "../../components/theme/theme";
    import ShopItem from "../../components/shopItem/shopItem";
    import H2 from "../../components/h2/h2";
    export default {
      name: "Home",
      data() {
        return {
          shopType: ""
        };
      },
      components: {
        Top,
        H2,
        Banner,
        Theme,
        ShopItem,
        TabBar
      }
    };
    </script>
    
    <style lang="less" scoped>
    @import "../../style/init.less";
    </style>

    以上就是主页功能实现及部分公共组件的实现,下篇文章将对商品分类列表,商品主题界面及功能进行介绍

  • 相关阅读:
    基于RTP的h.264视频传输系统设计(一)
    NAS配置Time Machine,在D-Link DNS-320上的配置笔记
    重构版机房收费系统之分层、接口、数据库连接、反射+工厂(vb.net)
    复制表机构
    JVM内存
    System.gc()
    重写(Override) 重载(Overload)
    final 关键字
    JAVA stack
    java 获取环境变量
  • 原文地址:https://www.cnblogs.com/HelloWorld-Yu/p/13806821.html
Copyright © 2011-2022 走看看