Cenário do projeto:
Eu tenho muitos formulários de formulário e há muitos seletores de seleção no formulário de formulário. As listas suspensas desses seletores são renderizadas por meio dos dados retornados pela interface de back-end. Se cada seletor de seleção for usado para criar um componente , a redundância de código da página será muito grande e o custo de desenvolvimento e manutenção será relativamente alto, por isso é necessário encapsular.
No início, procurei artigos nesta área na Internet e descobri que os artigos atuais não eram adequados às minhas necessidades, então encontrei uma maneira de empacotar um e compartilhar minhas ideias e códigos aqui.
Efeito
1. Lista suspensa de pacotes
Criar RangeSearch.vue
<!--
component:远程搜索下拉列表
time:2022/12/15
1.placeholder(默认为空数组):占位符
示例:
:placeholder="'Please_enter_customer_ID'"
2.SelectData(必传):下拉框数据
此处有有一个重要逻辑,原本这个数据是子组件接收源数据在进行处理,但是这样子无法自适应各种数据的字段,所以使用父组件去进行处理,处理完成在传给子组件
示例:
:SelectData="CustomerIDData"
this.CustomerIDData = CustomerID.data.map((item) => {
return {
value : item.CustomerID.toString() , label : item.CustomerID.toString()}
})
还有一个点需要注意,这个方法需要转为字符串格式,所以需要toString()
3.multiple(默认为true):是否多选
示例:
:Ifmultiple=false
4.clearable(默认为false):是否可清空
注意该属性仅适用于单选
示例:
:Ifmultiple=true
-->
<template>
<div class="RangeSearch">
<el-select
v-model="employeesData.transshipmentdepot"
filterable
remote
reserve-keyword
:multiple=Ifmultiple
:clearable=Isclearable
:placeholder="$t(placeholder)"
:remote-method="transshipmentdepotremoteMethod"
:focus="transshipmentdepotremoteMethod"
:loading="loading"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</template>
<script>
export default {
data(){
return{
options: [],
value: [],
list: [],
loading: false,
employeesData:{
transshipmentdepot:'',
},
data:[], //暂存下拉数据,用于当输入为空时显示
multipleSelection:'', //是否多选
}
},
props:{
placeholder:{
default(){
return [];
}
},
SelectData:{
default(){
return [];
}
},
Ifmultiple:{
type: Boolean,
default: true
},
Isclearable:{
type: Boolean,
default: false
},
},
methods:{
transshipmentdepotremoteMethod(query) {
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
this.options = this.list.filter(item => {
return item.label.toLowerCase()
.indexOf(query.toLowerCase()) > -1;
});
}, 200);
} else {
this.options = this.data
}
}
},
mounted(){
},
watch:{
SelectData:function(newVal){
this.options = newVal
this.data = newVal
this.list = newVal
}
},
}
</script>
<style>
</style>
Para habilitar a pesquisa remota, e precisa ser
filterable
definidoremote
como verdadeiro, ao passar um arquivoremote-method
.remote-method
Por um ladoFunction
, ele será chamado quando o valor de entrada for alterado e o parâmetro for o valor de entrada atual. Deve-se observar que, seel-option
for renderizado por meio do comando v-for,el-option
o atributo chave precisa ser adicionado neste momento e seu valor deve ser exclusivo.
filtrável : se é pesquisável
remoto : se é pesquisável remoto
reserva-palavra-chave : quando seleção múltipla e pesquisável, se deve manter a palavra-chave de pesquisa atual após selecionar uma opção
múltiplo : se seleção múltipla pode ser
apagado : se a opção pode ser limpa
espaço reservado : contabilizado para Bit
remote-method : método de pesquisa remota
focus : dispara quando a entrada obtém o foco
loading : se os dados estão sendo buscados remotamente
Os itens acima são explicados em documentos oficiais, então não vou explicá-los em detalhes. Vou falar principalmente sobre minhas ideias de embalagens aqui.
placeholder: placeholder
Eu sou "$t(placeholder)" aqui, porque eu uso a gramática de alternar entre chinês e inglês, você pode diretamente "placeholder")
SelectData : Os dados na caixa suspensa
devem ser passados. SelectData aqui representa os dados que foram processados e renderizados diretamente na lista suspensa. Simplificando, são os dados que precisamos renderizar. Quanto a como a fonte os dados se tornam os dados que precisamos renderizar A operação é feita quando esse componente é chamado (o componente pai), onde apenas os dados são renderizados em vez de processar os dados para renderizar os dados.
Por que você quer fazer isso, porque pode ser usado em muitos lugares, seus dados de origem são diferentes e os campos que precisam ser renderizados também são diferentes. Por exemplo, eu renderizo o ID do cliente aqui e posso renderize o ID do warehouse em outros lugaresitem.CustomerID
.item.WarehouseID
, dessa forma, se você permitir que o componente manipule os dados de origem.
Ao retornaritem.CustomerID.toString()
,item.CustomerID.toString()
haverá um problema aqui, pois é o nome do campo ID que eu preciso ao renderizar o ID do cliente, então não posso adaptarCustomerID
quando quiser renderizar o warehouse. Ou seja , é difícil- codificado aqui, porque é completamente não sei quais são os campos dos dados de origem. Se processarmos diretamente os dados de origem ao chamar o componente, os dados passados estão todos em um formato unificado e todos os campos unificados podem ser usado para atingir o objetivo de uso, mas neste caso, o custo de uso será um pouco mais alto, mas não consigo pensar em um método de implementação melhor no momento e se houver um método de implementação melhor no futuro , vou compartilhar. Depois de obtê-lo aqui , use o ouvinte do relógio para monitorar as alterações de dados e atribua os dados recebidos mais recentes às opções do componente: dados de dados da lista suspensa : esses dados são criados por mim, o objetivo é clicar no início ou quando a entrada está vazia, o Elemento A melhor maneira é atribuir o valor a vazio, mas eu quero exibir todos os dados quando estiver vazio, então um dado é criado aqui e quando os dados de entrada estiverem vazios, os dados são passados para, e eu alcancei meu propósito desejado .WarehouseID
item.CustomerID.toString()
SelectData
options
options
lista : dados da lista suspensa processados
2. Use na página
<template>
<div>
<RangeSearch
:placeholder="'Please_enter_User_Stock'"
:SelectData="this.warehouseData"
:multiple=false
:clearable=false
></RangeSearch>
</div>
</template>
<script>
import RangeSearch from '@/components/RangeSearch.vue'
mounted(){
this.warehouseData = warehouse.data.map((item) => {
return {
value : item.StockID , label : item.Name}
})
}
</script>
- espaço reservado (matriz vazia por padrão): espaço reservado
//使用示例:
:placeholder="'Please_enter_customer_ID'"
Como os requisitos dos componentes são diferentes, os placeholders também são diferentes, passando os dados ao utilizá-los na página placeholder
, é possível ter placeholders diferentes para o mesmo componente.
- SelectData (obrigatório): dados da caixa suspensa
//使用示例:
:SelectData="CustomerIDData"
this.CustomerIDData = CustomerID.data.map((item) => {
return {
value : item.CustomerID.toString() , label : item.CustomerID.toString()}
})
Existe uma lógica importante aqui. Originalmente, esses dados são processados pelo subcomponente que recebe os dados de origem, mas dessa forma eles não podem se adaptar aos campos de vários dados, então o componente pai é usado para processamento e o processamento é concluído e passado para o subcomponente
Há outro ponto aqui que precisa ser observado toString()
, pois o componente elemento suporta apenas o formato de conversão caractere a caractere, e ocorrerá um erro quando um array ou objeto for passado, então aqui vai uma sugestão toSring()
.
this.CustomerIDData
: Dados que precisam ser renderizados
CustomerID.data
: Dados de origem
:SelectData="CustomerIDData"
: Observe que a posição onde isso é colocado é escrita no local onde este componente é usado, e o restante é mounted
escrito na função de ciclo de vida do componente pai.
- múltiplo (o padrão é verdadeiro): se deseja selecionar múltiplos
//使用示例:
:Ifmultiple=false
Isso é muito simples de entender se é de múltipla escolha (Verdadeiro: Sim, Falso: Não)
- limpável (o padrão é false): se pode ser zerado
//使用示例:
:Ifmultiple=tr
Isso também é fácil de entender se ele pode ser esvaziado (Verdadeiro: Sim, Falso: Não),
mas deve-se observar que esse atributo só é aplicável à seleção única