从零开始,搭建一个简单的购物平台十四前端商城部分

从零开始,搭建一个简单的购物平台(十三)前端商城部分:
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);
      width: 100%;
    }
    .swiper {
      width: 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);
        width: 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,{
            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"],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>

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

原文地址:https://blog.csdn.net/time_____

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于nodejs...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs怎么实现目录不存在自动创建”文章能帮助大...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs如何实现定时删除文件”文章能帮助大家解决疑惑...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文...
本篇内容主要讲解“怎么安装Node.js的旧版本”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎...
这篇“node中的Express框架怎么安装使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要介绍“nodejs如何实现搜索引擎”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs如何实现搜索引擎...
这篇文章主要介绍“nodejs中间层如何设置”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs中间层如何设置”文...
这篇文章主要介绍“nodejs多线程怎么实现”,在日常操作中,相信很多人在nodejs多线程怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
这篇文章主要讲解了“nodejs怎么分布式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs怎么分布式”...
本篇内容介绍了“nodejs字符串怎么转换为数组”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
这篇文章主要介绍了nodejs如何运行在php服务器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇nodejs如何运行在php服务器文章都...
本篇内容主要讲解“nodejs单线程如何处理事件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“nodejs单线程如何...
这篇文章主要介绍“nodejs怎么安装ws模块”,在日常操作中,相信很多人在nodejs怎么安装ws模块问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
本篇内容介绍了“怎么打包nodejs代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!
本文小编为大家详细介绍“nodejs接收到的汉字乱码怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs接收到的汉字乱码怎么解决”文章能帮助大家解...
这篇“nodejs怎么同步删除文件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇...
今天小编给大家分享一下nodejs怎么设置淘宝镜像的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希