2021-05-17

news/2024/7/10 1:46:44 标签: vue

购物车项目
实现语言:css、html、javascript
实现框架:vue3
使用插件:vue-cil4、vue-router、vue-axios
相关组件:swiper、better-scroll
实现功能:
1.商品内容分块展示
2.商品详细信息展示
3.商品点击添加购物车
4.页面轮播图
5.页面滚动效果
6.页面吸顶效果
7.页面返回顶部功能
8.上拉加载功能
9.点击跳转功能

vue.config.js

module.exports = {
    configureWebpack: {
        resolve: {
            alias: {
                'assets': '@/assets',
                'common': '@/common',
                'components': '@/components',
                'network': '@/network',
                'views': '@/views',
            }
        }
    }
}

相关素材样式:
在这里插入图片描述
main.js:
创建组件,挂载组件(only创建项目)

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false
Vue.prototype.$bus = new Vue()

new Vue({
    render: h => h(App),
    router,
    store
}).$mount('#app')

App.vue:组件管理,通过MainTabBar搭建项目框架
keep-alive:自带插件,保持状态
router-view:
router-link:

<template>
  <div id="app" class="wrapper">
    <keep-alive exclude="Detail"><router-view/></keep-alive>
  
    <main-tab-bar/>
  </div>
</template>

<script>
  import MainTabBar from 'components/content/mainTabbar/MainTabBar'

  export default {
    name: 'app',
    components: {
      MainTabBar
    }
  }
</script>

<style>
  @import "assets/css/base.css";
</style>

MainTabBar.vue:搭建项目框架,添加跳转路径

<template>
  <tab-bar>
    <tab-bar-item path="/home">
      <img slot="item-icon" src="~assets/img/tabbar/home.svg" alt="">
      <img slot="item-icon-active" src="~assets/img/tabbar/home_active.svg" alt="">
      <div slot="item-text">首页</div>
    </tab-bar-item>
    <tab-bar-item path="/category">
      <img slot="item-icon" src="~assets/img/tabbar/category.svg" alt="">
      <img slot="item-icon-active" src="~assets/img/tabbar/category_active.svg" alt="">
      <div slot="item-text">分类</div>
    </tab-bar-item>
    <tab-bar-item path="/cart">
      <img slot="item-icon" src="~assets/img/tabbar/shopcart.svg" alt="">
      <img slot="item-icon-active" src="~assets/img/tabbar/shopcart_active.svg" alt="">
      <div slot="item-text">购物车</div>
    </tab-bar-item>
    <tab-bar-item path="/profile">
      <img slot="item-icon" src="~assets/img/tabbar/profile.svg" alt="">
      <img slot="item-icon-active" src="~assets/img/tabbar/profile_active.svg" alt="">
      <div slot="item-text">我的</div>
    </tab-bar-item>
  </tab-bar>
</template>

<script>
  import TabBar from 'components/common/tabbar/TabBar'
  import TabBarItem from 'components/common/tabbar/TabBarItem'

  export default {
    name: "MainTabBar",
    components: {
      TabBar,
      TabBarItem
    }
  }
</script>

router/index.js
配置路由:
1.路由懒加载:异步加载,用到时候再显示
2.路由传参:动态传参、query传参
3.路由模式:history

import Vue from 'vue'
import VueRouter from 'vue-router'

const Home = () =>
    import ('../views/home/Home')
const Category = () =>
    import ('../views/category/Category')
const Cart = () =>
    import ('../views/cart/Cart')
const Profile = () =>
    import ('../views/profile/Profile')
const Detail = () =>
    import ('../views/detail/Detail')
    // 1.安装插件
Vue.use(VueRouter)

// 2.创建router
const routes = [{
        path: '',
        redirect: '/home'
    },
    {
        path: '/home',
        component: Home
    },
    {
        path: '/category',
        component: Category
    },
    {
        path: '/cart',
        component: Cart
    },
    {
        path: '/profile',
        component: Profile
    },
    {
        path: '/detail/:iid',
        component: Detail
    }
]
const router = new VueRouter({
    routes,
    mode: 'history'
})


export default router

home.vue:首页home组件,管理首页内容
首页内容:
在这里插入图片描述
1.nav导航栏
2.swiper轮播图
3.recommend
4.feature本周流行
5.tabcontrol商品类别
6.商品展示
7.maintabbar

