Skip to content

07 - 组件体系

组件库总览

项目有 64 个导出组件,分为旧版组件(10个,标记 /* old */)和新版 sp-* 前缀组件(54个)。

组件导出入口

src/components/index.js 统一导出所有组件:

js
// 旧版组件
export { default as GoodsItem } from './goods-item'         /* old */
export { default as BackToTop } from './back-to-top'         /* old */
export { default as FilterBar } from './filter-bar'          /* old */
export { default as GoodsBuyPanel } from './goods-buy-panel'  /* old */
export { default as FormIdCollector } from './form-id-collector' /* old */
export { default as Loading } from './loading'               /* old */
export { default as TabBar } from './tab-bar'                 /* old */
export { default as AddressChoose } from './address/choose-address' /* old */
export { default as CouponItem } from './coupon-item'         /* old */
export { default as SpCheckbox } from './sp-checkbox'          /* old */

// 新版 sp-* 组件
export { default as SpButton } from './sp-button'
export { default as SpGoodsItem } from './sp-goods-item'
export { default as SpGoodsCell } from './sp-goods-cell'
// ... 共 54 个

sp-* 组件清单

基础组件

组件路径说明
SpButton./sp-button按钮,支持主题色、加载态
SpInput./sp-input输入框
SpSelect./sp-select选择器
SpCheckbox./sp-checkbox复选框
SpCheckboxNew./sp-checkbox新版复选框
SpInputNumber./sp-input-number数字输入框
SpNumberKeyBoard./sp-numberkeyboard数字键盘
SpPicker./sp-picker选择器
SpTimePicker./sp-time-picker时间选择器
SpModal./sp-modal模态弹窗
SpFloatLayout./sp-float-layout浮动布局
SpSearch./sp-search搜索组件
SpSearchBar./search-bar搜索栏
SpSearchInput./sp-search-input搜索输入框
SpSearchOne./sp-search-one单选搜索
SpToast./toastToast 提示
SpLoading./sp-loading加载中
SpDefault./sp-default默认空状态

商品相关组件

组件路径说明
SpGoodsItem./sp-goods-item商品卡片
SpGoodsCell./sp-goods-cell商品列表项
SpGoodsPrice./sp-goods-price商品价格
SpPrice./sp-price价格展示
SpPoint./sp-point积分展示
SpVipLabel./sp-vip-labelVIP 标签
SpSkuSelect./sp-sku-selectSKU 选择器
SpOrderItem./sp-order-item订单商品项
SpTradeItem./sp-trade-item交易商品项
SpRecommend./sp-recommend推荐商品
SpRecommendItem./sp-recommend-item推荐商品项

媒体组件

组件路径说明
SpImg./sp-img图片
SpImage./sp-image图片(增强版)
SpHtml./sp-html富文本(微信使用 mp-html)
SpUpload./sp-upload文件上传
SpPoster./sp-poster海报生成

表单组件

组件路径说明
SpForm./sp-form表单容器
SpFormItem./sp-form-item表单项
SpAddress./sp-address地址选择

营销组件

组件路径说明
SpCoupon./sp-coupon优惠券
SpNewCoupon./sp-new-coupon新版优惠券
SpCouponPackage./sp-coupon-package优惠券包
SpShopCoupon./sp-shop-coupon店铺优惠券
SpShopFullReduction./sp-shop-fullReduction满减
SpScreenAd./sp-screen-ad弹屏广告
SpFloatMenus./sp-float-menus浮动菜单
SpFloatMenuItem./sp-float-menu-item浮动菜单项
SpFloatAd./sp-float-ad浮动广告

导航与布局

组件路径说明
SpPage./sp-page页面容器(提供 Context)
SpNavBar./sp-nav-bar导航栏
SpTabbar./sp-tabbar底部 TabBar
SpTabs./sp-tabs标签页
SpCell./sp-cell列表单元格
SpScrollView./sp-scrollview滚动视图
SpPoweredBy./sp-powered-by版权标识

分类组件

组件路径说明
SpCategorySearch./sp-category-search分类搜索
SpClassifyHorizontal./sp-classify-horizontal横向分类
SpClassifyVertical./sp-classify-vertical纵向分类
SpBrandIndexes./sp-brand-indexes品牌索引

业务组件

组件路径说明
SpCashier./sp-cashier收银台
SpDeliver./sp-deliver配送选择
SpShop./sp-shop店铺信息
SpChat./sp-chat客服聊天
SpPurchaseEnterpriseBar./sp-purchase-enterprise-bar内购企业栏
SpLogin./sp-login登录组件
SpPrivacyModal./sp-privacy-modal隐私协议弹窗
SpNote./sp-note笔记/提示

高阶组件(HOCs)

src/hocs/index.js 导出 6 个 HOC:

js
export { withLogin, withPager, withBackToTop, withPointitem, withLoadMore, withPageWrapper }

withLogin — 登录 HOC

js
import { withLogin, LIFE_CYCLE_TYPES } from '@/hocs'

