基于vant实现极客时间移动web商城

738 阅读3分钟

之前一直做得是pc端项目,使用的比较多的是element-ui,一直没怎么接触过移动端项目。趁着这段时间比较空闲,就了解了下vant,仿照极客时间的移动web商城。闹了个尴尬,极客时间商城就是用vant做的,难怪用着真香。 商城截图:

商城链接: shop18793264.m.youzan.com/v2/showcase…

首先做项目我们得先做分析,先看上面的三张截图(也可以点击上面链接访问实际页面)。我们看到页面都是分区域的。从顶部往下分别是广告、礼品卡搜索、轮播、三张推荐小图、数据列表(两种布局)、底部copyright、固定底部的tabbar。为了方便修改,七个区块我们可以分为七个组件,这样便于后续页面内容的添加或删除。 我们使用vue-cli3.0生成基础目录结构,在view目录下新建一个home文件夹存放首页的内容,index.vue组件来承载上面说的七个区块,容器组件作为页面的顶层组件,可以用来处理一些数据请求并传递给区块组件,文件划分如下:

我们这里主要讲下数据列表的实现。观察数据列表,可以看到每个分类的数据列表都有一个区域标题和英文翻译,列表分为两列的与三列的,两列和三列的右下角图标又不相同。整个数据区域我们可以作为一个Panel组件,区域的标题通过props传入该组件。而列表是放在Panel里面的,所以这里一定要有一个slot。代码如下:

<template>
  <div class="panel" v-if="Object.keys(data).length">
    <div class="panel-title">
      <div class="title">{{ data.title }}</div>
      <div class="sub-title">-{{ data.subTitle }}-</div>
    </div>
    <div class="content">
      <!-- 插槽用来放主要内容 -->
      <slot></slot>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    data: {
      type: Object,
      default() {
        return {};
      }
    }
  }
};
</script>

我们通过data传递title、subTitle,你也可以将他们拆开。 容器有了,我们来实现列表。实际上,列表可以分为两个组件,决定list布局方式的为一个组件,list每一个数据项是一个组件,这样拆开我们就可以随意更换每个数据项的内容。我们先来看list怎么决定布局的列数。我们知道vant有自带的栅格系统,我们基于栅格组件来处理列数的问题,如下:

<template>
  <van-row>
    <van-col v-for="(item, index) in data" :key="index" :span="spanNum">
      <item :data="item" :height="height" />
    </van-col>
  </van-row>
</template>

span属性值决定了列元素的宽度,宽度的多少实际上就决定了一行可以显示多少列。我们根据传入的col参数计算van-col的span值:

<script>
export default {
  props: {
    col: {
      type: Number,
      default: 1
    }
  },
  computed: {
    spanNum() {
      return Math.floor(24 / this.col);
    }
  }
};
</script>

然后循环传入的数据列表,并将每一个数据项的值传入到item组件里,由item组件自己做数据的渲染,item组件如下:

<template>
  <div class="item">
    <van-image :src="data.img" fit="scale-down" :height="height + ''" />
    <h3 class="title">{{ data.title }}</h3>
    <p class="price-info">
      <span class="price-tag">¥</span>{{ data.price }}
      <van-icon class="cart" :name="data.icon" />
    </p>
  </div>
</template>
<script>
export default {
  props: {
    data: {
      type: Object,
      default() {
        return {};
      }
    },
    height: {
      type: Number
    }
  }
};
</script>

这就是我实现数据列表区域的思路,组件关系图如下:

使用方式如下:

<template>
  <panel :data="data.category">
    <list
      :col="data.category.col"
      :data="data.list"
      :height="data.category.height"
    />
  </panel>
</template>
<script>
import panel from "@/components/Panel";
import list from "@/components/List";
export default {
  components: {
    panel,
    list
  },
  props: {
    data: {
      type: Object,
      default() {
        return {};
      }
    }
  }
};
</script>

以上就是我的简要分析,多有不足,希望大家多提意见。 详细代码:https://gitee.com/linbingrong/vant-geektime.git