源码里看不懂的先放一放,先往下看。
一、 Input 输入框组件
- 入口文件与按钮等其他组件一样,不再重复。 2.关于value
/* 接受传入的value作为input的value */
<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="value"
ref="input"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur"
>
/* 监听传入的value,并将value值存在currentValue 如果textarea的情况,根据内容动态计算尺寸
然后发射input、change事件
*/
watch: {
'value'(val, oldValue) {
this.currentValue = val;
},
'currentValue'(val) {
this.$nextTick(_ => {
this.resizeTextarea();
});
this.$emit('input', val);
this.$emit('change', val);
/* 这里发射了事件,具体逻辑写在 mixins: [emitter]中 */
this.dispatch('form-item', 'el.form.change', [val]);
}
}
3、emitter.js
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
var name = child.$options.componentName;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat(params));
}
});
}
export default {
methods: {
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root;
var name = parent.$options.componentName;
/* 找到指定的父组件,这里是'form-item */
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
/* 让组件发射事件, apply将第二个参数(数组)打散,使其对应方法中的参数 */
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
/* 'form-item'响应事件 触发相关规则的校验 */
this.$on('el.form.change', this.onFieldChange);