来个大佬,如何优化设计这个组件?
基于 el-select
封装了一个 my-select
接受一个外部传入的api
,其中 request
是封装好了的 axios
请求函数
const getUserList = (data)=>{ return request({
data
})
}
<my-select :api="getUserList">
现在遇到一个场景, 要改变 其中的参数,改完后就重新渲染 select 我现在想了两个方案
手动更新外部
getUserList
const params = {name:xxx}
this.getUserList = ()=>{
return request({
data:params
})
}
2.传入
request
params
监听params
的改变 内部更新getUserList
<my-select :request="request" :params="params">
watch:{
params:{
handler(val){
this.getUserList = ()=>{
return request({
data:val
})
}
},
deep:true
}
}
总结下,就是传入一个业务 api
, 如何更加优雅的 去更新 组件内部 api
的参数值~
底层组件,最好让使用者 更加简单 易上手~
回答:
有点疑惑,select
这种直接展示结果的组件,既然都是底层组件了,针对异步获取数据,直接业务使用方拿到结果后传给组件不就行了么,为什么还要大费周折把异步方法传入到组件内部去处理?
个人认为你这里应该封装的是getUserList
方法,然后参数变化的时候每次重新调用这个请求,而不是封装select
// getUserList允许传入参数
const params = reactive({});
const data = ref([]);
const getUserList = (val)=>{
return request({
data:val
})
}
// 这里如何保证每次params变化,this.data也变化
data.value = await this.getUserList(params);
// 比如使用computed
data.value = computed(async () => await getUserList(params));
// data如何变化全部交由业务方决定,组件只负责拿到最新的data渲染即可
<select :options="data" />
回答:
个人感觉这个组件可能没有封装的意义,看到的描述,你封装的组件有两种方向:
- 传递一个 API 给组件内部调用,获取数据
- API 固定,组件内部监听传递的参数变化,调用 API 获取数据
不管哪种方式,可以确定是只有参数会发生变化,接口是固定的;
这个时候我思考的问题是:
- 接口返回的数据量大吗?
- 接口调用频繁吗?
我思考的方向是优化,而不是封装组件;
优化的方向不管是接口返回的数据量大还是调用频繁,我都使用数据缓存来做:
方案1
<el-select> <el-option
v-for="item in list"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
export default {
data() {
return {
selectData: [],
params: {
condition1: '',
condition2: ''
}
}
},
computed: {
list() {
return this.selectData.filter(item => {
const entries = Object.entries(this.params);
return entries.every(([key, value]) => {
if (value === '') {
return true;
}
switch (typeof item[key]) {
case 'string':
return item[key].includes(value);
case 'number':
return item[key] === value;
// ...
default:
return false;
}
})
});
}
},
created() {
// 数据量少直接获取全部数据
request().then(res => {
this.selectData = res.data;
});
}
}
这种方式在条件多变,请求频繁,数据量并不是很大的情况下比较合适。
方案2
export default { data() {
return {
cache: {},
params: {
condition1: '',
condition2: ''
}
}
},
computed: {
list() {
const key = JSON.stringify(this.params);
if (!this.cache[key]) {
request(this.params);
}
return this.cache[key] || [];
}
},
methods: {
getData() {
request(this.params).then(res => {
this.cache[JSON.stringify(this.params)] = res;
})
}
}
}
这种在条件变化没那么频繁,且条件相对固定的情况下比较合适,适合数据量大,接口请求比较耗时的情况。
然后就是继续优化,第二种方案就没必要优化了,没几行代码,第一种情况如果条件复杂就可以封装组件,将业务逻辑封装起来,简化代码。
回答:
我的想法一直都是使用 mixins
混入。主要就是查询函数和一些 QueryParams
都固定好,只不过URL按照具体页面去赋值,或者使用 import { remoteAPI as loadData } from '@api/xxx.js
形式去引入。
具体思路可以借鉴这个 mxins
文件 JeecgListMixin.js at master · jeecgboot/ant-design-vue-jeecg。
回答:
request
在父组件写好,传给my-select
,给选择按钮添加一个点击事件,点击时调用这个从父组件传下来的request
,做到点击时更新下拉菜单,缺点是每次点击select都会有一个loadingrequset
在父组件写好,由父组件更新options
,my-select
中仅获取父组件传下来的options
- 在父组件受到参数影响的位置绑定一个与改参数有关的key,让参数更新时重新渲染所有内容,其中就能包括这个
select
和里面的值
以上是 来个大佬,如何优化设计这个组件? 的全部内容, 来源链接: utcz.com/p/933682.html