前提的需求:
公司做了一个设计器,我们对一些组件进行二次封装。移动端我采取了vant这个UI框架。在写textarea的时候,发现
解决minHeight失效问题,只需要在需要使用自适应的时候,将传递过来的minHeight转成行数,赋值给rows就行。
我们是后端给我们传的自适应的值是行数,最小行和最大行。所以这里需要将行数改为高度。从element参考的文件:
calcTextareaHeight.js(将行数换算成高度,并且返回了minHeight,height,maxHeight。入参是$el,minRows,maxRows)
let hiddenTextarea
const HIDDEN_STYLE = `
height:0 !important;
visibility:hidden !important;
overflow:hidden !important;
position:absolute !important;
z-index:-1000 !important;
top:0 !important;
right:0 !important
`
const CONTEXT_STYLE = [
'letter-spacing',
'line-height',
'padding-top',
'padding-bottom',
'font-family',
'font-weight',
'font-size',
'text-rendering',
'text-transform',
'width',
'text-indent',
'padding-left',
'padding-right',
'border-width',
'box-sizing'
]
function calculateNodeStyling(targetElement1) {
if (targetElement1) {
const style = window.getComputedStyle(targetElement1)
const boxSizing = style.getPropertyValue('box-sizing')
const paddingSize = (
parseFloat(style.getPropertyValue('padding-bottom')) +
parseFloat(style.getPropertyValue('padding-top'))
)
const borderSize = (
parseFloat(style.getPropertyValue('border-bottom-width')) +
parseFloat(style.getPropertyValue('border-top-width'))
)
const contextStyle = CONTEXT_STYLE
.map(name => `${name}:${style.getPropertyValue(name)}`)
.join(';')
return { contextStyle, paddingSize, borderSize, boxSizing }
} else {
console.log('it‘s null')
}
}
export default function calcTextareaHeight(
targetElement1,
minRows = 1,
maxRows = null
) {
if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea')
document.body.appendChild(hiddenTextarea)
}
let {
paddingSize,
borderSize,
boxSizing,
contextStyle
} = calculateNodeStyling(targetElement1)
hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`)
hiddenTextarea.value = targetElement1.value || targetElement1.placeholder || ''
let height = hiddenTextarea.scrollHeight
const result = {}
if (boxSizing === 'border-box') {
height = height + borderSize
} else if (boxSizing === 'content-box') {
height = height - paddingSize
}
hiddenTextarea.value = ''
let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize
if (minRows !== null) {
let minHeight = singleRowHeight * minRows
if (boxSizing === 'border-box') {
minHeight = minHeight + paddingSize + borderSize
}
height = Math.max(minHeight, height)
result.minHeight = `${minHeight}`
}
if (maxRows !== null) {
let maxHeight = singleRowHeight * maxRows
if (boxSizing === 'border-box') {
maxHeight = maxHeight + paddingSize + borderSize
}
height = Math.min(maxHeight, height)
result.maxHeight = `${maxHeight}`
}
result.height = `${height}`
hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea)
hiddenTextarea = null
return result
}
在vue里面使用:
js:
import calcTextareaHeight from './calcTextareaHeight'
props: {
value: {
type: null,
require: false
},
resize: String
},
mounted() {
this.resizeTextarea()
if (this.getEllipsis() || this.getAdaptiveValue()) { // 设置了自适应
// 因为最小的高度不生效,所以这里设置一个rows就可以当做是最小高度了
this.propertyAttr.rows = this.getAdaptiveValue().minRows
this.textareaCalcStyle = this.merge({}, this.textareaCalcStyle, { resize: this.resize })
this.autosize = { maxHeight: this.textareaCalcStyle.maxHeight }
console.log(this.autosize)
} else {
this.autosize = false
}
},
methods: {
resizeTextarea() {
// 获取最小rows和最大rows,通过方法计算高度并返回。
const minRows = this.getAdaptiveValue().minRows
const maxRows = this.getAdaptiveValue().maxRows
this.textareaCalcStyle = calcTextareaHeight(this.$refs.textarea.$refs.input, minRows, maxRows)
},
merge(target) {
for (let i = 1, j = arguments.length; i < j; i++) {
let source = arguments[i] || {}
for (let prop in source) {
if (source.hasOwnProperty(prop)) {
let value = source[prop]
if (value !== undefined) {
target[prop] = value
}
}
}
}
return target
}
}
这样就可以了!