@withLogin((next) => { /* 登录后回调 */ }, LIFE_CYCLE_TYPES.DID_SHOW)
class MyPage extends Component { ... }
参数说明
nextFn登录成功后回调
lifeCycle触发时机:WILL_MOUNT(0) / DID_MOUNT(1) / DID_SHOW(2)

行为:在指定生命周期调用 Spx.autoLogin() 完成自动登录,支持异步轮询等待(最多 8 × 70ms)。

withPager — 分页 HOC

js
@withPager
class MyList extends Component {
  state = { list: [] }

  async fetch({ page_no, page_size }) {
    const data = await api.getList({ page: page_no, pageSize })
    this.setState({ list: data.list })
    return { total: data.total }  // 必须返回 total
  }
}

注入 this.state.page = { hasNext, isLoading, total, page_no, page_size }this.nextPage() / this.resetPage() 方法。

withLoadMore — 滚动加载 HOC

js
@withLoadMore
class MyList extends Component {
  onLoadMore(index, type, '_', dataLength) {
    // 当 .lastItem 元素进入视口时触发
  }
}

使用微信 IntersectionObserver 监听 .lastItem 元素,进入视口时触发回调。

withPageWrapper — 页面包装器 HOC

js
import { withPageWrapper } from '@/hocs'

const MyPage = withPageWrapper(({ initState }) => {
  // 等待 initState === true 后执行进店规则
  return <View>...</View>
})

核心逻辑:云店进店规则检查(distributor_codeshop_assistantshop_whiteshop_assistant_pro)。

withBackToTop — 回到顶部 HOC

js
@withBackToTop
class MyPage extends Component {
  // 注入 this.state.scrollTop 和 this.state.showBackToTop
  // 滚动超过 300px 显示按钮
}

withPointitem — 积分商品 HOC

js
@withPointitem
class MyPage extends Component {
  // this.isPointitem() 判断是否积分商品
  // this.transformUrl(url, isPointitem) 拼装参数
}

自定义 Hooks

src/hooks/index.js 导出 16 个 Hooks:

js
export {
  useLogin,         // 用户登录
  useQwLogin,       // 企微登录
  usePage,          // 分页
  useDepChange,     // 依赖变更检测
  useAsyncCallback, // 异步 setState + callback
  usePayment,       // 支付
  useNavigation,    // 导航栏
  useDebounce,      // 防抖
  useThrottle,      // 节流
  useDianWuLogin,   // 店务登录
  useModal,         // 弹窗
  useSyncCallback,  // 同步回调
  useLocation,      // 定位
  useThemsColor,    // 主题色
  useEffectAsync,   // 异步 useEffect
  useFirstMount     // 首次挂载检测
}

useLogin

js
const { isLogin, login, logout, setToken, getUserInfo } = useLogin({
  autoLogin: true,        // 无 Token 时自动登录
  loginSuccess: () => {}  // 登录成功回调
})

usePayment

js
const { cashierPayment, payError } = usePayment()

// 支持的支付通道:
// wxpay, adapay/bspay, wxpayh5, wxpayjs, deposit/point, offline_pay
// 实际可用通道由 standard(云店 B2C)或 platform(ECShopX BBC)的后端配置决定

usePage

js
const { page, nextPage, resetPage } = usePage({
  fetch: async (params) => {
    const data = await api.getList(params)
    return { total: data.total }
  },
  auto: true,      // 自动执行
  pageSize: 10
})

useNavigation

js
const { setNavigationBarTitle } = useNavigation()
setNavigationBarTitle('商品详情')

useLocation

js
const { updateAddress, calculateDistance } = useLocation()
await updateAddress()  // 获取定位 + 更新地址
const dist = calculateDistance(lat1, lon1, lat2, lon2)  // Haversine 距离

useEffectAsync

js
useEffectAsync(async () => {
  const data = await api.getData()
  setData(data)
}, [id])

useAsyncCallback

js
const [state, setStateAsync] = useAsyncCallback(initialState)
setStateAsync({ count: 1 }, () => {
  // state 更新后回调
})

useDebounce / useThrottle

js
const debouncedFn = useDebounce(fn, 300)
const throttledFn = useThrottle(fn, 300)

useModal

js
const { showModal, hideModal } = useModal()
showModal({ title: '提示', content: '确认删除?' })

组件使用规范

导入方式

js
// 统一从 components/index 导入
import { SpButton, SpGoodsItem, SpPage } from '@/components'

// 或直接从组件目录导入(按需)
import SpButton from '@/components/sp-button'

SpPage 页面容器

jsx
import { SpPage } from '@/components'

function MyPage() {
  return (
    <SpPage
      navBar={{ title: '页面标题' }}
      footer={<View>底部操作栏</View>}
    >
      <View>页面内容</View>
    </SpPage>
  )
}

SpPage 提供 usePageContext() 获取 scrollTop 等上下文:

js
import { usePageContext } from '@/hooks'

const { scrollTop } = usePageContext()

新增组件步骤

  1. src/components/ 下创建 sp-my-component/ 目录
  2. 创建 index.jsx(组件逻辑)和 index.scss(样式)
  3. 创建 index.config.js(如有平台特定配置)
  4. src/components/index.js 中添加导出
  5. 使用 @/components 或直接路径导入