cl-image.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <template>
  2. <view
  3. class="cl-image"
  4. :style="{
  5. height: size2[0],
  6. width: size2[1],
  7. }"
  8. :class="[classList]"
  9. @tap.stop="onPreview"
  10. >
  11. <slot name="placeholder" v-if="!src">
  12. <view class="cl-image__placeholder">
  13. <text class="cl-icon-image"></text>
  14. </view>
  15. </slot>
  16. <slot name="error" v-else-if="isError">
  17. <view class="cl-image__error"> 加载失败 </view>
  18. </slot>
  19. <image
  20. class="cl-image__target"
  21. :src="src"
  22. :mode="mode"
  23. :lazy-load="lazyLoad"
  24. :webp="webp"
  25. :show-menu-by-longpress="showMenuByLongpress"
  26. @error="handleError"
  27. @load="handleLoad"
  28. ></image>
  29. </view>
  30. </template>
  31. <script>
  32. import { isNumber, isArray, isString, parseRpx } from "../../utils";
  33. /**
  34. * image 图片
  35. * @description 该组件基于官方的 image 组件。参数与官方一致,同时添加新的支持。
  36. * @tutorial https://docs.cool-js.com/uni/components/basic/image.html
  37. * @property {String} src 图片链接
  38. * @property {String} mode 图片裁剪、缩放的模式
  39. * @property {String, Number, Array} size 图片大小
  40. * @property {Boolean} round 是否圆角
  41. * @property {Array} previewList 预览列表
  42. * @event {Function} load 加载成功时触发
  43. * @event {Function} error 加载失败时触发
  44. * @example <cl-image src="https://" />
  45. */
  46. export default {
  47. name: "cl-image",
  48. props: {
  49. // 图片链接
  50. src: String,
  51. // 图片裁剪、缩放的模式
  52. mode: String,
  53. // 图片大小
  54. size: {
  55. type: [String, Number, Array],
  56. default: "100%",
  57. },
  58. // 是否圆角
  59. round: Boolean,
  60. // 预览列表
  61. previewList: Array,
  62. lazyLoad: Boolean,
  63. fadeShow: {
  64. type: Boolean,
  65. default: true,
  66. },
  67. webp: Boolean,
  68. showMenuByLongpress: Boolean,
  69. },
  70. data() {
  71. return {
  72. isError: null,
  73. };
  74. },
  75. computed: {
  76. classList() {
  77. let list = [];
  78. if (this.round) {
  79. list.push("is-round");
  80. }
  81. return list.join(" ");
  82. },
  83. size2() {
  84. let size = ["100%", "100%"];
  85. if (isString(this.size) || isNumber(this.size)) {
  86. size = [this.size, this.size];
  87. } else if (isArray(this.size)) {
  88. size = this.size;
  89. }
  90. return size.map(parseRpx);
  91. },
  92. },
  93. methods: {
  94. handleError(e) {
  95. this.isError = true;
  96. this.$emit("error", e);
  97. },
  98. handleLoad(e) {
  99. this.isError = false;
  100. this.$emit("load", e);
  101. },
  102. onPreview() {
  103. // 点击是否预览图片
  104. if (this.previewList) {
  105. uni.previewImage({
  106. urls: this.previewList,
  107. current: this.src,
  108. });
  109. }
  110. },
  111. },
  112. };
  113. </script>