来个大佬,如何优化设计这个组件?

基于 el-select 封装了一个 my-select

接受一个外部传入的api,其中 request 是封装好了的 axios 请求函数

const getUserList = (data)=>{

return request({

data

})

}

<my-select :api="getUserList">

现在遇到一个场景, 要改变 其中的参数,改完后就重新渲染 select 我现在想了两个方案

  1. 手动更新外部 getUserList

    const params = {name:xxx}

    this.getUserList = ()=>{

    return request({

    data:params

    })

    }

    2.传入 requestparams 监听 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" />


回答:

个人感觉这个组件可能没有封装的意义,看到的描述,你封装的组件有两种方向:

  1. 传递一个 API 给组件内部调用,获取数据
  2. API 固定,组件内部监听传递的参数变化,调用 API 获取数据

不管哪种方式,可以确定是只有参数会发生变化,接口是固定的;

这个时候我思考的问题是:

  1. 接口返回的数据量大吗?
  2. 接口调用频繁吗?

我思考的方向是优化,而不是封装组件;

优化的方向不管是接口返回的数据量大还是调用频繁,我都使用数据缓存来做:

方案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。


回答:

  1. request在父组件写好,传给my-select,给选择按钮添加一个点击事件,点击时调用这个从父组件传下来的request,做到点击时更新下拉菜单,缺点是每次点击select都会有一个loading
  2. requset在父组件写好,由父组件更新optionsmy-select中仅获取父组件传下来的options
  3. 在父组件受到参数影响的位置绑定一个与改参数有关的key,让参数更新时重新渲染所有内容,其中就能包括这个select和里面的值

以上是 来个大佬,如何优化设计这个组件? 的全部内容, 来源链接: utcz.com/p/933682.html

回到顶部