这篇文章主要为大家详细介绍了Element Input组件分析小结,具有一定的参考价值,可以用来参考一下。
感兴趣的小伙伴,下面一起跟随四海网的小编两巴掌来看看吧!
input组件相对来说复杂一点,我们先从它用到的一个工具库calcTextareaHeight.js
进行分析。
calcTextareaHeight.js使用来计算文本框的高度的,我们根据代码顺序从上往下进行分析。
HIDDEN_STYLE是一个常量,存储隐藏时候的css样式的。
代码如下:
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
`;
CONTEXT_STYLE也是一个常量,用来存储要查询的样式名。
代码如下:
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'
];
calculateNodeStyling用来获取结点的某些样式。
代码如下:
function calculateNodeStyling(node) {
const style = window.getComputedStyle(node); // 获取结点的计算后的样式,即实际渲染的样式
const boxSizing = style.getPropertyValue('box-sizing'); // 获取 box-sizing 的值
// 上下的 padding 之和
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 };
}
calcTextareaHeight是最终暴露出去的函数,用来计算文本域的高度。
代码如下:
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}`);
// 设置内容,按优先级一次是 结点的 value, 结点的 placeholder, 以及空字符串
hiddenTextarea.value = targetNode.value || targetNode.placeholder || '';
// 获取滚动高度
let height = hiddenTextarea.scrollHeight;
if (boxSizing === 'border-box') {
// 如果是 border-box,说明高度得加上边框
height = height + borderSize;
} else if (boxSizing === 'content-box') {
// 如果是 content-box,说明得减去上下内边距
height = height - paddingSize;
}
// 计算单行高度,先清空内容
hiddenTextarea.value = '';
// 再用滚动高度减去上下内边距
let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
if (minRows !== null) { // 如果参数传递了 minRows
let minHeight = singleRowHeight * minRows; // 说明最少应当有这么多行的高度
if (boxSizing === 'border-box') { // 如果是 border-box,还得加上上下内边距和上下边框的宽度
minHeight = minHeight + paddingSize + borderSize;
}
height = Math.max(minHeight, height); // 取二者最大值
}
if (maxRows !== null) { // 如果参数传递了 maxRows
let maxHeight = singleRowHeight * maxRows; // 说明最多只能有这么多行的高度
if (boxSizing === 'border-box') { // 如果是 border-box,还得加上上下内边距和上下边框的宽度
maxHeight = maxHeight + paddingSize + borderSize;
}
height = Math.min(maxHeight, height); // 取二者最小值
}
// 返回文本域应当设置的高度
return { height: height + 'px'};
};
input组件较为繁琐,我们一点点分析。
created
创建的时候会监听inputSelect事件,并调用inputSelect方法。
代码如下:
created() {
this.$on('inputSelect', this.inputSelect);
},
inputSelect方法会调用refs上的input的原生的select方法,来选中该input。
代码如下:
methods: {
inputSelect() {
this.$refs.input.select();
},
}
挂载的时候,会调用resizeTextarea方法来设置文本域的大小。
代码如下:
mounted() {
this.resizeTextarea();
}
代码如下:
methods: {
resizeTextarea() {
if (this.$isServer) return; // 如果是服务端渲染,直接返回,不进行下面的逻辑
var { autosize, type } = this;
if (!autosize || type !== 'textarea') return; // 如果 autosize 是 false,或者当前不是文本域,也直接返回
const minRows = autosize.minRows; // 最少行数
const maxRows = autosize.maxRows; // 最大行数
this.textareaStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows); // 计算文本域的高度,并赋值
},
}
最外层是一个div,上面设置了一些动态的class。
代码如下:
<div :class="[
type === 'textarea' ? 'el-textarea' : 'el-input',
size ? 'el-input--' + size : '',
{
'is-disabled': disabled,
'el-input-group': $slots.prepend || $slots.append,
'el-input-group--append': $slots.append,
'el-input-group--prepend': $slots.prepend
}
]">
</div>
type是一个prop,它默认设置为text,如果设置为textarea,表明当前是一个文本域。
代码如下:
props: {
type: {
type: String,
default: 'text'
},
}
size也是一个prop,用来设置输入框的大小,在textarea下无效。
代码如下:
props: {
size: String,
}
disabled也是一个prop,用来设置是否可用。
代码如下:
props: {
disabled: Boolean,
}
这两个都是在设置输入框组的时候使用的,通过具名slot传入,分别放置于input的首和尾。
然后,根据type的不同使用v-if分别渲染input或者textarea,我们先分析input部分。
前置元素直接通过具名slot传入。
代码如下:
<div class="el-input-group__prepend" v-if="$slots.prepend">
<slot name="prepend"></slot>
</div>
图标也是通过具名slot传入的,也可以通过prop中的icon传入图标名。
代码如下:
<slot name="icon">
<i
class="el-input__icon"
:class="'el-icon-' + icon"
v-if="icon"
@click="handleIconClick">
</i>
</slot>
上面还绑定了一个handleIconClick的点击事件,它会触发click事件:
代码如下:
methods: {
handleIconClick(event) {
this.$emit('click', event);
},
}
然后是最重要的input部分,上面大部分是prop,不进行讲解,其余的我们将一一讲解。
代码如下:
<input
v-if="type !== 'textarea'"
class="el-input__inner"
:type="type" // 类型
:name="name" // 名字
:placeholder="placeholder" // 默认值
:disabled="disabled" // 是否禁用
:readonly="readonly" // 是否只读
:maxlength="maxlength" // 输入的最大长度
:minlength="minlength" // 输入的最小长度(暂时不支持)
:autocomplete="autoComplete" // 自动补全
:autofocus="autofocus" // 自动聚焦
:min="min" // 允许输入的最小值(数字或者日期)
:max="max" // 允许输入的最大值(数字或者日期)
:form="form" // 绑定的表单(不是原生的)
:value="currentValue" // 输入值
ref="input" // 引用
@input="handleInput" // 输入事件
@focus="handleFocus" // 获得焦点事件
@blur="handleBlur" // 失去焦点事件
>
value改变的时候会调用setCurrentValue。
代码如下:
watch: {
'value'(val, oldValue) {
this.setCurrentValue(val);
}
},
而setCurrentValue是用来改变当前值的。
代码如下:
methods: {
setCurrentValue(value) {
if (value === this.currentValue) return; // 如果新旧值一致直接返回
this.$nextTick(_ => {
this.resizeTextarea(); // 下一个DOM更新周期时,重新设置文本域大小
});
this.currentValue = value; // 改变当前值
this.$emit('input', value); // 触发 input 事件
this.$emit('change', value); // 触发 change 事件
this.dispatch('ElFormItem', 'el.form.change', [value]); // 向父级的派发 el.form.change 事件
}
}
处理输入事件。
代码如下:
methods: {
handleInput(event) {
this.setCurrentValue(event.target.value); // 改变当前值
},
}
handleFocus用来处理获得焦点的事件,会直接触发focus事件。
代码如下:
methods: {
handleFocus(event) {
this.$emit('focus', event);
},
}
handleBlur用来处理失去焦点的事件。
代码如下:
methods: {
handleBlur(event) {
this.$emit('blur', event); // 触发 blur 事件
this.dispatch('ElFormItem', 'el.form.blur', [this.currentValue]); // 向父组件派发 el.form.blur 事件
},
}
loading会根据计算属性validating来决定是否渲染。
代码如下:
computed: {
validating() {
return this.$parent.validateState === 'validating';
}
},
代码如下:
<i class="el-input__icon el-icon-loading" v-if="validating"></i>
后置元素只能根据具名slot传入。
代码如下:
<div class="el-input-group__append" v-if="$slots.append">
<slot name="append"></slot>
</div>
如果type设置为textarea则会渲染textarea,上面绑定的都和input类似,不再多说,多了一个textareaStyle,是根据calcTextareaHeight计算出来的。
代码如下:
<textarea
v-else
class="el-textarea__inner"
:value="currentValue"
@input="handleInput"
ref="textarea"
:name="name"
:placeholder="placeholder"
:disabled="disabled"
:style="textareaStyle"
:readonly="readonly"
:rows="rows"
:form="form"
:autofocus="autofocus"
:maxlength="maxlength"
:minlength="minlength"
@focus="handleFocus"
@blur="handleBlur">
</textarea>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持四海网。
本文来自:http://www.q1010.com/184/6753-0.html
注:关于Element Input组件分析小结的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。
关键词:vue.js
四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。