index.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { use, isDef } from '../utils';
  2. import { inherit } from '../utils/functional';
  3. import Tag from '../tag';
  4. // Types
  5. import { CreateElement, RenderContext } from 'vue/types';
  6. import { DefaultSlots, ScopedSlot } from '../utils/use/sfc';
  7. export type CardProps = {
  8. tag?: string;
  9. num?: number | string;
  10. desc?: string;
  11. thumb?: string;
  12. title?: string;
  13. price?: number | string;
  14. currency: string;
  15. centered?: boolean;
  16. lazyLoad?: boolean;
  17. thumbLink?: string;
  18. originPrice?: number | string;
  19. };
  20. export type CardSlots = DefaultSlots & {
  21. num?: ScopedSlot;
  22. tag?: ScopedSlot;
  23. tags?: ScopedSlot;
  24. desc?: ScopedSlot;
  25. title?: ScopedSlot;
  26. thumb?: ScopedSlot;
  27. price?: ScopedSlot;
  28. footer?: ScopedSlot;
  29. 'origin-price'?: ScopedSlot;
  30. };
  31. export type CardEvents = {
  32. onClick?(event: Event): void;
  33. };
  34. const [sfc, bem] = use('card');
  35. function Card(
  36. h: CreateElement,
  37. props: CardProps,
  38. slots: CardSlots,
  39. ctx: RenderContext<CardProps>
  40. ) {
  41. const { thumb } = props;
  42. const showThumb = slots.thumb || thumb;
  43. const showTag = slots.tag || props.tag;
  44. const showNum = slots.num || isDef(props.num);
  45. const showPrice = slots.price || isDef(props.price);
  46. const showOriginPrice = slots['origin-price'] || isDef(props.originPrice);
  47. const showBottom = showNum || showPrice || showOriginPrice;
  48. const Thumb = showThumb && (
  49. <a href={props.thumbLink} class={bem('thumb')}>
  50. {slots.thumb ? (
  51. slots.thumb()
  52. ) : props.lazyLoad ? (
  53. <img class={bem('img')} vLazy={thumb} />
  54. ) : (
  55. <img class={bem('img')} src={thumb} />
  56. )}
  57. {showTag && (
  58. <div class={bem('tag')}>
  59. {slots.tag ? (
  60. slots.tag()
  61. ) : (
  62. <Tag mark type="danger">
  63. {props.tag}
  64. </Tag>
  65. )}
  66. </div>
  67. )}
  68. </a>
  69. );
  70. const Title = slots.title
  71. ? slots.title()
  72. : props.title && <div class={bem('title')}>{props.title}</div>;
  73. const Desc = slots.desc
  74. ? slots.desc()
  75. : props.desc && <div class={[bem('desc'), 'van-ellipsis']}>{props.desc}</div>;
  76. const Price = showPrice && (
  77. <div class={bem('price')}>
  78. {slots.price ? slots.price() : `${props.currency} ${props.price}`}
  79. </div>
  80. );
  81. const OriginPrice = showOriginPrice && (
  82. <div class={bem('origin-price')}>
  83. {slots['origin-price']
  84. ? slots['origin-price']()
  85. : `${props.currency} ${props.originPrice}`}
  86. </div>
  87. );
  88. const Num = showNum && (
  89. <div class={bem('num')}>{slots.num ? slots.num() : `x ${props.num}`}</div>
  90. );
  91. const Footer = slots.footer && <div class={bem('footer')}>{slots.footer()}</div>;
  92. return (
  93. <div class={bem()} {...inherit(ctx, true)}>
  94. <div class={bem('header')}>
  95. {Thumb}
  96. <div class={bem('content', { centered: props.centered })}>
  97. {Title}
  98. {Desc}
  99. {slots.tags && slots.tags()}
  100. {showBottom && (
  101. <div class="van-card__bottom">
  102. {Price}
  103. {OriginPrice}
  104. {Num}
  105. </div>
  106. )}
  107. </div>
  108. </div>
  109. {Footer}
  110. </div>
  111. );
  112. }
  113. Card.props = {
  114. tag: String,
  115. desc: String,
  116. thumb: String,
  117. title: String,
  118. centered: Boolean,
  119. lazyLoad: Boolean,
  120. thumbLink: String,
  121. num: [Number, String],
  122. price: [Number, String],
  123. originPrice: [Number, String],
  124. currency: {
  125. type: String,
  126. default: '¥'
  127. }
  128. };
  129. export default sfc<CardProps, CardEvents>(Card);