<template>
  <div id="home" class="wrapper">
    <nav-bar class="home-nav"><div slot="center">购物街</div></nav-bar>
    <tab-control :titles="['流行', '新款', '精选']"
                   @tabClick="tabClick"
                   ref="tabcontrol1"
                   class="tab-control" v-show="isFixed"/>
    <scroll class="content"
            ref="scroll"
            :probe-type="3"
            @scroll="contentScroll"
            :pull-up-load="true"
            @pullingUp="loadMore">
      <home-swiper :banners="banners" @swiperImageLoad="swiperImageLoad" ref="hswiper"/>
      <recommend-view :recommends="recommends"/>
      <feature-view/>
      <tab-control :titles="['流行', '新款', '精选']"
                   @tabClick="tabClick"
                   ref="tabcontrol2"/>
      <good-list :goods="showGoods"/>
    </scroll>
    <div>呵呵呵呵</div>
    <back-top @click.native="backClick" v-show="isShowBackTop"/>
  </div>
</template>

<script>
  import HomeSwiper from './childComps/HomeSwiper'
  import RecommendView from './childComps/RecommendView'
  import FeatureView from './childComps/FeatureView'

  import NavBar from 'components/common/navbar/NavBar'
  import TabControl from 'components/content/tabControl/TabControl'
  import GoodList from 'components/content/goods/GoodsList'
  import Scroll from 'components/common/scroll/Scroll'
  import BackTop from 'components/content/backTop/BackTop'


  import { getHomeMultidata, getHomeGoods } from "network/home"

  import {itemListenerMixin} from 'common/mixin'

  export default {
    name: "Home",
    components: {
      HomeSwiper,
      RecommendView,
      FeatureView,
      NavBar,
      TabControl,
      GoodList,
      Scroll,
      BackTop
    },
    mixins:[itemListenerMixin],
    data() {
      return {
        banners: [],
        recommends: [],
        goods: {
          'pop': {page: 0, list: []},
          'new': {page: 0, list: []},
          'sell': {page: 0, list: []},
        },
        currentType: 'pop',
        isShowBackTop: false,
        offsetTop: 0,
        isFixed: false,
      }
    },
    computed: {
      showGoods() {
        return this.goods[this.currentType].list
      }
    },
    created() {
      // 1.请求多个数据
      this.getHomeMultidata()

      // 2.请求商品数据
      this.getHomeGoods('pop')
      this.getHomeGoods('new')
      this.getHomeGoods('sell')
    },
    mounted() {
      
    },
    methods: {
      /**
       * 事件监听相关的方法
       */
      tabClick(index) {
        switch (index) {
          case 0:
            this.currentType = 'pop'
            break
          case 1:
            this.currentType = 'new'
            break
          case 2:
            this.currentType = 'sell'
            break
        }
        //两个tabcontrol
        this.$refs.tabcontrol1.currentIndex = index;
        this.$refs.tabcontrol2.currentIndex = index;
      },
      backClick() {
        this.$refs.scroll.scrollTo(0, 0)
      },
      contentScroll(position) {
                
        // console.log(this.$refs.tabcontrol.$el.offsetTop);
        this.isShowBackTop = (-position.y) > 1000
        this.isFixed = (-position.y) > this.offsetTop
// console.log(this.isFixed);
      },
      loadMore() {
        this.getHomeGoods(this.currentType)
      },
      /**
       * 网络请求相关的方法
       */
      swiperImageLoad(){
        // 获取组件里元素的offsetTop
        this.offsetTop=this.$refs.tabcontrol2.$el.offsetTop
      },
      getHomeMultidata() {
        getHomeMultidata().then(res => {
          // this.result = res;
          this.banners = res.data.banner.list;
          this.recommends = res.data.recommend.list;
          console.log(res);
        })
      },
      getHomeGoods(type) {
        const page = this.goods[type].page + 1
        getHomeGoods(type, page).then(res => {
          this.goods[type].list.push(...res.data.list)
          this.goods[type].page += 1
          this.$refs.scroll.finishPullUp()
          // this.$refs.scroll.refresh()
          console.log(res);
        })
        
      }
    }
  }
</script>

NavBar.vue:
1.插槽slot可以对应填充内容

<template>
  <div class="nav-bar">
      <div class="left"><slot name="left"></slot></div>
      <div class="center"><slot name="center"></slot></div>
      <div class="right"><slot name="right"></slot></div>
  </div>
</template>
<script>

export default {
  name: 'NavBar',
}
</script>

Recommend.vue:
1.父组件请求数据,然后传给子组件显示
2.子组件根据数据生成相应内容

<template>
  <div class="recommend">
    <div v-for="item in recommends" class="recommend-item">
      <a :href="item.link">
        <img :src="item.image" alt="">
        <div>{{item.title}}</div>
      </a>
    </div>
  </div>
</template>

<script>
  export default {
    name: "RecommendView",
    props: {
      recommends: {
        type: Array,
        default() {
          return []
        }
      }
    }
  }
</script>

Feature.vue:
仅仅是一张图片套了一个a标签

<template>
  <div class="feature">
    <a href="https://act.mogujie.com/zzlx67">
      <img src="~assets/img/home/recommend_bg.jpg" alt="">
    </a>
  </div>
