83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
import {nextTick, watch, onMounted, type Ref} from 'vue'
|
||
|
||
/**
|
||
* 图片样式处理 Composable
|
||
* 用于强制处理 v-html 内容中的图片样式
|
||
*/
|
||
export const useImageStyles = (
|
||
contentRef: Ref<string> | (() => string),
|
||
containerSelector: string = '.article-content',
|
||
options: {
|
||
maxWidth?: string
|
||
margin?: string
|
||
display?: string
|
||
boxSizing?: string
|
||
} = {}
|
||
) => {
|
||
// 默认配置
|
||
const defaultOptions = {
|
||
maxWidth: 'calc(100% - 0px)',
|
||
margin: '15px 0',
|
||
display: 'block',
|
||
boxSizing: 'border-box',
|
||
...options
|
||
}
|
||
|
||
/**
|
||
* 强制处理图片样式
|
||
*/
|
||
const forceImageStyles = () => {
|
||
if (typeof document === 'undefined') return
|
||
|
||
const images = document.querySelectorAll(`${containerSelector} img`)
|
||
images.forEach((img: any) => {
|
||
// 强制设置样式
|
||
img.style.maxWidth = defaultOptions.maxWidth
|
||
img.style.height = 'auto'
|
||
img.style.width = 'auto'
|
||
img.style.display = defaultOptions.display
|
||
img.style.margin = defaultOptions.margin
|
||
img.style.boxSizing = defaultOptions.boxSizing
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 处理图片样式的核心方法
|
||
*/
|
||
const processImageStyles = () => {
|
||
nextTick(() => {
|
||
forceImageStyles()
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 初始化图片样式处理
|
||
*/
|
||
const initImageStyles = () => {
|
||
// 组件挂载时处理
|
||
onMounted(() => {
|
||
processImageStyles()
|
||
})
|
||
|
||
// 监听内容变化
|
||
if (typeof contentRef === 'function') {
|
||
// 如果是函数,直接监听
|
||
watch(contentRef, () => {
|
||
processImageStyles()
|
||
}, {deep: true})
|
||
} else {
|
||
// 如果是 Ref,监听其值
|
||
watch(contentRef, () => {
|
||
processImageStyles()
|
||
}, {deep: true})
|
||
}
|
||
}
|
||
|
||
return {
|
||
forceImageStyles,
|
||
processImageStyles,
|
||
initImageStyles,
|
||
|
||
}
|
||
}
|