yj-kikimore 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +489 -0
- package/package.json +99 -0
- package/src/FormDialog/elementIsVisible.ts +7 -0
- package/src/FormDialog/highlightError.scss +85 -0
- package/src/FormDialog/highlightError.ts +84 -0
- package/src/FormDialog/index.vue +932 -0
- package/src/PopButton/index.vue +168 -0
- package/src/PopSwitch/index.vue +271 -0
- package/src/PopSwitch/utils.ts +9 -0
- package/src/Select/index.vue +480 -0
- package/src/index.ts +6 -0
- package/src/src/FormDialog/elementIsVisible.d.ts +2 -0
- package/src/src/FormDialog/highlightError.d.ts +2 -0
- package/src/src/PopSwitch/utils.d.ts +1 -0
- package/src/src/index.d.ts +5 -0
- package/src/src/utils.d.ts +8 -0
- package/src/utils.ts +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-present Cloyd Lau
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
<h1 align="center">yj-Kikimore</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img height="28px" src="https://user-images.githubusercontent.com/10731096/95823103-9ce15780-0d5f-11eb-8010-1bd1b5910d4f.png">
|
|
5
|
+
|
|
6
|
+
<img height="28px" src="https://cdn.rawgit.com/ElemeFE/element/dev/element_logo.svg">
|
|
7
|
+
<br>
|
|
8
|
+
几个 Element Plus / Element 组件的封装。
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<br>
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
npm i kikimore
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Vite
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// vite.config.ts
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
optimizeDeps: {
|
|
26
|
+
include: ['kikimore'],
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- Vue CLI
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
// vue.config.js
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
transpileDependencies: ['kikimore'],
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
<br>
|
|
42
|
+
|
|
43
|
+
### Element Plus (Vue 3)
|
|
44
|
+
|
|
45
|
+
#### 局部注册
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<script setup>
|
|
49
|
+
import { KiFormDialog, KiPopButton, KiPopSwitch, KiSelect } from 'kikimore'
|
|
50
|
+
</script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### 全局注册
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { KiFormDialog, KiPopButton, KiPopSwitch, KiSelect } from 'kikimore'
|
|
57
|
+
|
|
58
|
+
app
|
|
59
|
+
.use(KiFormDialog, {
|
|
60
|
+
// 全局配置
|
|
61
|
+
})
|
|
62
|
+
.use(KiPopButton, {
|
|
63
|
+
// 全局配置
|
|
64
|
+
})
|
|
65
|
+
.use(KiPopSwitch, {
|
|
66
|
+
// 全局配置
|
|
67
|
+
})
|
|
68
|
+
.use(KiSelect, {
|
|
69
|
+
// 全局配置
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### ~~CDN~~
|
|
74
|
+
|
|
75
|
+
⚠ 暂不支持。
|
|
76
|
+
|
|
77
|
+
<br>
|
|
78
|
+
|
|
79
|
+
### Element (Vue 2)
|
|
80
|
+
|
|
81
|
+
#### 局部注册
|
|
82
|
+
|
|
83
|
+
```vue
|
|
84
|
+
<script>
|
|
85
|
+
import { KiFormDialog, KiPopButton, KiPopSwitch, KiSelect } from 'kikimore'
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
components: { KiFormDialog, KiPopButton, KiPopSwitch, KiSelect },
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### 全局注册
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import Vue from 'vue'
|
|
97
|
+
import { KiFormDialog, KiPopButton, KiPopSwitch, KiSelect } from 'kikimore'
|
|
98
|
+
|
|
99
|
+
Vue.use(FormDialog, {
|
|
100
|
+
// 全局配置
|
|
101
|
+
})
|
|
102
|
+
Vue.use(KiPopButton, {
|
|
103
|
+
// 全局配置
|
|
104
|
+
})
|
|
105
|
+
Vue.use(KiPopSwitch, {
|
|
106
|
+
// 全局配置
|
|
107
|
+
})
|
|
108
|
+
Vue.use(KiSelect, {
|
|
109
|
+
// 全局配置
|
|
110
|
+
})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### ~~CDN~~
|
|
114
|
+
|
|
115
|
+
⚠ 暂不支持。
|
|
116
|
+
|
|
117
|
+
<br>
|
|
118
|
+
|
|
119
|
+
## FormDialog
|
|
120
|
+
|
|
121
|
+
[el-dialog](https://element.eleme.cn/#/zh-CN/component/dialog) + [el-form](https://element.eleme.cn/#/zh-CN/component/form) 组合拳。
|
|
122
|
+
|
|
123
|
+
### 特性
|
|
124
|
+
|
|
125
|
+
- 打开对话框自动回显数据,关闭对话框自动重置数据
|
|
126
|
+
- 提交、拒绝、重置、全屏一应俱全
|
|
127
|
+
- 校验失败时平滑滚动至错误项并震动提示
|
|
128
|
+
- 限制高度,无页面级滚动条
|
|
129
|
+
- 只读模式
|
|
130
|
+
- 支持全局属性、全局事件、全局插槽 ([vue-global-config](https://github.com/cloydlau/vue-global-config) 提供技术支持)
|
|
131
|
+
|
|
132
|
+
### 属性
|
|
133
|
+
|
|
134
|
+
| 名称 | 说明 | 类型 | 默认值 |
|
|
135
|
+
| ----------------------------------------------- | ----------------------------------- | -------- | ----------- |
|
|
136
|
+
| title | 对话框标题 | string | |
|
|
137
|
+
| v-model:show (Vue 3) /<br>show.sync (Vue 2) | 是否显示 | boolean | `false` |
|
|
138
|
+
| modelValue (Vue 3) /<br>value (Vue 2) / v-model | 表单数据对象 (`el-form` 的 `model`) | any | |
|
|
139
|
+
| elFormProps | `el-form` 的属性 | object | |
|
|
140
|
+
| retrieve | 读取数据 | Function | |
|
|
141
|
+
| loading | 读取状态 | boolean | `false` |
|
|
142
|
+
| readonly | 是否只读 | boolean | `false` |
|
|
143
|
+
| showFullscreenToggle | 是否显示全屏开关 | boolean | `true` |
|
|
144
|
+
| showConfirmButton | 是否显示确认按钮 | boolean | `!readonly` |
|
|
145
|
+
| confirmButtonText | 确认按钮的文案 | string | `'OK'` |
|
|
146
|
+
| confirm | 确认 | Function | |
|
|
147
|
+
| showCancelButton | 是否显示取消按钮 | boolean | `!readonly` |
|
|
148
|
+
| cancelButtonText | 取消按钮的文案 | string | `'Cancel'` |
|
|
149
|
+
| showDenyButton | 是否显示拒绝按钮 | boolean | `false` |
|
|
150
|
+
| denyButtonText | 拒绝按钮的文案 | string | `'No'` |
|
|
151
|
+
| deny | 拒绝 | Function | |
|
|
152
|
+
| showResetButton | 是否显示重置按钮 | boolean | `false` |
|
|
153
|
+
| resetButtonText | 重置按钮的文案 | string | `'Reset'` |
|
|
154
|
+
| reverseButtons | 是否反转按钮顺序 | boolean | `false` |
|
|
155
|
+
| ... | `el-dialog` 的属性 | | |
|
|
156
|
+
|
|
157
|
+
### 事件
|
|
158
|
+
|
|
159
|
+
| 名称 | 说明 | 参数 |
|
|
160
|
+
| ---------------------------------- | ----------------------------------- | --- |
|
|
161
|
+
| validateCatch | 表单校验失败时触发 | 同element表单 校验失败时的参数 |
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
#### modelValue (Vue 3) / value (Vue 2) / v-model
|
|
165
|
+
|
|
166
|
+
如果是 plain object 类型,将用于 `el-form` 的 `model`。
|
|
167
|
+
|
|
168
|
+
`onMounted` 时记录初始值 (与 `el-form-item` 保持一致),关闭对话框时会重置至初始值。
|
|
169
|
+
|
|
170
|
+
#### retrieve
|
|
171
|
+
|
|
172
|
+
```vue
|
|
173
|
+
<template>
|
|
174
|
+
<KiFormDialog
|
|
175
|
+
:retrieve="() => {
|
|
176
|
+
// 表格打开之后、获取数据之前
|
|
177
|
+
$POST('xxx').then(() => {
|
|
178
|
+
// 获取数据之后
|
|
179
|
+
})
|
|
180
|
+
}"
|
|
181
|
+
/>
|
|
182
|
+
</template>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### readonly
|
|
186
|
+
|
|
187
|
+
开启只读模式时默认不显示确认和取消按钮。
|
|
188
|
+
|
|
189
|
+
跟 `<el-form disabled />` 的区别是在样式上,更便于用户阅读。
|
|
190
|
+
|
|
191
|
+
如果希望部分组件不进入禁用状态:
|
|
192
|
+
|
|
193
|
+
- 单独给这个组件设置 `:disabled="false"`
|
|
194
|
+
- 给这部分组件包一层 `<el-form />`
|
|
195
|
+
|
|
196
|
+
#### confirm
|
|
197
|
+
|
|
198
|
+
如果返回一个 Promise 实例,则在该 Promise 实例状态终结后对话框才会关闭。
|
|
199
|
+
|
|
200
|
+
```vue
|
|
201
|
+
<template>
|
|
202
|
+
<KiFormDialog
|
|
203
|
+
:confirm="() => {
|
|
204
|
+
// 确认之前
|
|
205
|
+
$POST('xxx').then(() => {
|
|
206
|
+
// 确认之后
|
|
207
|
+
})
|
|
208
|
+
}"
|
|
209
|
+
/>
|
|
210
|
+
</template>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
返回 `Promise.reject()` / `Promise.resolve({ show: true })` / `{ show: true }` 时对话框不会关闭。
|
|
214
|
+
|
|
215
|
+
```vue
|
|
216
|
+
<template>
|
|
217
|
+
<KiFormDialog
|
|
218
|
+
:confirm="() => {
|
|
219
|
+
const valid = true
|
|
220
|
+
if (valid) {
|
|
221
|
+
return $POST('xxx')
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
$swal.warning('校验失败')
|
|
225
|
+
return {
|
|
226
|
+
show: true,
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}"
|
|
230
|
+
/>
|
|
231
|
+
</template>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
#### deny
|
|
235
|
+
|
|
236
|
+
如果返回一个 Promise 实例,则在该 Promise 实例状态终结后对话框才会关闭。
|
|
237
|
+
|
|
238
|
+
```vue
|
|
239
|
+
<template>
|
|
240
|
+
<KiFormDialog
|
|
241
|
+
:deny="() => {
|
|
242
|
+
// 确认之前
|
|
243
|
+
$POST('xxx').then(() => {
|
|
244
|
+
// 确认之后
|
|
245
|
+
})
|
|
246
|
+
}"
|
|
247
|
+
/>
|
|
248
|
+
</template>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
返回 `Promise.reject()` / `Promise.resolve({ show: true })` / `{ show: true }` 时对话框不会关闭。
|
|
252
|
+
|
|
253
|
+
```vue
|
|
254
|
+
<template>
|
|
255
|
+
<KiFormDialog
|
|
256
|
+
:deny="() => {
|
|
257
|
+
const valid = true
|
|
258
|
+
if (valid) {
|
|
259
|
+
return $POST('xxx')
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
$swal.warning('校验失败')
|
|
263
|
+
return {
|
|
264
|
+
show: true,
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}"
|
|
268
|
+
/>
|
|
269
|
+
</template>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### reverseButtons
|
|
273
|
+
|
|
274
|
+
关于 “确定” 和 “取消” 按钮的顺序,可以看看这篇[知乎回答](https://www.zhihu.com/question/20694680/answer/1400624833)。
|
|
275
|
+
|
|
276
|
+
### 方法
|
|
277
|
+
|
|
278
|
+
| 名称 | 说明 | 类型 |
|
|
279
|
+
| -------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------- |
|
|
280
|
+
| highlightError | 平滑滚动至校验失败的表单项 | (selectors: string \| Element \| NodeList = '.el-form .el-form-item.is-error', container = window) => void |
|
|
281
|
+
| ... | 通过 ref 调用 `el-form` 的方法 | |
|
|
282
|
+
|
|
283
|
+
### 事件
|
|
284
|
+
|
|
285
|
+
| 名称 | 说明 | 回调参数 |
|
|
286
|
+
| ----------------- | ----------------------------- | --------------------- |
|
|
287
|
+
| fullscreen-change | 切换全屏状态时触发 | (fullscreen: boolean) |
|
|
288
|
+
| ... | `el-dialog`、`el-form` 的事件 | |
|
|
289
|
+
|
|
290
|
+
### 插槽
|
|
291
|
+
|
|
292
|
+
| 名称 | 说明 |
|
|
293
|
+
| ---- | ------------------ |
|
|
294
|
+
| — | `el-form` 的内容 |
|
|
295
|
+
| ... | `el-dialog` 的插槽 |
|
|
296
|
+
|
|
297
|
+
### 改变遮罩层定位
|
|
298
|
+
|
|
299
|
+
```scss
|
|
300
|
+
.el-dialog__wrapper, .v-modal {
|
|
301
|
+
position: absolute;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// 在原来的基础上减去 navbar + tab 的高度 (以 90px 为例)
|
|
305
|
+
.el-dialog {
|
|
306
|
+
.el-dialog__body {
|
|
307
|
+
max-height: calc(100vh - 190px) !important;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
&.is-fullscreen .el-dialog__body {
|
|
311
|
+
max-height: calc(100vh - 135px) !important;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
<br>
|
|
317
|
+
|
|
318
|
+
## PopButton
|
|
319
|
+
|
|
320
|
+
`el-button` + `el-popconfirm` + `el-popover` + `el-tooltip` 组合拳。
|
|
321
|
+
|
|
322
|
+
### 特性
|
|
323
|
+
|
|
324
|
+
- 操作拦截 (`el-popconfirm` 点击确定后才会触发 `click` 事件)
|
|
325
|
+
- `el-popover` 和 `el-tooltip` 的 `content` 属性均支持渲染 HTML
|
|
326
|
+
- `el-tooltip` 不与 `el-popconfirm`、`el-popover` 冲突
|
|
327
|
+
- `el-popconfirm`、`el-popover`、`el-tooltip` 内容为空时,默认不启用
|
|
328
|
+
- 支持全局属性、全局事件、全局插槽 ([vue-global-config](https://github.com/cloydlau/vue-global-config) 提供技术支持)
|
|
329
|
+
|
|
330
|
+
### 属性
|
|
331
|
+
|
|
332
|
+
| 名称 | 说明 | 类型 | 默认值 |
|
|
333
|
+
| --------------------------- | ------------------------------------------ | ------- | ------- |
|
|
334
|
+
| elPopconfirmProps | `el-popconfirm` 的属性 | object | |
|
|
335
|
+
| elPopoverProps | `el-popover` 的属性,支持事件绑定 | object | |
|
|
336
|
+
| `elPopoverProps.rawContent` | `content` 中的内容是否作为 HTML 字符串处理 | boolean | `false` |
|
|
337
|
+
| elTooltipProps | `el-tooltip` 的属性 | object | |
|
|
338
|
+
| `elTooltipProps.rawContent` | `content` 中的内容是否作为 HTML 字符串处理 | boolean | `false` |
|
|
339
|
+
| ... | `el-button` 的属性 | | |
|
|
340
|
+
|
|
341
|
+
### 事件
|
|
342
|
+
|
|
343
|
+
`el-popconfirm`、`el-popover` 的事件。
|
|
344
|
+
|
|
345
|
+
### 插槽
|
|
346
|
+
|
|
347
|
+
| 名称 | 说明 |
|
|
348
|
+
| --------------- | ------------------------------ |
|
|
349
|
+
| tooltip-content | `el-tooltip` 的 `content` 插槽 |
|
|
350
|
+
| popover-content | `el-popover` 的 `content` 插槽 |
|
|
351
|
+
|
|
352
|
+
<br>
|
|
353
|
+
|
|
354
|
+
## PopSwitch
|
|
355
|
+
|
|
356
|
+
`el-switch` + `el-popconfirm` + `el-popover` + `el-tooltip` 组合拳。
|
|
357
|
+
|
|
358
|
+
### 特性
|
|
359
|
+
|
|
360
|
+
- 操作拦截 (`el-popconfirm` 点击确定后才会触发 `change` 事件)
|
|
361
|
+
- 支持内嵌文字描述,宽度自适应
|
|
362
|
+
- `el-popover` 和 `el-tooltip` 的 `content` 属性均支持渲染 HTML
|
|
363
|
+
- `el-tooltip` 不与 `el-popconfirm`、`el-popover` 冲突
|
|
364
|
+
- `el-popconfirm`、`el-popover`、`el-tooltip` 内容为空时,默认不启用
|
|
365
|
+
- 支持全局属性、全局事件、全局插槽 ([vue-global-config](https://github.com/cloydlau/vue-global-config) 提供技术支持)
|
|
366
|
+
|
|
367
|
+
### 属性
|
|
368
|
+
|
|
369
|
+
| 名称 | 说明 | 类型 | 默认值 |
|
|
370
|
+
| --------------------------- | ------------------------------------------ | ------- | ------- |
|
|
371
|
+
| inlinePrompt | 是否内嵌文字描述 | boolean | `false` |
|
|
372
|
+
| elPopconfirmProps | `el-popconfirm` 的属性 | object | |
|
|
373
|
+
| elPopoverProps | `el-popover` 的属性,支持事件绑定 | object | |
|
|
374
|
+
| `elPopoverProps.rawContent` | `content` 中的内容是否作为 HTML 字符串处理 | boolean | `false` |
|
|
375
|
+
| elTooltipProps | `el-tooltip` 的属性 | object | |
|
|
376
|
+
| `elTooltipProps.rawContent` | `content` 中的内容是否作为 HTML 字符串处理 | boolean | `false` |
|
|
377
|
+
| ... | `el-switch` 的属性 | | |
|
|
378
|
+
|
|
379
|
+
### 方法
|
|
380
|
+
|
|
381
|
+
通过 ref 调用 `el-switch` 的方法。
|
|
382
|
+
|
|
383
|
+
### 事件
|
|
384
|
+
|
|
385
|
+
`el-switch`、`el-popconfirm`、`el-popover` 的事件。
|
|
386
|
+
|
|
387
|
+
### 插槽
|
|
388
|
+
|
|
389
|
+
| 名称 | 说明 |
|
|
390
|
+
| --------------- | ------------------------------ |
|
|
391
|
+
| tooltip-content | `el-tooltip` 的 `content` 插槽 |
|
|
392
|
+
| popover-content | `el-popover` 的 `content` 插槽 |
|
|
393
|
+
|
|
394
|
+
<br>
|
|
395
|
+
|
|
396
|
+
## Select
|
|
397
|
+
|
|
398
|
+
`el-select` + `el-option` + `el-option-group` 组合拳。
|
|
399
|
+
|
|
400
|
+
### 特性
|
|
401
|
+
|
|
402
|
+
- 单向绑定 `label`
|
|
403
|
+
- 远程搜索时无需关心 `options` 和 `loading`
|
|
404
|
+
- 无匹配选项时展示 `label` (而不是 `value`)
|
|
405
|
+
- 多选时支持一键全选
|
|
406
|
+
- 支持全局属性、全局事件、全局插槽、全局作用域插槽 ([vue-global-config](https://github.com/cloydlau/vue-global-config) 提供技术支持)
|
|
407
|
+
|
|
408
|
+
### 属性
|
|
409
|
+
|
|
410
|
+
| 名称 | 说明 | 类型 | 默认值 |
|
|
411
|
+
| ------------------------------------------------- | --------------------------------- | --------------------------------------------- | -------------- |
|
|
412
|
+
| modelValue (Vue 3) /<br>value (Vue 2) / v-model | 绑定值 | any | |
|
|
413
|
+
| v-model:options (Vue 3) /<br>options.sync (Vue 2) | 选项 | any[] | |
|
|
414
|
+
| props | 定位选项的各项属性 | object | |
|
|
415
|
+
| search | 远程搜索 (`remote-method` 封装) | (query: string) =><br>Promise<any[]> \| any[] | |
|
|
416
|
+
| searchImmediately | 是否立即执行远程搜索 | boolean | `true` |
|
|
417
|
+
| v-model:label (Vue 3) /<br>label.sync (Vue 2) | 绑定值对应的 `label` (单向数据流) | string \| string[] | |
|
|
418
|
+
| showSelectAllCheckbox | 多选时是否显示全选框 | boolean | `true` |
|
|
419
|
+
| selectAllCheckboxLabel | 全选框的文案 | string | `'Select All'` |
|
|
420
|
+
| ... | `el-select` 的属性 | | |
|
|
421
|
+
|
|
422
|
+
#### options
|
|
423
|
+
|
|
424
|
+
默认情况下绑定值将得到选中项的数组元素本身。
|
|
425
|
+
|
|
426
|
+
可使用 `props.value` 改变此行为 (比如选项的数组元素是 plain object 类型,而绑定值只想要其中某个属性)。
|
|
427
|
+
|
|
428
|
+
#### props
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
interface Props {
|
|
432
|
+
// 定位 option 中的 value
|
|
433
|
+
// 如果是 string 类型,将默认用于 el-select 的 value-key
|
|
434
|
+
'value': string | symbol | ((value: any) => any)
|
|
435
|
+
// 定位 option 中的 label
|
|
436
|
+
'label': string | symbol | ((value: any) => string)
|
|
437
|
+
// 定位 option 中的 disabled
|
|
438
|
+
'disabled': string | symbol | ((value: any) => boolean)
|
|
439
|
+
// 定位 option 中分组的 label
|
|
440
|
+
'groupLabel': string | symbol | ((value: any) => string)
|
|
441
|
+
// 定位 option 中分组的 options
|
|
442
|
+
'groupOptions': string | symbol | ((value: any) => any[])
|
|
443
|
+
// 定位 option 中分组的 disabled
|
|
444
|
+
'groupDisabled': string | symbol | ((value: any) => boolean)
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
- 支持属性名,如 `'url'`
|
|
449
|
+
- 支持属性路径,如 `'data[0].url'`
|
|
450
|
+
- 支持 symbol 类型的属性名
|
|
451
|
+
- 支持 Function,如 `value => value.url`
|
|
452
|
+
|
|
453
|
+
### 方法
|
|
454
|
+
|
|
455
|
+
| 名称 | 说明 | 类型 |
|
|
456
|
+
| ------------ | ---------------------------------------------------------------- | ----------------------- |
|
|
457
|
+
| remoteMethod | `el-select` 的 `remoteMethod` 属性,自行控制 `search` 时机时使用 | (query: string) => void |
|
|
458
|
+
| ... | 通过 ref 调用 `el-select` 的方法 | |
|
|
459
|
+
|
|
460
|
+
### 事件
|
|
461
|
+
|
|
462
|
+
`el-select` 的事件。
|
|
463
|
+
|
|
464
|
+
### 插槽
|
|
465
|
+
|
|
466
|
+
| 名称 | 说明 |
|
|
467
|
+
| -------------- | ------------------------------------------------------------------- |
|
|
468
|
+
| prefix | `el-select` 的 `prefix` 插槽 |
|
|
469
|
+
| empty | `el-select` 的 `empty` 插槽 |
|
|
470
|
+
| group-prepend | `el-option-group` 的前置内容 |
|
|
471
|
+
| group-append | `el-option-group` 的后置内容 |
|
|
472
|
+
| — | `el-option` 的默认插槽,作用域参数为 `{option: any, index: number}` |
|
|
473
|
+
| option-prepend | `el-option` 的前置内容,默认内容为全选框 |
|
|
474
|
+
| option-append | `el-option` 的后置内容 |
|
|
475
|
+
|
|
476
|
+
### 命名
|
|
477
|
+
|
|
478
|
+
关于 `value` 和 `label` 的命名:
|
|
479
|
+
|
|
480
|
+
- `value`:这里要表达的含义就是选中目标的 “值”,等同于原生 `<input type="checkbox">` 元素的 `value` 属性,不一定是其唯一标识,所以不应该使用 id 或者 key,且 key 与 Vue 的特殊 attribute 冲突。
|
|
481
|
+
|
|
482
|
+
- `label`:HTML 中 `<label>` 与 `<input>` 元素相关联,用于对后者进行说明,所以 `label` 天生是用来表达选中目标的 “展示名称” 的,而 ‘name’ 由于与原生 `<input>` 元素的 `name` 属性冲突故不考虑使用 ‘name’。
|
|
483
|
+
|
|
484
|
+
> Element 本身没有做到命名的统一,`el-select` 中 `label` 表示选项的标签,
|
|
485
|
+
> 但 `el-checkbox` 中 `label` 却表示的是选中状态的值。
|
|
486
|
+
|
|
487
|
+
UI 组件库的标杆 Ant Design 也是使用 `value` 与 `label` 命名。
|
|
488
|
+
|
|
489
|
+
<br>
|
package/package.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "yj-kikimore",
|
|
3
|
+
"PascalCasedName": "YjKikimore",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"private": false,
|
|
6
|
+
"packageManager": "pnpm@7.25.0",
|
|
7
|
+
"description": "Several components wrapper for Element Plus / Element.",
|
|
8
|
+
"author": "yunjing",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"vue",
|
|
12
|
+
"vue-demi",
|
|
13
|
+
"element",
|
|
14
|
+
"element-ui",
|
|
15
|
+
"element-plus"
|
|
16
|
+
],
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./src/index.d.ts",
|
|
20
|
+
"require": "./src/index.ts",
|
|
21
|
+
"import": "./src/index.ts"
|
|
22
|
+
},
|
|
23
|
+
"./*": "./*"
|
|
24
|
+
},
|
|
25
|
+
"main": "./src/index.ts",
|
|
26
|
+
"module": "./src/index.ts",
|
|
27
|
+
"unpkg": "./src/index.ts",
|
|
28
|
+
"jsdelivr": "./src/index.ts",
|
|
29
|
+
"types": "./src/index.d.ts",
|
|
30
|
+
"files": [
|
|
31
|
+
"docs",
|
|
32
|
+
"src"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"dev3": "cl switchVue 3 && vite --config ./demo/vue3/vite.config.ts --open",
|
|
36
|
+
"dev2.7": "cl switchVue 2.7 && vite --config ./demo/vue2.7/vite.config.ts --open",
|
|
37
|
+
"dev": "vite --config ./demo/vue2.6/vite.config.ts --open",
|
|
38
|
+
"build": "vite build",
|
|
39
|
+
"release": "npx lint-staged && pnpm build && cl release"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"element-plus": ">=2",
|
|
43
|
+
"element-ui": ">=2",
|
|
44
|
+
"vue": "2||3"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"element-plus": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"element-ui": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"lodash-es": "latest",
|
|
56
|
+
"vue-demi": "latest",
|
|
57
|
+
"vue-global-config": "latest"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@commitlint/cli": "latest",
|
|
61
|
+
"@commitlint/config-conventional": "latest",
|
|
62
|
+
"@types/lodash-es": "latest",
|
|
63
|
+
"@types/node": "latest",
|
|
64
|
+
"@vitejs/plugin-vue2": "latest",
|
|
65
|
+
"@vue/test-utils": "1",
|
|
66
|
+
"case-police": "latest",
|
|
67
|
+
"element-ui": "latest",
|
|
68
|
+
"husky": "latest",
|
|
69
|
+
"lint-staged": "latest",
|
|
70
|
+
"rome": "latest",
|
|
71
|
+
"sass": "latest",
|
|
72
|
+
"stylelint": "latest",
|
|
73
|
+
"stylelint-config-recommended-vue": "latest",
|
|
74
|
+
"stylelint-config-standard-scss": "latest",
|
|
75
|
+
"typescript": "latest",
|
|
76
|
+
"unplugin-auto-import": "latest",
|
|
77
|
+
"unplugin-vue-components": "latest",
|
|
78
|
+
"vanilla-jsoneditor": "latest",
|
|
79
|
+
"vite": "latest",
|
|
80
|
+
"vite-plugin-checker": "latest",
|
|
81
|
+
"vite-plugin-dts": "latest",
|
|
82
|
+
"vls": "latest",
|
|
83
|
+
"vti": "latest",
|
|
84
|
+
"vue": "2.7",
|
|
85
|
+
"vue-template-compiler": "2.7",
|
|
86
|
+
"vue-tsc": "latest",
|
|
87
|
+
"zhlint": "latest"
|
|
88
|
+
},
|
|
89
|
+
"lint-staged": {
|
|
90
|
+
"{src,__tests__}/**.*": "rome check",
|
|
91
|
+
"*.md": [
|
|
92
|
+
"case-police --fix",
|
|
93
|
+
"zhlint --fix"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
"publishConfig": {
|
|
97
|
+
"registry": "https://registry.npmjs.org"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export default (element) => {
|
|
2
|
+
const { top, right, bottom, left } = element.getBoundingClientRect()
|
|
3
|
+
const yInView =
|
|
4
|
+
top >= 0 && top <= window.innerHeight && bottom >= 0 && bottom <= window.innerHeight
|
|
5
|
+
const xInView = left >= 0 && left <= window.innerWidth && right >= 0 && right <= window.innerWidth
|
|
6
|
+
return yInView && xInView
|
|
7
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--animate-duration: 1s;
|
|
3
|
+
--animate-delay: 1s;
|
|
4
|
+
--animate-repeat: 1;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.animate__animated {
|
|
8
|
+
-webkit-animation-duration: 1s;
|
|
9
|
+
animation-duration: 1s;
|
|
10
|
+
-webkit-animation-duration: var(--animate-duration);
|
|
11
|
+
animation-duration: var(--animate-duration);
|
|
12
|
+
-webkit-animation-fill-mode: both;
|
|
13
|
+
animation-fill-mode: both;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@-webkit-keyframes headShake {
|
|
17
|
+
0% {
|
|
18
|
+
-webkit-transform: translateX(0);
|
|
19
|
+
transform: translateX(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
6.5% {
|
|
23
|
+
-webkit-transform: translateX(-6px) rotateY(-9deg);
|
|
24
|
+
transform: translateX(-6px) rotateY(-9deg);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
18.5% {
|
|
28
|
+
-webkit-transform: translateX(5px) rotateY(7deg);
|
|
29
|
+
transform: translateX(5px) rotateY(7deg);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
31.5% {
|
|
33
|
+
-webkit-transform: translateX(-3px) rotateY(-5deg);
|
|
34
|
+
transform: translateX(-3px) rotateY(-5deg);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
43.5% {
|
|
38
|
+
-webkit-transform: translateX(2px) rotateY(3deg);
|
|
39
|
+
transform: translateX(2px) rotateY(3deg);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
50% {
|
|
43
|
+
-webkit-transform: translateX(0);
|
|
44
|
+
transform: translateX(0);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@keyframes headShake {
|
|
49
|
+
0% {
|
|
50
|
+
-webkit-transform: translateX(0);
|
|
51
|
+
transform: translateX(0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
6.5% {
|
|
55
|
+
-webkit-transform: translateX(-6px) rotateY(-9deg);
|
|
56
|
+
transform: translateX(-6px) rotateY(-9deg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
18.5% {
|
|
60
|
+
-webkit-transform: translateX(5px) rotateY(7deg);
|
|
61
|
+
transform: translateX(5px) rotateY(7deg);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
31.5% {
|
|
65
|
+
-webkit-transform: translateX(-3px) rotateY(-5deg);
|
|
66
|
+
transform: translateX(-3px) rotateY(-5deg);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
43.5% {
|
|
70
|
+
-webkit-transform: translateX(2px) rotateY(3deg);
|
|
71
|
+
transform: translateX(2px) rotateY(3deg);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
50% {
|
|
75
|
+
-webkit-transform: translateX(0);
|
|
76
|
+
transform: translateX(0);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.animate__headShake {
|
|
81
|
+
-webkit-animation-timing-function: ease-in-out;
|
|
82
|
+
animation-timing-function: ease-in-out;
|
|
83
|
+
-webkit-animation-name: headShake;
|
|
84
|
+
animation-name: headShake;
|
|
85
|
+
}
|