依赖注入
核心思想:让后代组件能够访问到祖先组件的内容。
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
el-select 中通过 provider 来提供变量,在子孙组件 el-option 中通过 inject 来注入变量
provide() {
return {
'select': this
};
}
select 组件直接将自己的实例 this 注入 option 组件,这样 option 组件则可以通过 this.select 来修改父组件属性
inject: ['select']
created() {
this.select.options.push(this);
}
option 组件的 created 生命周期中,将自己的实例 this 注入到 select 组件的 options 数组中
selectOptionClick() {
if (this.disabled !== true && this.groupDisabled !== true) {
// emitter.js 文件通过 mixins 传进来方法 dispatch
this.dispatch('ElSelect', 'handleOptionClick', [this, true]);
}
}
option 组件中通过 dispatch 把点击事件暴露给 select 组件
handleOptionSelect(option, byClick) {
if (this.multiple) {
const value = (this.value || []).slice();
const optionIndex = this.getValueIndex(value, option.value);
if (optionIndex > -1) {
value.splice(optionIndex, 1);
} else if (this.multipleLimit <= 0 || value.length < this.multipleLimit) {
value.push(option.value);
}
this.$emit('input', value);
this.emitChange(value);
// ...
} else {
this.$emit('input', option.value);
this.emitChange(option.value);
this.visible = false;
}
// ...
this.$nextTick(() => {
this.scrollToOption(option);
});
}
在多选还是单选下进行不同的操作。this.$emit('input', value);
中传递改变的值就是 select 中绑定的 v-model 中的值 <el-select v-model="value">
。
下拉框的定位
引入了第三方库 popper.js,同时写了个 vue-popper.vue 来控制