使用VUE+Vant组件库实现小米商城app

1 cd到某个文件夹,在命令窗口输入 vue create xiaomi创建vue项目
2 在vscode中打开项目 xaomi,可以看到以下项目结构
  • node_modules 包与依赖存放位置
    public 根模板文件
    src 项目源文件
    .gitigonore 当文件用git方式上传(git忽略文件)
    babel.config.js ES6转es5配置文件
    package.json 项目配置文件
    README.md 项目说明文件
    yarn.lock yarn安装相关锁定文件
  • src文件目录说明
    assets 项目资源目录
    components 项目组件存放地方
    router 路由
    store 项目数据
    views 项目的页面
    App.vue 项目的根组件
    main.js 项目的根js
3 在views文件夹中创建5个组件,分别对应购物车,用户,分类,主页,产品详情页

部分源码如下:

####Cart.vue
<script>
// 在nodemodules中的文件可以直接导入,不用指定路径
import jsonp from 'jsonp'
import bus  from '../bus.js'
import {mapState,mapMutations,mapGetters} from 'vuex'
export default {
    data(){return {
      cart:[],
    }},
   
    created(){
       this.getCart();
      //  this.getWeather();
      //  this.getC();
       bus.$emit("tabevent",false)
    },
    computed:{
      // 循环cart改为循环goods,因为goodsNum统计的是goods中的商品数量
        ...mapState(["goods"]),
      ...mapGetters(["goodsNum"]),
      // 价格是自定义属性,而goods和goodsnum是映射过来的属性
      totalPrice:function(){
        var price = 0;
        this.goods.forEach(item => {
          
          //  price+=item.price;
          // 假数据是没有select属性,也没有num属性。只有name和price属性
          //所以想要显示价格,必须使用真数据,必须在进入购物车之前就调用getCart()方法
          if(item.select){
            //必须是被选择的商品
            price+=item.num*item.price;
          }
        });
        return price;
      }
    },
    beforeRouteLeave(to,from,next){
      // 离开的时候也要提交一个事件
      bus.$emit("tabevent",true);
      // this.$parent.showTab=true;
      next();
    },

    methods: {
      ...mapMutations(["delCart"]),
      getCart(){
        this.$http.get("http://bigr.apnzi.com/cart.py")
        // this.$http.get("/static/mock/cart.json")
        .then(res=>{
        
          //我们需要的数据在响应对象的data中
          // console.log(res.data);
          // console.log(res);
          this.cart = res.data;
        })
      },
    },
}
</script>

Home.vue

<template>
  <div class="home">
    <div class="row header">
        <a href="#/"><img src="../assets/logo.png" alt="" height="22"></a>
        <input type="text" class="col">
        <a href="#/user"><img src="../assets/user.png" alt="" height="26"></a>
    </div>
    <div class="subheader">
     
        <!-- <span v-for="item in tabs" :key="item.page_id">
         {{item.name}} 
        </span> -->
        <van-tabs v-model="active" swipeable background="#f0f0f0">
          <van-tab v-for="item in tabs" :key="item.page_id" :title="item.name">
              {{item.name}}
          </van-tab>
      </van-tabs>
    </div>
    <div class="content full has-subheader">
        <!-- //轮播图 -->
        <!-- <img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/36b5b151fe94bc6f0024231b9797cbfc.jpg?thumb=1&w=720&h=360" width="100%" alt=""> -->
        <van-swipe :autoplay="3000" indicator-color="#f30" :height="200">
          
          <van-swipe-item v-for="(item, index) in gallery" :key="index">
            <img v-lazy="item.img_url" width="100%" />
          </van-swipe-item>
        </van-swipe>
        <!-- //子分类A -->
        <div class="row">
          <div class="col" v-for="item in subCategoryA" :key="item.img_url">
            
              <img :src="item.img_url" alt="" width="100%">
          </div>
        </div>
        <!-- 子分类B -->
        <div class="row">
          <div class="col" v-for="item in subCategoryB" :key="item.img_url">
            
              <img :src="item.img_url" alt="" width="100%">
          </div>
        </div>
        <div class="row" v-if="productA.length">
          <div class="col-50">
            <img :src="productA[0].img_url" width="100%" alt="">
          </div>
          <div class="col-50">
            <div class="clear">
              <img :src="productA[1].img_url" width="100%" alt="">
            </div>
           
            <div>
              <img :src="productA[2].img_url" width="100%" alt="">
            </div>
          </div>

        </div>
    </div>
  </div>
