{"version":3,"file":"index2.mjs","sources":["../../../../../src/components/ivue-image/index.vue"],"sourcesContent":["<template>\r\n  <div :class=\"prefixCls\" :style=\"wrapperStyles\" ref=\"wrapper\">\r\n    <!-- 加载中 -->\r\n    <div :class=\"`${prefixCls}-loading`\" v-if=\"data.loading\">\r\n      <slot name=\"loading\">\r\n        <span>{{ loadingText }}</span>\r\n      </slot>\r\n    </div>\r\n    <!-- 加载错误 -->\r\n    <div :class=\"`${prefixCls}-error`\" v-else-if=\"data.imageError\">\r\n      <slot name=\"error\">\r\n        <span>{{ errorText }}</span>\r\n      </slot>\r\n    </div>\r\n    <!-- content -->\r\n    <div\r\n      :class=\"`${prefixCls}-content`\"\r\n      @click=\"handlePreview\"\r\n      v-if=\"data.loadingImage\"\r\n    >\r\n      <img\r\n        :src=\"src\"\r\n        :class=\"imageClasses\"\r\n        :style=\"imageStyles\"\r\n        :referrerPolicy=\"referrerPolicy\"\r\n        :loading=\"loadingType\"\r\n        @load=\"handleImageLoad\"\r\n        @error=\"handleImageError\"\r\n      />\r\n      <slot name=\"preview\" v-if=\"preview && previewTip\">\r\n        <div :class=\"`${prefixCls}-mark`\">\r\n          <span>{{ previewText }}</span>\r\n        </div>\r\n      </slot>\r\n    </div>\r\n\r\n    <!-- 图片预览 -->\r\n    <image-preview\r\n      v-model=\"data.imagePreviewModal\"\r\n      :previewList=\"previewList\"\r\n      :initialIndex=\"initialIndex\"\r\n      @on-close=\"handleImagePreviewClose\"\r\n      @on-switch=\"handleImageSwitch\"\r\n    ></image-preview>\r\n  </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport {\r\n  defineComponent,\r\n  ref,\r\n  computed,\r\n  reactive,\r\n  onMounted,\r\n  onBeforeUnmount,\r\n} from 'vue';\r\nimport { isClient, isElement } from '../../utils/helpers';\r\nimport { oneOf } from '../../utils/assist';\r\nimport ImagePreview from './image-preview.vue';\r\n\r\n// type\r\nimport type { Props, Data } from './types/image';\r\n\r\nconst prefixCls = 'ivue-image';\r\n\r\nexport default defineComponent({\r\n  name: prefixCls,\r\n  emits: ['on-click', 'on-load', 'on-error', 'on-close', 'on-switch'],\r\n  props: {\r\n    /**\r\n     * 圆角\r\n     *\r\n     * @type {Number | String}\r\n     */\r\n    radius: {\r\n      type: [Number, String],\r\n      default: 0,\r\n    },\r\n    /**\r\n     * 图片源地址\r\n     *\r\n     * @type {String}\r\n     */\r\n    src: {\r\n      type: String,\r\n      default: '',\r\n    },\r\n    /**\r\n     * 确定图片如何适应容器框，同原生 object-fit\r\n     *\r\n     * @type {String}\r\n     */\r\n    fit: {\r\n      type: String,\r\n      validator(value: string) {\r\n        return oneOf(value, [\r\n          '',\r\n          'contain',\r\n          'cover',\r\n          'fill',\r\n          'none',\r\n          'scale-down',\r\n        ]);\r\n      },\r\n      default: '',\r\n    },\r\n    /**\r\n     * 图片描述\r\n     *\r\n     * @type {String}\r\n     */\r\n    alt: {\r\n      type: String,\r\n      default: '',\r\n    },\r\n    /**\r\n     * 首部用来监管哪些访问来源信息\r\n     *\r\n     * @type {String}\r\n     */\r\n    referrerPolicy: {\r\n      type: String,\r\n      validator(value: string) {\r\n        return oneOf(value, [\r\n          'no-referrer',\r\n          'no-referrer-when-downgrade',\r\n          'origin',\r\n          'origin-when-cross-origin',\r\n          'same-origin',\r\n          'strict-origin',\r\n          'strict-origin-when-cross-origin',\r\n          'unsafe-url',\r\n        ]);\r\n      },\r\n    },\r\n    /**\r\n     * 是否使用懒加载\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    lazy: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * loading文案\r\n     *\r\n     * @type {String}\r\n     */\r\n    loadingText: {\r\n      type: String,\r\n      default: '加载中',\r\n    },\r\n    /**\r\n     * 加载错误文案\r\n     *\r\n     * @type {String}\r\n     */\r\n    errorText: {\r\n      type: String,\r\n      default: '加载失败',\r\n    },\r\n    /**\r\n     * 是否图片预览\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    preview: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 图片预览文案\r\n     *\r\n     * @type {String}\r\n     */\r\n    previewText: {\r\n      type: String,\r\n      default: '预览',\r\n    },\r\n    /**\r\n     * 是否显示预览提示和遮罩\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    previewTip: {\r\n      type: Boolean,\r\n      default: true,\r\n    },\r\n    /**\r\n     * 滚动加载容器\r\n     *\r\n     * @type {String}\r\n     */\r\n    scrollContainer: {\r\n      type: [String, Object],\r\n      default: '',\r\n    },\r\n    /**\r\n     * 打开预览的第一项\r\n     *\r\n     * @type {Number}\r\n     */\r\n    initialIndex: {\r\n      type: Number,\r\n      default: 0,\r\n    },\r\n    /**\r\n     * 图片预览列表\r\n     *\r\n     * @type {Array}\r\n     */\r\n    previewList: {\r\n      type: Array,\r\n    },\r\n  },\r\n  setup(props: Props, { emit }) {\r\n    // dom\r\n    const wrapper = ref<HTMLDivElement>();\r\n\r\n    // data\r\n    const data = reactive<Data>({\r\n      /**\r\n       * 加载中\r\n       *\r\n       * @type {Boolean}\r\n       */\r\n      loadingImage: false,\r\n      /**\r\n       * 加载中\r\n       *\r\n       * @type {Boolean}\r\n       */\r\n      loading: false,\r\n      /**\r\n       * 图片错误\r\n       *\r\n       * @type {Boolean}\r\n       */\r\n      imageError: false,\r\n      /**\r\n       * 滚动的元素\r\n       *\r\n       * @type {String}\r\n       */\r\n      scrollElement: null,\r\n      /**\r\n       * 异步检测目标元素与祖先元素或 viewport 相交情况变化的方法\r\n       *\r\n       * @type {Function}\r\n       */\r\n      observer: null,\r\n      /**\r\n       * 图片预览弹窗\r\n       *\r\n       * @type {Boolean}\r\n       */\r\n      imagePreviewModal: false,\r\n    });\r\n\r\n    // computed\r\n\r\n    // 外部样式\r\n    const wrapperStyles = computed(() => {\r\n      let obj = {};\r\n\r\n      // 圆角\r\n      if (props.radius) {\r\n        const regexp = new RegExp(/[a-zA-Z]/g);\r\n\r\n        // 是否有单位\r\n        const isUnit = regexp.test(`${props.radius}`);\r\n\r\n        obj = {\r\n          borderRadius: !isUnit ? `${props.radius}px` : props.radius,\r\n        };\r\n      }\r\n\r\n      return obj;\r\n    });\r\n\r\n    // 图片样式\r\n    const imageClasses = computed(() => {\r\n      return [`${prefixCls}-img`];\r\n    });\r\n\r\n    // 图片样式\r\n    const imageStyles = computed(() => {\r\n      const { fit } = props;\r\n\r\n      let obj = {};\r\n\r\n      // 确定图片如何适应容器框\r\n      if (isClient && fit) {\r\n        obj = {\r\n          objectFit: fit,\r\n        };\r\n      }\r\n\r\n      return obj;\r\n    });\r\n\r\n    // 浏览器加载图像的策略\r\n    const loadingType = computed(() => {\r\n      // eager：立即加载图像，无论图像当前是否在可见视口内-默认值\r\n      // lazy：延迟加载图像，直到它达到与浏览器定义的视口的计算距离。\r\n      return props.lazy ? 'lazy' : 'eager';\r\n    });\r\n\r\n    // methods\r\n\r\n    // 图片完成\r\n    const handleImageLoad = () => {\r\n      data.loading = false;\r\n      data.imageError = false;\r\n\r\n      // 图片加载成功\r\n      emit('on-load');\r\n    };\r\n\r\n    // 图片错误\r\n    const handleImageError = () => {\r\n      data.loading = false;\r\n      data.imageError = true;\r\n\r\n      data.loadingImage = false;\r\n\r\n      // 图片加载失败\r\n      emit('on-error');\r\n    };\r\n\r\n    // 懒加载图片\r\n    const lazyImage = () => {\r\n      data.scrollElement = null;\r\n\r\n      // 元素\r\n      if (isElement(props.scrollContainer)) {\r\n        data.scrollElement = props.scrollContainer;\r\n      }\r\n      // 不是元素\r\n      else if (\r\n        props.scrollContainer &&\r\n        typeof props.scrollContainer === 'string'\r\n      ) {\r\n        // 寻找元素\r\n        data.scrollElement = document.querySelector(props.scrollContainer);\r\n      }\r\n\r\n      // 懒加载 IntersectionObserver\r\n      handIntersectionObserverle();\r\n    };\r\n\r\n    // 初始化加载图片\r\n    const initLoadImage = () => {\r\n      data.loading = true;\r\n      data.imageError = false;\r\n\r\n      data.loadingImage = true;\r\n    };\r\n\r\n    // 懒加载\r\n    const handIntersectionObserverle = () => {\r\n      // https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API\r\n      // 注册一个回调函数，每当被监视的元素进入或者退出另外一个元素时 (或者 viewport )，\r\n      // 或者两个元素的相交部分大小发生变化时，该回调方法会被触发执行 handlerObserveImage\r\n      // 我们网站的主线程不需要再为了监听元素相交而辛苦劳作，浏览器会自行优化元素相交管理。\r\n      data.observer = new IntersectionObserver(handlerObserveImage, {\r\n        // 指定根 (root) 元素，用于检查目标的可见性\r\n        root: data.scrollElement,\r\n        // 根 (root) 元素的外边距\r\n        rootMargin: '0px',\r\n        // 可以是单一的 number 也可以是 number 数组，\r\n        // target 元素和 root 元素相交程度达到该值的时候\r\n        // IntersectionObserver 注册的回调函数将会被执行\r\n        threshold: 0,\r\n      });\r\n\r\n      data.observer.observe(wrapper.value);\r\n    };\r\n\r\n    // 异步加载图片\r\n    const handlerObserveImage = (entries) => {\r\n      for (const entry of entries) {\r\n        // 元素是否与交集观察者的根相交\r\n        if (entry.isIntersecting) {\r\n          // 停止观察其所有目标元素的可见性变化\r\n          observerDisconnect();\r\n          // 加载图片\r\n          initLoadImage();\r\n        }\r\n      }\r\n    };\r\n\r\n    // 停止观察其所有目标元素的可见性变化\r\n    const observerDisconnect = () => {\r\n      data.observer && data.observer.disconnect();\r\n    };\r\n\r\n    // 预览图片\r\n    const handlePreview = () => {\r\n      if (props.preview) {\r\n        data.imagePreviewModal = true;\r\n\r\n        emit('on-click', {\r\n          initialIndex: props.initialIndex,\r\n        });\r\n      }\r\n    };\r\n\r\n    // 切换\r\n    const handleImageSwitch = (params: { currentIndex: number }) => {\r\n      emit('on-switch', params);\r\n    };\r\n\r\n    // 图片预览关闭\r\n    const handleImagePreviewClose = () => {\r\n      emit('on-close');\r\n    };\r\n\r\n    // onMounted\r\n    onMounted(() => {\r\n      if (isClient) {\r\n        props.lazy ? lazyImage() : initLoadImage();\r\n      }\r\n    });\r\n\r\n    // onBeforeUnmount\r\n    onBeforeUnmount(() => {\r\n      observerDisconnect();\r\n    });\r\n\r\n    return {\r\n      prefixCls,\r\n\r\n      // dom\r\n      wrapper,\r\n\r\n      // data\r\n      data,\r\n\r\n      // computed\r\n      wrapperStyles,\r\n      imageClasses,\r\n      imageStyles,\r\n      loadingType,\r\n\r\n      // methods\r\n      handleImageLoad,\r\n      handleImageError,\r\n      handlePreview,\r\n      handleImagePreviewClose,\r\n      handleImageSwitch,\r\n    };\r\n  },\r\n  components: {\r\n    ImagePreview,\r\n  },\r\n});\r\n</script>\r\n"],"names":["_resolveComponent","_openBlock","_createElementBlock","_normalizeClass","_normalizeStyle","_createCommentVNode","_Fragment","_createElementVNode","_renderSlot","_createVNode"],"mappings":"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"}