From scratch, build a simple shopping platform (14) Front-end mall part

From scratch, build a simple shopping platform (13) Front-end mall part:
https://blog.csdn.net/time_____/article/details/108514710
Project source code (continuous update): https://gitee.com/ DieHunter/myCode/tree/master/shopping

This article introduces the implementation of some components and the home page. The home page components are as follows. The data on the home page is loaded asynchronously in batches, that is, the data of each component is requested separately to reduce data request congestion. The implementation process is introduced below.

pageTitle (page title)

  • First of all, consider the return function of the title, and write a route return function in the methods
     methods: {
        goBack() {
          this.$router.go(-1);
        }
      }

     

  • Then pass the parameters through the component properties (title content, whether there is a return button), and put the component properties in the current data through props

    props: ["title", "isBack"],

     

  • The label determines whether there is a back button based on isBack and displays the title value

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

     

banner (homepage carousel)

  • The picture in the carousel diagram component is requested separately, so the model management data is used, the bussiness is requested, and the subsequent components have data request interactions that are written in this way
  • Model.js content, save the banner list, vue instance, page configuration information
    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 does request and logic processing
    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 page display
    <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);
      width: 100%;
    }
    .swiper {
      width: 100%;
      .h(500);
    }
    </style>

 tableBar (navigation bar)

  • Download the corresponding icon font resource in iconfont. I download it directly in the style directory and display it as a class name. Create a new model.js in the tabbar folder to fetch data (in fact, this can be placed in 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, through the list
    <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);
        width: 25%;
        text-align: center;
        .fontColorOff();
      }
      .li::before {
        .f_s(58);
      }
      .li {
        .f_s(26);
      }
      .change {
        .fontColorOn();
      }
    }
    </style>

title

  • Title made a simple style modification with 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 (product list) 

  • Create new model.js to store the list of readable and writable products, vue component instances and default paging configuration
    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
      }
    }
    
  • Create a new bussiness.js for business processing
    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;
            }
          })
      }
    }
    
  • Render the list in shopItem.vue and add a click event to jump to the product details page
    <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>

The final product theme component is similar to the product list, add a click event to jump to the theme details page

home page

Create a new home folder and home.vue file under the page folder, and introduce the above components into home to form a page. The effect is as follows

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>

The above is the realization of the homepage function and the realization of some public components. The next article will introduce the product classification list, product theme interface and functions

Guess you like

Origin blog.csdn.net/time_____/article/details/108545330