</template>
<script>
export default {
  name:'home',
  data(){
    return{
      tabs:[],//分类信息
      gallery:[],
      subCategoryA:[],
      subCategoryB:[],
      productA:[],
      active:'a',
  }},
  created(){
  
    this.getPage();
  },
  
  methods:{
    getPage(){
    
      this.$http({
        url:'http://bigr.apnzi.com/page.py',
        method:"GET"
      })
      .then(res=>{
        if(res.data.code==0){
          this.tabs=res.data.data.tabs;
          this.gallery=res.data.data.data.sections[0].body.items;
          this.subCategoryA=res.data.data.data.sections[1].body.items;
          this.subCategoryA=res.data.data.data.sections[2].body.items;
          this.productA=res.data.data.data.sections[4].body.items;
          console.log(this.productA);
        }else{
          alert(res.data.result)
        }
      })
    }
  },
  components:{

  }
}
</script>
4配置路由

index.js

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,
    meta:{keep:true}
  },
  {
    path: '/cart',
    name: 'cart',
    component: Cart
  },
  {
    path: '/product/:id',
    name: 'product',
    component: Product
  },
  {
    path: '/user',
    name: 'user',
    component: User
  },
  {
    path: '/category',
    name: 'category',
    //想要缓存哪个组件,就加个keep属性,在app.vue进行判断
    meta:{keep:true},
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/Category.vue')
  }
]
5 根组件App.vue的配置

app.vue

<template>
  <div id="app">
    <div class="content full" :class="{'has-footer':showTab}">
   
      <!-- <keep-alive :include="keepAlive" >
        <router-view/>
      </keep-alive> -->
      <keep-alive>
        <router-view v-if="$route.meta.keep"/>
      </keep-alive>
      <router-view v-if="!$route.meta.keep"/>
    </div>
    <div class="tabs row footer tac" v-if="showTab">
     
       <!-- <router-link to="/" class="col"> {{$store.state.goods}}</router-link> | -->
       <router-link to="/" class="col">首页</router-link> |
      <router-link to="/category" class="col">分类</router-link>
      <router-link to="/cart" class="col">购物车({{goodsNum}})</router-link>
      <router-link to="/user" class="col">我的</router-link>
    </div>
  </div>
</template>

<script>
import bus from "./bus.js";
import {mapState,mapGetters,mapActions} from 'vuex';
// map映射 通过映射 成为computed 里面一个属性
export default {
  // 监听一个事件
  created() {
 
    bus.$on("tabevent",(data)=>{
      console.log("tabevent",data);
       this.showTab = data;
    });
    this.getCart()
  },
  data(){return {
    showTab:true,
  }},
  computed:{
  
    "goods":function(){
      return this.$store.state.goods;
    },

    //map映射可以把store中的属性或者方法变成当前组件的属性或方法
    // ...mapState(["goods"]),
    ...mapGetters(["goodsNum"])
  },
  methods:{
    //action映射必须写在methods中
    ...mapActions(["getCart"])

  }
}
6 进入项目文件启动项目
cd xxxxx/xiaomi
yarn serve

浏览器打开 http://localhost:8080

7成功

在这里插入图片描述
在这里插入图片描述

8总结

该vue项目使用vuex实现组件之间的数据共享和自动更新(购物车金额随着数量自动更新),同时使用vant组件库完成了菜单栏,轮播图等前端的一些布局,同时通过vue的全局路由守卫实现了登录注册的路由权限判断,除此以外还是用了js-cookie来存储cookie,实现了登录保持和注销,数据是组件通过axios发送ajax请求从后台获取(js存在同源策略,所以我在自己的后台访问小米的接口再进行转发,设置allow-origin="*"),由于篇幅有限代码只写了一部分,需要完整项目源码练手的朋友可以留下邮箱

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值