</template>

<script>
  export default {
    name: "FeatureView"
  }
</script>

TabControl.vue:
1.实现局部的商品刷新
2.点击对应类别传递不同商品参数
3.

<template>
  <div class="tab-control">
    <div v-for="(item, index) in titles"
         class="tab-control-item"
         :class="{active: index === currentIndex}"
         @click="itemClick(index)">
      <span>{{item}}</span>
    </div>
  </div>
</template>

<script>
  export default {
    name: "TabControl",
    props: {
      titles: {
        type: Array,
        default() {
          return []
        }
      }
    },
    data() {
      return {
        currentIndex: 0
      }
    },
    methods: {
      itemClick(index) {
        this.currentIndex = index;
        this.$emit('tabClick', index)
      }
    }
  }
</script>

request.js:
1.使用axios插件请求数据

import axios from 'axios'

export function request(config) {
    // 1.创建axios的实例
    const instance = axios.create({
        baseURL: 'http://152.136.185.210:7878/api/m5',
        timeout: 5000
    })

    // 2.axios的拦截器
    // 2.1.请求拦截的作用
    instance.interceptors.request.use(config => {
        return config
    }, err => {
        // console.log(err);
    })

    // 2.2.响应拦截
    instance.interceptors.response.use(res => {
        return res.data
    }, err => {
        console.log(err);
    })

    // 3.发送真正的网络请求
    return instance(config)
}

home.js:
1.home首页的数据请求

import { request } from "./request";

export function getHomeMultidata() {
    return request({
        url: '/home/multidata'
    })
}

export function getHomeGoods(type, page) {
    return request({
        url: '/home/data',
        params: {
            type,
            page
        }
    })
}

利用封装好的swiper、better-scroll、back-top渲染页面功能


http://www.niftyadmin.cn/n/724480.html

相关文章

freemarker内置函数,数字,字符串,日期格式化

一、 Sequence的内置函数1. sequence?first 返回sequence的第一个值。 2. sequence?last 返回sequence的最后一个值。 3. sequence?reverse 将sequence的现有顺序反转&#xff0c;即倒序排序 4. sequence?size 返回sequence的大小 5. sequence?sort 将sequen…

手写new方法

new的过程&#xff1a; 1.创建一个对象 let obj {} 2.将构造函数的作用域赋给新对象 _class.call(obj) 3.执行构造函数的代码&#xff0c;返回新对象 function newMethod(_class,...rest) {// 1.以构造器的prototype为原型创建新对象let object Object.create(proto, propert…

扩展或插件 (Extension or Plugin )

Manual:Component:扩展或插件 zh-CN From Learn About the Ext JavaScript Library Jump to: navigation, searchSummary: 辨析Ext Extensions&#xff08;扩展&#xff09;与Plugins&#xff08;插件&#xff09;之间的关系。 Author: Jozef Sakalos, aka Saki &#xff08;译…

VS2010 solution中完美的相对路径引用方法

假设您有一个工程叫solar&#xff0c;路径结构是这样的&#xff1a;公用头路径: d:\solar\public\include公用库路径&#xff1a;d:\solar\public\libmars项目 : d:\solar\marsuranus项目: d:\solar\uranus工具路径 : d:\solar\tools现在mars这个项目中要引用公用头路径和公用…

RegExp

匹配模式&#xff1a; g-全局、i-不区分大小写、m-多行匹配 字面量&#xff1a; var pattern1 /[bc]at/i; var pattern2 new RegExp("[bc]at", "i");RegExp属性&#xff1a; global&#xff1a;布尔值&#xff0c;是否设置了g标志 ignoreCase&#xff1…

子窗体,主窗体,互相传值,组策略,子窗体文本选择,select,length,反射系列

在昨天的教程窗体传值,子窗体,父窗体,反射,reflection,windows,组策略,gpedit.msc,动态创建窗体,谢谢中我写到了&#xff0c;传值遇到的问题&#xff0c;主要是因为子窗体是反射出来的&#xff0c;所以子窗体的属性也应该反射才可以得到&#xff0c;可以看我的上面的教程&#…

MySQL命令行数据操作使用心得(总结版)

Char 0~255 Varchar 0~65535 text 0~65535&#xff08;只能保存字符&#xff09; Longtext 0~4294967295&#xff08;只能保存字符&#xff09; CMD登陆mysql mysql -u root -p mysql -P 3306 -uroot -p123456 (-P必须大写表示端口) 1&#xff0c;数据库操作databases 创建数据…

手写new、apply、call、bind

// 手写实现new方法// function _new(ctor, ...args) { // let obj new Object(); // // // obj.__ptoto__ Object.create(ctor.prototype); // // 执行构造函数 // ctor.apply(obj, [...args]); // return obj // } // //手写实现apply方法 // Func…