mirror of https://github.com/ElemeFE/element
add rows and autosize property
parent
3c10d063e8
commit
70410a2b1f
|
@ -8,6 +8,7 @@
|
|||
- 修复 TimePicker 错误的隐藏面板
|
||||
- 修复 Table Cell 的样式, #204
|
||||
- 为 Message Box 和 Dialog 添加 lockScroll 属性,用于定义是否在弹框出现时将 body 滚动锁定
|
||||
- 新增 Input textarea 类型的 rows, autosize 属性
|
||||
|
||||
### 1.0.0-rc.5
|
||||
|
||||
|
|
|
@ -240,6 +240,8 @@
|
|||
```html
|
||||
<el-input
|
||||
type="textarea"
|
||||
placeholder="请输入内容"
|
||||
:autosize="{minRows: 2, maxRows: 5}"
|
||||
v-model="textarea">
|
||||
</el-input>
|
||||
```
|
||||
|
@ -625,15 +627,17 @@
|
|||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|------------- |---------------- |---------------- |---------------------- |-------- |
|
||||
| type | 同原生的 input 的 type 属性,如果为 textarea 则显示为 textarea | string | — | — |
|
||||
| type | 同原生的 input 的 type 属性,另外提供 type="textarea" | string | — | — |
|
||||
| value | 绑定值 | string, number | — | — |
|
||||
| maxlength | 最大输入长度 | number | — | — |
|
||||
| minlength | 最小输入长度 | number | — | — |
|
||||
| placeholder | 输入框占位文本 | string | — | — |
|
||||
| disabled | 禁用 | boolean | — | false |
|
||||
| size | 输入框尺寸 | string | large, small, mini | — |
|
||||
| size | 输入框尺寸,只在 `type!="textarea"` 时有效 | string | large, small, mini | — |
|
||||
| icon | 输入框尾部图标 | string | — | — |
|
||||
| number | 指定model值为number类型 | boolean | — | false |
|
||||
| number | 指定 model 值为 number 类型 | boolean | — | false |
|
||||
| rows | 输入框行数,只对 `type="textarea"` 有效 | number | — | 2 |
|
||||
| autosize | 自适应内容高度,只对 `type="textarea"` 有效,可传入对象,如,{ minRows: 2, maxRows: 6 } | boolean/object | — | false |
|
||||
|
||||
### Autocomplete API
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
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(node) {
|
||||
const style = window.getComputedStyle(node);
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
export default function calcTextareaHeight(
|
||||
targetNode,
|
||||
minRows = null,
|
||||
maxRows = null
|
||||
) {
|
||||
if (!hiddenTextarea) {
|
||||
hiddenTextarea = document.createElement('textarea');
|
||||
document.body.appendChild(hiddenTextarea);
|
||||
}
|
||||
|
||||
let {
|
||||
paddingSize,
|
||||
borderSize,
|
||||
boxSizing,
|
||||
contextStyle
|
||||
} = calculateNodeStyling(targetNode);
|
||||
|
||||
hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`);
|
||||
hiddenTextarea.value = targetNode.value || targetNode.placeholder || '';
|
||||
|
||||
let height = hiddenTextarea.scrollHeight;
|
||||
|
||||
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);
|
||||
}
|
||||
if (maxRows !== null) {
|
||||
let maxHeight = singleRowHeight * maxRows;
|
||||
if (boxSizing === 'border-box') {
|
||||
maxHeight = maxHeight + paddingSize + borderSize;
|
||||
}
|
||||
height = Math.min(maxHeight, height);
|
||||
}
|
||||
|
||||
return { height: height + 'px'};
|
||||
};
|
|
@ -13,20 +13,20 @@
|
|||
<slot name="prepend"></slot>
|
||||
</div>
|
||||
<input
|
||||
class="el-input__inner"
|
||||
v-model="currentValue"
|
||||
:type="type"
|
||||
:name="name"
|
||||
class="el-input__inner"
|
||||
:placeholder="placeholder"
|
||||
v-model="currentValue"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
@focus="$emit('onfocus', currentValue)"
|
||||
@blur="handleBlur"
|
||||
:number="number"
|
||||
:maxlength="maxlength"
|
||||
:minlength="minlength"
|
||||
:autocomplete="autoComplete"
|
||||
ref="input"
|
||||
@focus="$emit('onfocus', currentValue)"
|
||||
@blur="handleBlur"
|
||||
>
|
||||
<!-- input 图标 -->
|
||||
<i class="el-input__icon" :class="[icon ? 'el-icon-' + icon : '']" v-if="icon"></i>
|
||||
|
@ -36,12 +36,27 @@
|
|||
<slot name="append"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 写成垂直的方式会导致 placeholder 失效, 蜜汁bug -->
|
||||
<textarea v-else v-model="currentValue" class="el-textarea__inner" :name="name" :placeholder="placeholder" :disabled="disabled" :readonly="readonly" @focus="$emit('onfocus', currentValue)" @blur="handleBlur"></textarea>
|
||||
<textarea
|
||||
v-else
|
||||
class="el-textarea__inner"
|
||||
v-model="currentValue"
|
||||
ref="textarea"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:style="textareaStyle"
|
||||
:readonly="readonly"
|
||||
:rows="rows"
|
||||
:maxlength="maxlength"
|
||||
:minlength="minlength"
|
||||
@focus="$emit('onfocus', currentValue)"
|
||||
@blur="handleBlur">
|
||||
</textarea>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import emitter from 'main/mixins/emitter';
|
||||
import calcTextareaHeight from './calcTextareaHeight';
|
||||
|
||||
export default {
|
||||
name: 'ElInput',
|
||||
|
@ -82,6 +97,14 @@
|
|||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
autosize: {
|
||||
type: [Boolean, Object],
|
||||
default: false
|
||||
},
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
autoComplete: {
|
||||
type: String,
|
||||
default: 'off'
|
||||
|
@ -98,12 +121,22 @@
|
|||
|
||||
inputSelect() {
|
||||
this.$refs.input.select();
|
||||
},
|
||||
resizeTextarea() {
|
||||
var { autosize, type } = this;
|
||||
if (!autosize || type !== 'textarea') {
|
||||
return;
|
||||
}
|
||||
const minRows = autosize ? autosize.minRows : null;
|
||||
const maxRows = autosize ? autosize.maxRows : null;
|
||||
this.textareaStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
currentValue: ''
|
||||
currentValue: this.value,
|
||||
textareaStyle: {}
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -111,6 +144,10 @@
|
|||
this.$on('inputSelect', this.inputSelect);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.resizeTextarea();
|
||||
},
|
||||
|
||||
computed: {
|
||||
validating() {
|
||||
return this.$parent.validating;
|
||||
|
@ -118,16 +155,13 @@
|
|||
},
|
||||
|
||||
watch: {
|
||||
'value': {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.currentValue = val;
|
||||
}
|
||||
'value'(val, oldValue) {
|
||||
this.currentValue = val;
|
||||
this.resizeTextarea();
|
||||
},
|
||||
|
||||
'currentValue'(val) {
|
||||
this.$emit('input', val);
|
||||
this.$emit('onchange', val);
|
||||
this.dispatch('form-item', 'el.form.change', [val]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,11 +161,10 @@
|
|||
@e inner {
|
||||
display: block;
|
||||
resize: vertical;
|
||||
padding: 8px 5px;
|
||||
line-height: normal;
|
||||
padding: 5px 7px;
|
||||
line-height: 1.5;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-height: 88px;
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--input-color);
|
||||
background-color: #fff;
|
||||
|
|
Loading…
Reference in New Issue