vue3笔记(17-2)el-select组件封装

本篇接上一篇,将el-select封装成组件

子组件

使用 filter-method 进行前端本地搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<el-select
v-model="selectedArr"
multiple
filterable
:filter-method="dataFilter"
default-first-option
:placeholder="text"
>
<el-option v-for="item in optionList" :key="item.id" :label="item.name" :value="item.name" />
<div
v-if="query.p * query.pageSize < optionTotal && showLoadMore"
@click="loadmore"
class="load-more"
>
点击加载更多
</div>
</el-select>
</template>

text 表示输入框默认提示;optionAll 代表列表所有可选项,为了和业务解耦,从父组件中获取;optionTotal表示所有可选项的数量,如果父组件直接从接口获取到值,则直接传递给子组件。
这里要注意的是:

  1. vue3 setup 使用 defineEmits 语法糖,需要先注册再引用;
  2. v-model是一个语法糖,等于:value+@input,所以这里使用 emit(‘input’) 来实现数据双向绑定;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    const props = defineProps<{
    text: string
    optionAll: Array<any>
    optionTotal?: number
    }>()

    const state = reactive({
    optionList: [],
    showLoadMore: true,
    selectedArr: [],
    query: { p: 1, pageSize: 10 }
    })
    const { optionList, showLoadMore, selectedArr, query } = toRefs(state)

    const emit = defineEmits(['input'])
    watch(state.selectedArr, (val) => {
    emit('input', val)
    })

    const loadmore = () => {
    state.query.p++
    getItems() //类似于分页查询
    }

    onMounted(() => {
    getItems(1)
    })
    const dataFilter = (val) => {
    if (val) {
    state.optionList = props.optionAll.filter((item) => {
    if (item && !!~item.name.indexOf(val)) {
    return true
    }
    })
    showLoadMore.value = false
    } else {
    getItems(1)
    showLoadMore.value = true
    }
    }

    const getItems = (flag?: number) => {
    if (flag) {
    state.query.p = flag
    }
    let num = ~~state.query.p * ~~state.query.pageSize
    state.optionList = props.optionAll.filter((item, index, arr) => {
    if (item) {
    return index < num
    }
    })
    }

    父组件调用

1
2
3
4
5
6
<tree-select
v-model="roleForm.users"
text="请选择包含的用户"
:optionAll="userListAll"
:optionTotal="userTotal"
></tree-select>