vue二次封装element ui的select或者input组件
有时候我们会把select或者input等element ui组件进行业务封装,方便复用的需求。比如我有个select,需要获取部门信息,在多个列表里使用,那我可以进行如下封装
熟悉Vue的小伙伴们都知道 v-model 是Vue的一个很大的特色,可以实现双向数据绑定。但本质上呢,它不过是语法糖,它负责监听用户的输入事件以更新数据。
以下摘取自Vue官方文档
v-model 在内部使用不同的属性为不同的输入元素并抛出不同的事件:
- text 和 textarea 使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
如何巧妙利用 v-model实现父子组件传值
通常子组件某个变量更新,并需要告知父组件时,需要子组件触发事件并父组件监听该事件。
但是熟悉上面 v-model 的实现原理后,我们可以巧妙地运用这一原理(v-model 在内部使用不同的属性为不同的输入元素并抛出不同的事件)。
方法总结:
1.子组件设 value 为props属性,并且不主动改变 value 值
2.子组件通过 this.$emit('input', 'updateValue') 将 updateValue 值传给父组件
3.父组件通过 v-model="localValue" 绑定一个本地变量,即可实现子组件value值与父组件updateValue 值同步更新
首先组件的使用
父组件:
<template>
<el-form-item label="销售员:">
<AjaxSelect
v-model="creatorId" // 核心代码
placeholder="请选择销售员"
@change="onChangeMemberId"
url="/api/stock/purchase/query_employee_all"
/>
</el-form-item>
</template>
import AjaxSelect from "./sale_components/ajax_select";
export default {
data(){
return {
creatorId:"" // 核心代码
}
},
methods:{
onChangeMemberId(val) {
// console.log("val", val);
},
}
}
子组件::
<template>
<el-select
v-model="val" // 核心代码
clearable
filterable
:disabled="disabled"
:placeholder="placeholder"
style="width: 100%"
remote
:remote-method="ajaxMember"
@keyup.enter.native="ajaxMember"
@focus="onFocusMember"
@change="onChangeMember"
>
<el-option
v-for="item in options"
:key="getKey(item.memberId)"
:label="item.memberName"
:value="item.memberId"
></el-option>
</el-select>
</template>
<script>
import http from "@/libs/http";
export default {
name: "select_member",
data() {
return {
options: [],
selected: "",
memberId: "",
val: "" // 核心代码
};
},
// event: "change",
props: {
placeholder: {
type: String,
default: "请选择会员名称"
},
url: {
type: String,
default: "/api/stock/purchase/query_members"
},
like: {
type: String,
default: "name"
},
pageSize: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
value: { // 核心代码
type: Number | String,
default: ""
}
},
watch: {
// 核心代码
value(newVal, oldVal) {
// console.log("newVal", newVal, oldVal);
if (newVal !== oldVal) {
this.val = newVal;
}
}
},
methods: {
getKey(key) {
return Symbol(key);
},
onFocusMember() {
if (this.options.length) {
return;
}
this.ajaxMember();
},
// 核心代码
onChangeMember(v) {
if (this.val) {
this.selected = this.options.find(item => {
return item.memberId === this.val;
});
} else {
this.selected = {};
}
// console.log("99", this.val);
this.$emit("input", this.val, this.selected);
this.$emit("change", this.val, this.selected);
},
//远程搜索会员
ajaxMember(query = "") {
let data = {
isControl: false,
pageNum: 1,
pageSize: this.pageSize
};
if (this.like) {
data[this.like] = query;
}
return new Promise((resolve, reject) => {
http
.get(this.url, data, { autoHandleErrors: false })
.then(res => {
if (res.code === 200) {
let lists = res.data.recordList || res.data || [];
this.options = lists.map(item => {
return {
...item,
memberId: item.member_id || item.id,
memberName: item.company_full_name || item.name
};
});
resolve(lists);
} else {
reject(lists);
}
})
.catch(res => {
reject(res);
});
});
}
}
};
</script>
本文主要用了 v-model 绑定自定义组件来实现
子组件通过 $emit('input') 更新父组件的本地变量
父组件通过props把value值传递给子组件
另外子组件select时,还回调了父组件传递进来的change事件。
版权声明
本站部分原创文章,部分文章整理自网络。如有转载的文章侵犯了您的版权,请联系站长删除处理。如果您有优质文章,欢迎发稿给我们!联系站长:
愿本站的内容能为您的学习、工作带来绵薄之力。
评论