UNPKG

ivue-material-plus

Version:

A high quality UI components Library with Vue.js

1 lines 14 kB
{"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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"}