# d-select 分页选择框

# 何时使用


扩展 a-select 组件,又一定的局限性,如果只是使用普通的,建议使用 a-select

# 代码演示

基本

支持大多数 a-selectAPI 属性,

mode 为 tags 并 手动输入添加的 未支持

常规功能大多支持

显示代码
<template>
  <div class="demo-main">
    <label for="">基本使用-value: {{form.basicValue}}</label>
    <d-select
      v-model="form.basicValue"
      :options="options"
      placeholder="请选择"
    />
    <label for="">基本使用-value-multiple: {{form.basicValue1}}</label>
    <d-select
      v-model="form.basicValue1"
      :options="options"
      placeholder="请选择"
      mode="multiple"
    />
    <label for="">基本使用-value-groups: {{form.basicValue2}}</label>
    <d-select
      v-model="form.basicValue2"
      :groups="groups"
      placeholder="请选择"
    />
    <label for="">基本使用-labelInValue: {{form.basicValue3}}</label>
    <d-select
      v-model="form.basicValue3"
      :options="options"
      placeholder="请选择"
      labelInValue
    />
  </div>
</template>
<script>
import region from "../../../http/json/region.json";
export default {
  data() {
    return {
      options: region.data[0].children, // 假数据格式,忽略写法
      groups: [
        {
          label: region.data[0].label,
          key: region.data[0].value,
          options: region.data[0].children,
        },
      ],
      form: {},
    };
  },
  methods: {},
};
</script>
<style scoped>
.demo-main {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
</style>
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
53
54
55
56
显示代码
回填到选择框的 Option 的属性值-optionLabelProp

默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 value。

显示代码
<template>
  <div class="demo-main">
    <label for="">optionLabelProp 默认: {{ form.basicValue }}</label>
    <d-select v-model="form.basicValue" :options="options" placeholder="请选择">
      <template #children="{ option }">
        {{ option.label }}({{ option.value }})
      </template>
    </d-select>
    <d-select
      v-model="form.basicValue"
      :options="options"
      placeholder="请选择"
      optionLabelProp="label"
    >
      <template #children="{ option }">
        {{ option.label }}({{ option.value }})
      </template>
    </d-select>
    <d-select
      v-model="form.basicValue"
      :options="options"
      placeholder="请选择"
      optionLabelProp="value"
    >
      <template #children="{ option }">
        {{ option.label }}({{ option.value }})
      </template>
    </d-select>
  </div>
</template>
<script>
import region from "../../../http/json/region.json";
export default {
  data() {
    return {
      options: region.data[0].children, // 假数据格式,忽略写法
      form: {
        basicValue: '320300'
      },
    };
  },
  methods: {},
};
</script>
<style scoped>
.demo-main {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
</style>
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
显示代码
分页-pagination-动态加载

完整的例子

远程搜索建议使用 labelInValue 模式,编辑回显 value 值 找不到 回显效果不好

显示代码
<template>
  <div class="demo-main">
    <d-select
      v-model="form.loadRemote1"
      placeholder="请选择"
      :options="filterOptions"
      showSearch
      pageType="paginationRemote"
      :total="total"
      optionFilterProp="label"
      :searchLoading="searchLoading"
      @search="onSearch"
      @focus="onFocus"
      @pagChange="pagChange"
    >
    </d-select>
  </div>
</template>
<script>
import region from "../../../http/json/region.json";
export default {
  data() {
    return {
      allRegion: region.data[0].children, // 假数据格式,忽略写法
      searchLoading: false,
      total: 0,
      inputValue: "", // 需要搜索的关键字
      filterOptions: [],
      pag: {
        current: 1,
        pageSize: 10,
        showTotal: (total) => `${total}`,
      },
      form: {},
      timer: null,
    };
  },
  beforeDestroy() {
    this.timer && clearTimeout(this.timer);
  },
  methods: {
    async onFocus() {
      if (this.filterOptions.length) return;
      this.onSearch("");
    },
    async pagChange(current, pageSize) {
      console.log(current, pageSize)
      if (this.searchLoading) return;
      this.searchLoading = true;
      const result = await this.queryData({
        pageSize,
        current,
      });
      this.handleResult(result);
    },
    async onSearch(v) {
      if (v === this.inputValue && this.filterOptions.length) return;
      // 查询的时候需要重置一些变量
      this.total = 0;
      this.filterOptions = [];
      this.inputValue = v;
      this.searchLoading = true;
      // 节流
      this.timer && clearTimeout(this.timer);
      this.timer = setTimeout(async () => {
        const result = await this.queryData({
          pageSize: this.pag.pageSize,
          current: 1,
        });
        this.handleResult(result);
      }, 500);
    },
    handleResult(result) {
      this.filterOptions = result.data || []
      this.pag.current = result.current || 1;
      this.total = result.total || 0;
    },
    delay(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    },
    /**
     * 下面是模拟接口返回数据,可忽略
     */
    async queryData(param) {
      const { current, pageSize } = param;
      const inputValue = this.inputValue;

      /**   模拟接口  ---------start---------- */
      // 下面相当于一个后台接口
      await this.delay(1000);
      const start = (current - 1) * pageSize;
      const end = current * pageSize;
      const _all = inputValue
        ? this.allRegion.filter((v) => v.label.indexOf(inputValue) !== -1)
        : this.allRegion;
      const _optionArr = _all.slice(start, end);
      /**   模拟接口  ---------end---------- */
      this.searchLoading = false;
      return {
        data: _optionArr,
        current: current,
        total: _all.length,
      };
    },
  },
};
</script>
<style scoped>
.demo-main {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
</style>
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
显示代码
上滑分页

完整的例子

远程搜索建议使用 labelInValue 模式,编辑回显 value 值 找不到 回显效果不好

显示代码
<template>
  <div class="demo-main">
    <label for="">基本版</label>
    <d-select
      v-model="form.loadValue"
      placeholder="请选择"
      :options="allRegion"
      showSearch
      optionFilterProp="label"
      pageType="scroll"
      :pag="{
        current: 1,
        pageSize: 10,
      }"
    >
    </d-select>
    <label for="">远程搜索</label>
    <d-select
      v-model="form.loadRemote"
      placeholder="请选择"
      :options="filterOptions"
      showSearch
      optionFilterProp="label"
      pageType="scroll"
      :total="total"
      :loadData="loadData"
      :searchLoading="searchLoading"
      @search="search"
      @focus="onFocus"
    >
    </d-select>
  </div>
</template>
<script>
import region from "../../../http/json/region.json";
export default {
  data() {
    return {
      allRegion: region.data[0].children, // 假数据格式,忽略写法
      searchLoading: false,
      total: 0,
      inputValue: "", // 需要搜索的关键字
      filterOptions: [],
      filterOptions1: [],
      pag: {
        current: 1,
        pageSize: 10,
        showTotal: (total) => `${total}`,
      },
      form: {},
      timer: null,
    };
  },
  created() {},
  beforeDestroy() {
    this.timer && clearTimeout(this.timer);
  },
  methods: {
    async onFocus() {
      if (this.filterOptions.length) return;
      this.search("");
    },
    search(v) {
      /** 初始重置 */
      this.total = 0;
      this.filterOptions = [];
      this.inputValue = v;
      // 节流
      this.timer && clearTimeout(this.timer);
      this.searchLoading = true;
      this.timer = setTimeout(async () => {
        const result = await this.queryData({
          pageSize: this.pag.pageSize,
          current: 1,
        });
        this.searchLoading = false;
        this.handleResult(result);
      }, 400);
    },
    handleResult(result) {
      this.filterOptions.push(...(result.data || []));
      this.pag.current = result.current || 1;
      this.total = result.total || 0;
    },
    delay(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    },
    async loadData(e) {
      if (this.loading) return;
      if (this.total <= this.filterOptions.length) return;
      // 下面相当于一个后台接口
      this.loading = true; // 这里相当于节流的作用,免得获取同样数据进行追加
      const _resut = await this.queryData({
        pageSize: this.pag.pageSize,
        current: this.pag.current + 1,
      });
      this.loading = false;
      this.handleResult(_resut);
    },
    /**
     * 下面是模拟接口返回数据,可忽略
     */
    async queryData(param) {
      /**   模拟接口  ---------start---------- */
      const { current, pageSize } = param;
      const inputValue = this.inputValue;
      // 下面相当于一个后台接口
      await this.delay(1000);
      const start = (current - 1) * pageSize;
      const end = current * pageSize;
      const _all = inputValue
        ? this.allRegion.filter((v) => v.label.indexOf(inputValue) !== -1)
        : this.allRegion;
      const _optionArr = _all.slice(start, end);
      /**   模拟接口  ---------end---------- */
      return {
        data: _optionArr,
        current: current,
        total: _all.length,
      };
    },
  },
};
</script>
<style scoped>
.demo-main {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
</style>
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
显示代码
分页-pagination

默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 value。

远程搜索建议使用 labelInValue 模式,编辑回显 value 值 找不到 回显效果不好

显示代码
<template>
  <div class="demo-main">
    <label for="">简单模式</label>
    <d-select
      v-model="form.basicValue"
      placeholder="请选择"
      :options="allRegion"
      pageType="pagination"
    />
    <label for="">group(仅支持groups的组数)</label>
    <d-select
      v-model="form.basicValue"
      placeholder="请选择"
      :groups="groups"
      pageType="pagination"
      :pag="{
        current: 1,
        pageSize: 10,
        showTotal: (total) => `共 ${total} 组`,
      }"
    />
    <label for="">分页pagination(远程搜索) - 简单版</label>
    <d-select
      v-model="form.loadRemote"
      placeholder="请选择"
      :options="filterOptions"
      pageType="paginationRemote"
      :total="total"
      :searchLoading="searchLoading"
      @pagChange="pagChange"
      @focus="onFocus"
    >
    </d-select>
  </div>
</template>
<script>
import region from "../../../http/json/region.json";
export default {
  data() {
    return {
      allRegion: region.data[0].children, // 假数据格式,忽略写法
      searchLoading: false,
      total: 0,
      inputValue: "", // 需要搜索的关键字
      filterOptions: [],
      filterOptions1: [],
      pag: {
        current: 1,
        pageSize: 10,
        showTotal: (total) => `${total}`,
      },
      groups: [
        {
          label: region.data[0].label,
          key: region.data[0].value,
          options: region.data[0].children,
        },
      ],
      form: {},
    };
  },
  created() {},
  methods: {
    onFocus() {
      if (this.filterOptions.length) return;
      this.pagChange(this.pag.current, this.pag.pageSize);
    },
    async pagChange(current, pageSize) {
      const result = await this.queryData({
        current,
        pageSize,
      });
        console.log(result, 'result')
      this.filterOptions = result.data || [];
      this.pag.current = result.current || 1;
      this.total = result.total || 0;
    },
    delay(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    },
    async queryData(param) {
      if (this.searchLoading) return;
      const { current, pageSize } = param;
      const inputValue = this.inputValue;
      this.searchLoading = true;
      /**   模拟接口  ---------start---------- */
      // 下面相当于一个后台接口
      await this.delay(1000);
      const start = (current - 1) * pageSize;
      const end = current * pageSize;
      const _all = inputValue
        ? this.allRegion.filter((v) => v.label.indexOf(inputValue) !== -1)
        : this.allRegion;
      const _optionArr = _all.slice(start, end);
      /**   模拟接口  ---------end---------- */
      this.searchLoading = false;
      return {
        data: _optionArr,
        current: current,
        total: _all.length,
      };
    },
  },
};
</script>
<style scoped>
.demo-main {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
</style>
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
显示代码

# API

# Select props

继承 a-select 大多数的属性 a-select (opens new window)

# Select events

a-select 有细微差别, 其他事件皆继承了!详情请查看 a-select 文档

# Select Methods

继承 a-select 的方法