@zfqh/uview-x 0.0.2 → 0.0.4
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/CHANGELOG.md +19 -0
- package/README.md +22 -0
- package/components/uv-button/uv-button.vue +2 -0
- package/components/uv-checkbox/uv-checkbox.vue +1 -0
- package/components/uv-dialog/uv-dialog.vue +2 -0
- package/components/uv-form-item/uv-form-item.vue +3 -0
- package/components/uv-input/uv-input.vue +79 -41
- package/components/uv-overlay/uv-overlay.vue +1 -0
- package/components/uv-popup/uv-popup.vue +5 -0
- package/components/uv-tabs/uv-tabs.vue +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.0.4](http://10.10.10.16/caoben/front-end-tools/compare/@zfqh/uview-x@0.0.3...@zfqh/uview-x@0.0.4) (2026-11-10)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @zfqh/uview-x
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [0.0.3](http://10.10.10.16/caoben/front-end-tools/compare/@zfqh/uview-x@0.0.2...@zfqh/uview-x@0.0.3) (2026-11-10)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* 文本框输入过快光标乱跳 ([fdf27f9](http://10.10.10.16/caoben/front-end-tools/commits/fdf27f9c37cde6941af3e8dd2db0c708816d3a2f))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
## [0.0.2](http://10.10.10.16/caoben/front-end-tools/compare/@zfqh/uview-x@0.0.1...@zfqh/uview-x@0.0.2) (2026-11-09)
|
|
7
26
|
|
|
8
27
|
**Note:** Version bump only for package @zfqh/uview-x
|
package/README.md
CHANGED
|
@@ -37,6 +37,28 @@ export function createApp() {
|
|
|
37
37
|
}
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
以上 easycom 配置适用于 dev 阶段(H5 / 小程序 / 经典 uni-app);uni-app x Vapor 的 build 阶段不支持 easycom,见下方显式 import。
|
|
41
|
+
|
|
42
|
+
### 显式 import(推荐;Vapor build 必需)
|
|
43
|
+
|
|
44
|
+
uni-app x Vapor(蒸汽模式)下,easycom 仅在 dev 阶段可用,build 阶段不支持;用户也可能主动关闭 easycom。为此 `components/uv-*` 内部已经全部改为显式 import,页面只需 import 自己用到的组件:
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<script setup lang="ts">
|
|
48
|
+
import UvButton from '@zfqh/uview-x/components/uv-button/uv-button.vue';
|
|
49
|
+
import UvIcon from '@zfqh/uview-x/components/uv-icon/uv-icon.vue';
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<uv-button type="primary" text="提交" @click="onSubmit" />
|
|
54
|
+
<uv-icon name="search" :size="24" />
|
|
55
|
+
</template>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- 组件入口为 `@zfqh/uview-x/components/uv-<name>/uv-<name>.vue`,与 easycom 路径一致。
|
|
59
|
+
- `examples/uview-vapor`、`examples/uniapp-vapor` 已关闭 easycom(`"easycom": { "autoscan": false }`),用于验证显式 import 在 dev / build 下都可用。
|
|
60
|
+
- `app.use(uviewX)` 只安装 `$uv` 插件能力,不注册组件。
|
|
61
|
+
|
|
40
62
|
`uni.scss` 引入主题变量,`App.uvue` 引入全局工具样式:
|
|
41
63
|
|
|
42
64
|
```scss
|
|
@@ -114,6 +114,8 @@
|
|
|
114
114
|
import { computed } from 'vue'
|
|
115
115
|
import { $uv } from '../../utils'
|
|
116
116
|
import props from './props'
|
|
117
|
+
import UvIcon from '../uv-icon/uv-icon.vue'
|
|
118
|
+
import UvLoadingIcon from '../uv-loading-icon/uv-loading-icon.vue'
|
|
117
119
|
import { useThrottle } from '../../hooks'
|
|
118
120
|
import { createBem } from '../../utils/compat'
|
|
119
121
|
|
|
@@ -96,6 +96,8 @@
|
|
|
96
96
|
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
|
97
97
|
import { $uv } from '../../utils'
|
|
98
98
|
import props from './props'
|
|
99
|
+
import UvPopup from '../uv-popup/uv-popup.vue'
|
|
100
|
+
import UvButton from '../uv-button/uv-button.vue'
|
|
99
101
|
import { useI18n } from '../../hooks'
|
|
100
102
|
|
|
101
103
|
defineOptions({
|
|
@@ -71,6 +71,9 @@
|
|
|
71
71
|
import { computed, inject, onUnmounted, provide, reactive, ref, watch } from 'vue'
|
|
72
72
|
import { $uv } from '../../utils'
|
|
73
73
|
import props from './props'
|
|
74
|
+
import UvIcon from '../uv-icon/uv-icon.vue'
|
|
75
|
+
import UvTransition from '../uv-transition/uv-transition.vue'
|
|
76
|
+
import UvLine from '../uv-line/uv-line.vue'
|
|
74
77
|
|
|
75
78
|
|
|
76
79
|
defineOptions({
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
import { computed, inject, nextTick, ref, watch } from 'vue'
|
|
71
71
|
import { $uv } from '../../utils'
|
|
72
72
|
import props from './props'
|
|
73
|
+
import UvIcon from '../uv-icon/uv-icon.vue'
|
|
73
74
|
|
|
74
75
|
|
|
75
76
|
defineOptions({
|
|
@@ -139,9 +140,16 @@
|
|
|
139
140
|
'keyboardheightchange'
|
|
140
141
|
])
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
const toValueString = (value: any): string => (value === null || value === undefined ? '' : String(value))
|
|
144
|
+
|
|
145
|
+
const initialValue = toValueString(p.modelValue !== '' ? p.modelValue : p.value)
|
|
146
|
+
// 绑定到 input 的 value:只表示初始值/外部赋值/formatter 结果,输入过程中不回写,避免光标跳动
|
|
147
|
+
const innerValue = ref<string>(initialValue)
|
|
144
148
|
const inputRef = ref<any>(null)
|
|
149
|
+
// 输入框当前显示值:非响应式,仅用于回写判断与事件 payload,避免每次输入触发组件渲染
|
|
150
|
+
let currentValue = initialValue
|
|
151
|
+
// 是否有内容:仅用于清除控件显隐,空/非空切换时才触发渲染
|
|
152
|
+
const hasValue = ref<boolean>(initialValue !== '')
|
|
145
153
|
// 是否处于获得焦点状态
|
|
146
154
|
const focused = ref(false)
|
|
147
155
|
// 过滤处理方法
|
|
@@ -150,19 +158,50 @@
|
|
|
150
158
|
// 表单域上下文:用于触发表单校验(provide/inject 替代 $parent 链)
|
|
151
159
|
const formItemContext: any = inject('uv-form-item-context', null)
|
|
152
160
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
(
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
)
|
|
161
|
+
const updateHasValue = (value: string) => {
|
|
162
|
+
const next = value !== ''
|
|
163
|
+
if (hasValue.value !== next) hasValue.value = next
|
|
164
|
+
}
|
|
159
165
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(
|
|
163
|
-
innerValue.value =
|
|
166
|
+
// 让 input 的 value 属性真正变化:绑定值已是目标值时,用当前显示值制造一次变化
|
|
167
|
+
const setBoundValue = (value: string) => {
|
|
168
|
+
if (innerValue.value !== value) {
|
|
169
|
+
innerValue.value = value
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
if (currentValue !== value) {
|
|
173
|
+
const display = currentValue
|
|
174
|
+
innerValue.value = display
|
|
175
|
+
nextTick(() => {
|
|
176
|
+
if (innerValue.value !== value) innerValue.value = value
|
|
177
|
+
})
|
|
164
178
|
}
|
|
165
|
-
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 写入输入框并同步内部当前值(外部赋值、formatter 生效、清空时使用)
|
|
182
|
+
const applyValue = (value: string) => {
|
|
183
|
+
setBoundValue(value)
|
|
184
|
+
currentValue = value
|
|
185
|
+
updateHasValue(value)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 在下一 tick 统一向上抛出事件,保持 uv-ui 事件顺序
|
|
189
|
+
const emitValue = (value: string) => {
|
|
190
|
+
nextTick(() => {
|
|
191
|
+
emit('input', value)
|
|
192
|
+
emit('update:modelValue', value)
|
|
193
|
+
emit('change', value)
|
|
194
|
+
// 尝试调用uv-form的验证方法
|
|
195
|
+
if (formItemContext) formItemContext.validate('change')
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
watch([() => p.modelValue, () => p.value], () => {
|
|
200
|
+
const next = toValueString(p.modelValue !== '' ? p.modelValue : p.value)
|
|
201
|
+
// 忽略 v-model 回传的当前输入值,避免受控回写覆盖原生输入
|
|
202
|
+
if (next === currentValue) return
|
|
203
|
+
applyValue(next)
|
|
204
|
+
})
|
|
166
205
|
|
|
167
206
|
// x 的 input type 无 password 枚举值,密码由 password 属性控制
|
|
168
207
|
const inputType = computed(() => (p.type === 'password' ? 'text' : p.type))
|
|
@@ -202,7 +241,7 @@
|
|
|
202
241
|
|
|
203
242
|
// 是否显示清除控件
|
|
204
243
|
const isShowClear = computed(() => {
|
|
205
|
-
return !!p.clearable && !p.readonly && focused.value &&
|
|
244
|
+
return !!p.clearable && !p.readonly && focused.value && hasValue.value
|
|
206
245
|
})
|
|
207
246
|
|
|
208
247
|
// 组件的类名
|
|
@@ -261,22 +300,27 @@
|
|
|
261
300
|
|
|
262
301
|
// 当键盘输入时,触发input事件
|
|
263
302
|
const onInput = (e: any) => {
|
|
264
|
-
const
|
|
303
|
+
const rawValue = toValueString(e && e.detail ? e.detail.value : '')
|
|
265
304
|
// 格式化过滤方法
|
|
266
305
|
const formatter = p.formatter || innerFormatter.value
|
|
267
|
-
const formatValue = typeof formatter === 'function' ? formatter(
|
|
268
|
-
//
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
306
|
+
const formatValue = typeof formatter === 'function' ? toValueString(formatter(rawValue)) : rawValue
|
|
307
|
+
// 仅当 formatter 真正改变内容时才回写 value,恒等时保持原生输入不受打断
|
|
308
|
+
if (formatValue !== rawValue) {
|
|
309
|
+
currentValue = rawValue
|
|
310
|
+
applyValue(formatValue)
|
|
311
|
+
} else {
|
|
312
|
+
currentValue = formatValue
|
|
313
|
+
updateHasValue(formatValue)
|
|
314
|
+
}
|
|
315
|
+
emitValue(formatValue)
|
|
274
316
|
}
|
|
275
317
|
|
|
276
318
|
// 输入框失去焦点时触发
|
|
277
319
|
const onBlur = (event: any) => {
|
|
278
|
-
const
|
|
279
|
-
|
|
320
|
+
const detailValue = event && event.detail && event.detail.value !== undefined ? event.detail.value : currentValue
|
|
321
|
+
currentValue = toValueString(detailValue)
|
|
322
|
+
updateHasValue(currentValue)
|
|
323
|
+
emit('blur', currentValue)
|
|
280
324
|
// H5端的blur会先于点击清除控件的点击click事件触发,导致focused
|
|
281
325
|
// 瞬间为false,从而隐藏了清除控件而无法被点击到
|
|
282
326
|
$uv.sleep(100).then(() => {
|
|
@@ -287,14 +331,20 @@
|
|
|
287
331
|
}
|
|
288
332
|
|
|
289
333
|
// 输入框聚焦时触发
|
|
290
|
-
const onFocus = () => {
|
|
334
|
+
const onFocus = (event: any) => {
|
|
291
335
|
focused.value = true
|
|
336
|
+
const detailValue = event && event.detail && event.detail.value !== undefined ? event.detail.value : currentValue
|
|
337
|
+
currentValue = toValueString(detailValue)
|
|
338
|
+
updateHasValue(currentValue)
|
|
292
339
|
emit('focus')
|
|
293
340
|
}
|
|
294
341
|
|
|
295
342
|
// 点击完成按钮时触发
|
|
296
|
-
const onConfirm = () => {
|
|
297
|
-
|
|
343
|
+
const onConfirm = (event: any) => {
|
|
344
|
+
const detailValue = event && event.detail && event.detail.value !== undefined ? event.detail.value : currentValue
|
|
345
|
+
currentValue = toValueString(detailValue)
|
|
346
|
+
updateHasValue(currentValue)
|
|
347
|
+
emit('confirm', currentValue)
|
|
298
348
|
}
|
|
299
349
|
|
|
300
350
|
// 键盘高度发生变化的时候触发此事件
|
|
@@ -302,22 +352,10 @@
|
|
|
302
352
|
emit('keyboardheightchange', e)
|
|
303
353
|
}
|
|
304
354
|
|
|
305
|
-
// 内容发生变化,进行处理
|
|
306
|
-
const valueChange = () => {
|
|
307
|
-
const value = innerValue.value
|
|
308
|
-
nextTick(() => {
|
|
309
|
-
emit('input', value)
|
|
310
|
-
emit('update:modelValue', value)
|
|
311
|
-
emit('change', value)
|
|
312
|
-
// 尝试调用uv-form的验证方法
|
|
313
|
-
if (formItemContext) formItemContext.validate('change')
|
|
314
|
-
})
|
|
315
|
-
}
|
|
316
|
-
|
|
317
355
|
// 点击清除控件
|
|
318
356
|
const onClear = () => {
|
|
319
|
-
|
|
320
|
-
|
|
357
|
+
applyValue('')
|
|
358
|
+
emitValue('')
|
|
321
359
|
nextTick(() => {
|
|
322
360
|
emit('clear')
|
|
323
361
|
})
|
|
@@ -59,6 +59,11 @@
|
|
|
59
59
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
60
60
|
import { $uv, platform } from '../../utils'
|
|
61
61
|
import props from './props'
|
|
62
|
+
import UvIcon from '../uv-icon/uv-icon.vue'
|
|
63
|
+
import UvOverlay from '../uv-overlay/uv-overlay.vue'
|
|
64
|
+
import UvTransition from '../uv-transition/uv-transition.vue'
|
|
65
|
+
import UvSafeBottom from '../uv-safe-bottom/uv-safe-bottom.vue'
|
|
66
|
+
import UvStatusBar from '../uv-status-bar/uv-status-bar.vue'
|
|
62
67
|
import { preventEvent } from '../../utils/compat'
|
|
63
68
|
|
|
64
69
|
defineOptions({
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue'
|
|
81
81
|
import { $uv } from '../../utils'
|
|
82
82
|
import props from './props'
|
|
83
|
+
import UvBadge from '../uv-badge/uv-badge.vue'
|
|
83
84
|
import { getRect, getRectNvue } from '../../utils/compat'
|
|
84
85
|
|
|
85
86
|
defineOptions({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zfqh/uview-x",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "uview-x:面向 uni-app x 蒸汽模式(Vapor)、经典 uni-app Vue3 与 nvue 的 UV UI 组件库,组件保持 uv-ui API。",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"README.md",
|
|
41
41
|
"CHANGELOG.md"
|
|
42
42
|
],
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "2394e0c70de5af7326243f154b4eb92c65baa7f5"
|
|
44
44
|
}
|