Taro跨端开发探索10——商城小程序首页实现

560 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

前言

在前面9天的文章中,我们已经完成了基本的架构搭建和常用的方法封装,还有熟悉了一下父子组件中传值的方法。今天,我们基于京喜小程序分析一下首页需要实现的功能

需求分析

我们先看一下京喜小程序的首页是什么样子的 1650086826(1).png

如上所示,我们可以看到它有以下几个功能
1: 搜索:用户在选中输入框的时候会跳转到搜索页面,搜索之后会到搜索结果页面
2: 分类筛选
3: 活动和引流区域(对应我框出来的1区域)
4: 新人活动(对应我框出来的2区域)
5: 常驻活动(对应我框出来的3区域)
6: 推荐商品(对应我框出来的4区域)
我们取它的 1、5、6模块进行开发,其他的模块大家可以按照我的思路自己试一下开发

功能实现

初始化目录

我们将常驻活动和推荐商品作为独立的子模块在home下新建对应的文件夹并初始化index.tsx和index.scss文件。将搜索商品(在首页和分类搜索都有搜索商品)作为公用的组件,在src下新建component文件夹作为公用的组件库

先实现常驻活动和推荐商品开发

我们在进入首页的时候,会等待常驻活动和推荐商品的后端接口,这里有两种等待策略

  1. 等待所有接口请求完成之后一起渲染数据
  2. 所有子组件块的接口分块加载,没有请求完成的时候显示loading,请求完成之后加载数据
    我们使用第二种策略。原因为:后端接口存在不确定性,例如某个接口出现问题或者执行的逻辑花费时间过长时,严重影响客户体验
    我们的home\index.ts代码如下
import { View } from "@tarojs/components";
import "./index.scss";
import RecommendedGoods from "./recommended-goods";
import ResidentActivities from "./resident-activities";
export default function Home() {
  return (
    <View className="home">
      <ResidentActivities />
      <RecommendedGoods />
    </View>
  );
}

推荐商品的业务代码如下

import { View, Text } from "@tarojs/components";
import { useEffect, useState } from "react";
import { AtImagePicker } from "taro-ui";
import "./index.scss";
export default function RecommendedGoods() {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([] as any);
  useEffect(() => {
    const timer = setTimeout(() => {
      clearTimeout(timer);
      setLoading(false);
      setData([
        { id: 111, photo: "", price: 300 },
        { id: 222, photo: "", price: 200 },
        { id: 333, photo: "", price: 300 },
        { id: 444, photo: "", price: 200 },
        { id: 555, photo: "", price: 300 },
      ]);
    }, 2000);
  }, []);

  return (
    <View className="recommended-goods">
      {loading ? (
        <Text>加载中</Text>
      ) : (
        <View>
          <View>
            {data.map((item) => (
              <View>
                <AtImagePicker
                  files={[
                    {
                      url: "https://storage.360buyimg.com/mtd/home/111543234387022.jpg",
                    },
                  ]}
                  showAddBtn={false}
                  onImageClick={() => {
                    console.log(item["id"]);
                  }}
                  count={1}
                  onChange={() => {}}
                  sizeType={["original", "compressed"]}
                />
                <Text>{(item["price"] / 100).toFixed(2)}</Text>
              </View>
            ))}
          </View>
        </View>
      )}
    </View>
  );
}

常驻活动的业务代码如下

import { View, Text } from "@tarojs/components";
import { useEffect, useState } from "react";
import "./index.scss";
export default function ResidentActivities() {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([] as any);
  useEffect(() => {
    const timer = setTimeout(() => {
      clearTimeout(timer);
      setLoading(false);
      setData([
        {
          title: "秒杀活动",
          goodsData: [
            { id: "111", photo: "", price: 100 },
            { id: "222", photo: "", price: 200 },
          ],
        },
        {
          title: "官方补贴",
          goodsData: [
            { id: "333", photo: "", price: 300 },
            { id: "444", photo: "", price: 400 },
          ],
        },
      ]);
    }, 2000);
  }, []);

  return (
    <View className="resident-activities">
      {loading ? (
        <Text>加载中</Text>
      ) : data.length >= 2 ? (
        <View>
          <View>
            <Text>{data[0].title}</Text>
            {data[0].goodsData.map((item) => (
              <View
                className="goods-item"
                onClick={() => {
                  console.log(item.id);
                }}
              >
                <Text>{(item.price / 100).toFixed(2)}</Text>
              </View>
            ))}
          </View>
          <View>
            <Text>{data[1].title}</Text>
            {data[1].goodsData.map((item) => (
              <View
                onClick={() => {
                  console.log(item.id);
                }}
              >
                <Text>{(item.price / 100).toFixed(2)}</Text>
              </View>
            ))}
          </View>
        </View>
      ) : data.length === 1 ? (
        <View>
          <View>
            <Text>{data[0].title}</Text>
            {data[0].goodsData.map((item) => (
              <View
                onClick={() => {
                  console.log(item.id);
                }}
              >
                <Text>{(item.price / 100).toFixed(2)}</Text>
              </View>
            ))}
          </View>
        </View>
      ) : (
        ""
      )}
    </View>
  );
}

我们可以看到在我们使用父子组件之后,所有的子组件的加载动作可以自己控制,我们可以自己设置一下定时器的时间,体验一下不同子组件的延迟加载

结语

今天的开发进度不是很快,主要是一开始采用了父组件传值给子组件进行渲染,导致浪费了一些时间,还有taro ui的一些组件不太好集成。下篇文章我们探索一下下拉刷新的业务场景。
本系列文章对应git地址为:gitee.com/liangminghu… 欢迎各位css大佬提交样式pr。也欢迎大家多多点赞关注!