cdui-js 1.0.14 → 1.0.16

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/README.md CHANGED
@@ -100,6 +100,40 @@ console.log(getValue());
100
100
  ```
101
101
 
102
102
 
103
+ ## 批量更新
104
+
105
+ 同一时刻如果修改了多个响应式属性,则每次修改都会触发响应式更新。
106
+
107
+ ```tsx
108
+ import { batch, createEffect, reactive } from 'cdui-js';
109
+
110
+ const state = reactive({ value1: 1, value2: 2 });
111
+
112
+ createEffect(() => {
113
+ console.log(state.value1, state.value2);
114
+ });
115
+
116
+ // 两次更新会执行 createEffect 回调两次
117
+ state.value1++;
118
+ state.value2++;
119
+ ```
120
+
121
+ 这种情况可使用`batch`进行批量修改响应式属性以减少响应式自动更新的次数。
122
+
123
+ ```tsx
124
+ import { batch, createEffect, reactive } from 'cdui-js';
125
+
126
+ const state = reactive({ value1: 1, value2: 2 });
127
+
128
+ createEffect(() => {
129
+ console.log(state.value1, state.value2);
130
+ });
131
+
132
+ // 两次更新会执行 createEffect 回调两次
133
+ state.value1++;
134
+ state.value2++;
135
+ ```
136
+
103
137
  # 响应式组件
104
138
 
105
139
  任意一个函数,如果返回了`JSX.Element`,则这个函数就是一个响应式组件。建议使用`tsx`作为组件模板,本响应式框架没有虚拟`DOM`,也更轻量高效。
@@ -257,17 +291,17 @@ function ParentComponent() {
257
291
  }
258
292
  ```
259
293
 
260
- 有时候,需要把不同的属性值应用到不同的`DOM`节点,可以使用`splitProps`方法对`props`进行切分。切分后的任一部分都具有响应式特性。
294
+ 有时候,需要把不同的属性值应用到不同的`DOM`节点,可以使用`omitProps`方法排除`props`中不需要的属性。`omitProps`返回的对象仍具有响应式特性。
261
295
 
262
296
  ```tsx
263
- import { splitProps } from 'cdui-js';
297
+ import { omitProps } from 'cdui-js';
264
298
 
265
- function Component(props: { title: string, children: JSX.Element[] }) {
266
- // restProps 为拆分后剩余的部分
267
- const [titleProps, childrenProps, restProps] = splitProps(props, ['title'], ['children']);
299
+ // 定义要排除的属性集合(使用 as const 标记为元组)
300
+ const OMIT_PROPS = ['title', 'children'] as const;
268
301
 
302
+ function Component(props: { title: string, children: JSX.Element[] }) {
269
303
  return (
270
- <div {...restProps}>
304
+ <div {...omitProps(props, OMIT_PROPS)}>
271
305
  <div>{titleProps.title}</div>
272
306
  <div>{childrenProps.children}</div>
273
307
  </div>
@@ -275,6 +309,18 @@ function Component(props: { title: string, children: JSX.Element[] }) {
275
309
  }
276
310
  ```
277
311
 
312
+ 可以使用`combineClass`合并`class`:
313
+
314
+ ```tsx
315
+ import { combineClass } from 'cdui-js';
316
+
317
+ function Component(props: { class: string }) {
318
+ return (
319
+ <div class={combineClass('defaultClassName', props.class)}></div>
320
+ );
321
+ }
322
+ ```
323
+
278
324
  > 注意,解构`props`对象会丧失响应性,除非你确定要这样,否则不要随意解构任意`props`或响应式对象。
279
325
 
280
326
  ```tsx
package/css/all.css CHANGED
@@ -10,5 +10,6 @@
10
10
  @import url(combobox.css);
11
11
  @import url(canlendar.css);
12
12
  @import url(datepicker.css);
13
+ @import url(mobile-datepicker.css);
13
14
  @import url(form.css);
14
15
  @import url(carousel.css);
@@ -0,0 +1,75 @@
1
+ .mobile-date-picker {
2
+ display: flex;
3
+ flex-direction: row;
4
+ width: 100%;
5
+ min-height: calc(44px * 5);
6
+ position: relative;
7
+ box-sizing: border-box;
8
+ user-select: none;
9
+ }
10
+
11
+ .mobile-date-picker-column {
12
+ flex: 1;
13
+ position: relative;
14
+ min-width: 0;
15
+ }
16
+
17
+ .mobile-date-picker-column::before {
18
+ content: '';
19
+ pointer-events: none;
20
+ position: absolute;
21
+ left: 0;
22
+ right: 0;
23
+ top: 0;
24
+ bottom: 0;
25
+ z-index: 1;
26
+ background: linear-gradient(
27
+ to bottom,
28
+ rgba(255, 255, 255, 0.95) 0%,
29
+ rgba(255, 255, 255, 0) calc(50% - 22px)
30
+ ),
31
+ linear-gradient(
32
+ to top,
33
+ rgba(255, 255, 255, 0.95) 0%,
34
+ rgba(255, 255, 255, 0) calc(50% - 22px)
35
+ );
36
+ }
37
+
38
+ .mobile-date-picker-column::after {
39
+ content: '';
40
+ pointer-events: none;
41
+ position: absolute;
42
+ left: 0;
43
+ right: 0;
44
+ top: 50%;
45
+ transform: translateY(-50%);
46
+ height: 44px;
47
+ box-sizing: border-box;
48
+ border-top: 1px solid #e4e4e4;
49
+ border-bottom: 1px solid #e4e4e4;
50
+ z-index: 2;
51
+ }
52
+
53
+ .mobile-date-picker-wheel {
54
+ --mdp-item-h: 44px;
55
+ height: calc(var(--mdp-item-h) * 5);
56
+ overflow-y: auto;
57
+ touch-action: pan-y;
58
+ -webkit-overflow-scrolling: touch;
59
+ }
60
+
61
+ .mobile-date-picker-wheel-inner {
62
+ position: relative;
63
+ width: 100%;
64
+ }
65
+
66
+ .mobile-date-picker-item {
67
+ position: absolute;
68
+ left: 0;
69
+ right: 0;
70
+ height: var(--mdp-item-h);
71
+ line-height: var(--mdp-item-h);
72
+ text-align: center;
73
+ font-size: 16px;
74
+ color: #1b212d;
75
+ }
package/demo/src/App.tsx CHANGED
@@ -1,13 +1,36 @@
1
+ import { batch, createEffect, omitProps, pickProps, reactive } from '../../src/reactive';
1
2
  import { CanlendarPage } from './pages/Canlendar';
2
3
  import { ComboBoxPage } from './pages/ComboBox';
3
4
  import { DatePickerPage } from './pages/DatePicker';
4
5
  import { FormPage } from './pages/Form';
6
+ import { MobileDatePickerPage } from './pages/MobileDatePicker';
7
+
8
+ const Test = (props: { text1: string; text2: string }) => {
9
+ return (
10
+ <div>
11
+ <div>{JSON.stringify({ ...pickProps(props, ['text1']) })}</div>
12
+ <div>{JSON.stringify({ ...omitProps(props, ['text1']) })}</div>
13
+ </div>
14
+ );
15
+ };
5
16
 
6
17
  export const App = () => {
18
+ let state = reactive({
19
+ text1: '111',
20
+ text2: '222',
21
+ });
22
+
23
+ createEffect(() => {
24
+ console.log(state.text1, state.text2);
25
+ });
26
+
7
27
  return (
8
28
  <div style={{ 'min-height': '100%' }}>
29
+ <Test {...state}></Test>
30
+ <button onclick={() => (state.text1 = state.text2 = '' + Math.random())}>click</button>
9
31
  <CanlendarPage></CanlendarPage>
10
32
  <DatePickerPage></DatePickerPage>
33
+ <MobileDatePickerPage></MobileDatePickerPage>
11
34
  <ComboBoxPage></ComboBoxPage>
12
35
  <FormPage></FormPage>
13
36
  </div>
@@ -0,0 +1,5 @@
1
+ import { MobileDatePicker } from '../../../src/components/MobileDatePicker';
2
+
3
+ export const MobileDatePickerPage = () => {
4
+ return <MobileDatePicker></MobileDatePicker>;
5
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdui-js",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "bin": {
@@ -1,6 +1,5 @@
1
- import { createSignal, combineClass, splitProps } from '../reactive';
2
-
3
1
  import { JSX } from '../jsx';
2
+ import { createSignal, combineClass, omitProps } from '../reactive';
4
3
  import { Canleandar as i18n } from '../i18n';
5
4
  import { replaceTemplate } from '../template';
6
5
  import { For } from './For';
@@ -15,7 +14,7 @@ const renderDates = (
15
14
  className: string,
16
15
  todayDate: Date,
17
16
  selectedDate?: Date,
18
- disableDate?: (year: number, month: number, date: number) => boolean,
17
+ disableFn?: (year: number, month: number, date: number) => boolean,
19
18
  ) => {
20
19
  let today = todayDate.getFullYear() === year && todayDate.getMonth() === month ? todayDate.getDate() : -1;
21
20
  let selected =
@@ -26,7 +25,7 @@ const renderDates = (
26
25
  for (let i = from; i <= to; i++) {
27
26
  items.push(
28
27
  `<span class="canlendar-date${className}${today === i ? ' today' : ''}${selected === i ? ' selected' : ''}${
29
- disableDate && disableDate(year, month, i) ? ' disabled' : ''
28
+ disableFn && disableFn(year, month, i) ? ' disabled' : ''
30
29
  }" data-date="${year + '|' + month + '|' + i}">${i}</span>`,
31
30
  );
32
31
  }
@@ -40,7 +39,7 @@ const renderPrevMonthItems = (
40
39
  index: number,
41
40
  todayDate: Date,
42
41
  selectedDate?: Date,
43
- disableDate?: (year: number, month: number, date: number) => boolean,
42
+ disableFn?: (year: number, month: number, date: number) => boolean,
44
43
  ) => {
45
44
  // 获取上月天数
46
45
  let days = new Date(year, month, 0).getDate();
@@ -52,7 +51,7 @@ const renderPrevMonthItems = (
52
51
  month = 11;
53
52
  }
54
53
 
55
- renderDates(items, year, month, days - index + 1, days, ' prev-month', todayDate, selectedDate, disableDate);
54
+ renderDates(items, year, month, days - index + 1, days, ' prev-month', todayDate, selectedDate, disableFn);
56
55
  };
57
56
 
58
57
  const renderNextMonthItems = (
@@ -62,7 +61,7 @@ const renderNextMonthItems = (
62
61
  days: number,
63
62
  todayDate: Date,
64
63
  selectedDate?: Date,
65
- disableDate?: (year: number, month: number, date: number) => boolean,
64
+ disableFn?: (year: number, month: number, date: number) => boolean,
66
65
  ) => {
67
66
  if (month < 11) {
68
67
  month++;
@@ -71,13 +70,13 @@ const renderNextMonthItems = (
71
70
  month = 0;
72
71
  }
73
72
 
74
- renderDates(items, year, month, 1, days, ' next-month', todayDate, selectedDate, disableDate);
73
+ renderDates(items, year, month, 1, days, ' next-month', todayDate, selectedDate, disableFn);
75
74
  };
76
75
 
77
76
  const renderItems = (
78
77
  showDate: Date,
79
78
  selectedDate?: Date,
80
- disableDate?: (year: number, month: number, date: number) => boolean,
79
+ disableFn?: (year: number, month: number, date: number) => boolean,
81
80
  ) => {
82
81
  let today = new Date();
83
82
  let year = showDate.getFullYear();
@@ -92,17 +91,17 @@ const renderItems = (
92
91
  // 当前月第一天不是周一,渲染上月数据
93
92
  if (firstWeek !== 1) {
94
93
  index = firstWeek > 0 ? firstWeek - 1 : 6;
95
- renderPrevMonthItems(items, year, month, index, today, selectedDate, disableDate);
94
+ renderPrevMonthItems(items, year, month, index, today, selectedDate, disableFn);
96
95
  }
97
96
 
98
97
  // 获取当前月的天数
99
98
  days = new Date(year, month + 1, 0).getDate();
100
99
  // 渲染本月日期
101
- renderDates(items, year, month, 1, days, '', today, selectedDate, disableDate);
100
+ renderDates(items, year, month, 1, days, '', today, selectedDate, disableFn);
102
101
 
103
102
  // 当前月最后一天没有占满,渲染下月数据
104
103
  if ((index += days) < 42) {
105
- renderNextMonthItems(items, year, month, 42 - index, today, selectedDate, disableDate);
104
+ renderNextMonthItems(items, year, month, 42 - index, today, selectedDate, disableFn);
106
105
  }
107
106
 
108
107
  return items.join('');
@@ -138,6 +137,8 @@ const formatMonth = (value: Date) => {
138
137
  return month > 9 ? month : '0' + month;
139
138
  };
140
139
 
140
+ const OMIT_PROPS = ['class', 'value', 'onValueChange', 'disableFn'] as const;
141
+
141
142
  export const Canlendar = (
142
143
  props: Omit<JSX.HTMLAttributes<never>, 'children'> & {
143
144
  /**
@@ -151,19 +152,17 @@ export const Canlendar = (
151
152
  /**
152
153
  * 禁用函数
153
154
  */
154
- disableDate?: (year: number, month: number, date: number) => boolean;
155
+ disableFn?: (year: number, month: number, date: number) => boolean;
155
156
  },
156
157
  ) => {
157
- const [thisProps, restProps] = splitProps(props, ['class', 'value', 'onValueChange', 'disableDate']);
158
-
159
158
  let domMonth: HTMLElement;
160
159
  let domBody: HTMLElement;
161
160
 
162
- const [selectedDate, setSelectedDate] = createSignal(parseDate(thisProps.value));
161
+ const [selectedDate, setSelectedDate] = createSignal(parseDate(props.value));
163
162
  const [showDate, setShowDate] = createSignal(selectedDate() || new Date());
164
163
 
165
164
  return (
166
- <div class={combineClass('canlendar', thisProps.class)} {...restProps}>
165
+ <div class={combineClass('canlendar', props.class)} {...omitProps(props, OMIT_PROPS)}>
167
166
  <div class="canlendar-header">
168
167
  <div ref={domMonth as any} class="canlendar-month">
169
168
  {replaceTemplate(i18n.Month, showDate().getFullYear(), formatMonth(showDate()))}
@@ -185,7 +184,7 @@ export const Canlendar = (
185
184
  let target = event.target as HTMLElement;
186
185
  let date, onValueChange;
187
186
 
188
- if (target && (date = target.dataset.date) && (onValueChange = thisProps.onValueChange)) {
187
+ if (target && (date = target.dataset.date) && (onValueChange = props.onValueChange)) {
189
188
  let dom = domBody.querySelector('.selected') as HTMLElement;
190
189
 
191
190
  if (dom !== target) {
@@ -197,7 +196,7 @@ export const Canlendar = (
197
196
  }
198
197
  }
199
198
  }}
200
- innerHTML={renderItems(showDate(), selectedDate(), thisProps.disableDate)}
199
+ innerHTML={renderItems(showDate(), selectedDate(), props.disableFn)}
201
200
  ></div>
202
201
  </div>
203
202
  );
@@ -9,7 +9,7 @@ import {
9
9
  defineProperty,
10
10
  onCleanup,
11
11
  onMount,
12
- splitProps,
12
+ omitProps,
13
13
  } from '../reactive';
14
14
 
15
15
  import { For } from './For';
@@ -48,6 +48,8 @@ if (isBrowser) {
48
48
  );
49
49
  }
50
50
 
51
+ const OMIT_PROPS = ['class', 'each', 'children', 'autoplay', 'interval', 'vertical', 'api'] as const;
52
+
51
53
  /**
52
54
  * 轮播组件外部调用接口
53
55
  */
@@ -101,15 +103,6 @@ export const Carousel = <T, U extends JSX.Element>(
101
103
  api?: (api: CarouselApi) => void;
102
104
  },
103
105
  ) => {
104
- let [thisProps, restProps] = splitProps(props, [
105
- 'class',
106
- 'each',
107
- 'children',
108
- 'autoplay',
109
- 'interval',
110
- 'vertical',
111
- 'api',
112
- ]);
113
106
  let [currentIndex, setCurrentIndex] = createSignal(0);
114
107
 
115
108
  let ref: HTMLElement;
@@ -121,15 +114,15 @@ export const Carousel = <T, U extends JSX.Element>(
121
114
  let autoplayTimer: any;
122
115
 
123
116
  // 获取滚动方向
124
- const scrollType = createMemo(() => (thisProps.vertical ? 'scrollTop' : 'scrollLeft'));
125
- const offsetType = createMemo(() => (thisProps.vertical ? 'offsetTop' : 'offsetLeft'));
126
- const screenType = createMemo(() => (thisProps.vertical ? 'screenY' : 'screenX'));
117
+ const scrollType = createMemo(() => (props.vertical ? 'scrollTop' : 'scrollLeft'));
118
+ const offsetType = createMemo(() => (props.vertical ? 'offsetTop' : 'offsetLeft'));
119
+ const screenType = createMemo(() => (props.vertical ? 'screenY' : 'screenX'));
127
120
 
128
121
  // 滚动到指定索引
129
122
  const scrollTo = (index: number) => {
130
123
  let children = ref.children;
131
124
  let length = children.length;
132
- let count = thisProps.each.length; // 真实的子项数量
125
+ let count = props.each.length; // 真实的子项数量
133
126
 
134
127
  if (index < 0) {
135
128
  index += count;
@@ -156,7 +149,7 @@ export const Carousel = <T, U extends JSX.Element>(
156
149
 
157
150
  if (index <= 0) {
158
151
  // 真实的子项数量
159
- let count = thisProps.each.length;
152
+ let count = props.each.length;
160
153
 
161
154
  // 先滚动到对应节点的填充节点
162
155
  ref[scrollType()] = (ref.children[index + count] as HTMLElement)[offsetType()];
@@ -219,7 +212,7 @@ export const Carousel = <T, U extends JSX.Element>(
219
212
  const autoplay = () => {
220
213
  clearTimeout(autoplayTimer);
221
214
 
222
- if (thisProps.autoplay !== false) {
215
+ if (props.autoplay !== false) {
223
216
  autoplayTimer = setTimeout(
224
217
  () => {
225
218
  if (!resizing) {
@@ -233,14 +226,14 @@ export const Carousel = <T, U extends JSX.Element>(
233
226
 
234
227
  autoplay();
235
228
  },
236
- thisProps.interval > 3000 ? thisProps.interval : 3000,
229
+ props.interval > 3000 ? props.interval : 3000,
237
230
  );
238
231
  }
239
232
  };
240
233
 
241
234
  // 初始化外部访问接口
242
- thisProps.api &&
243
- thisProps.api(
235
+ props.api &&
236
+ props.api(
244
237
  defineProperty(
245
238
  {
246
239
  backward,
@@ -278,8 +271,12 @@ export const Carousel = <T, U extends JSX.Element>(
278
271
  });
279
272
 
280
273
  return (
281
- <div ref={ref as any} class={combineClass('carousel scrollbar-hidden', thisProps.class)} {...restProps}>
282
- <For each={fillItems(thisProps.each)}>{thisProps.children}</For>
274
+ <div
275
+ ref={ref as any}
276
+ class={combineClass('carousel scrollbar-hidden', props.class)}
277
+ {...omitProps(props, OMIT_PROPS)}
278
+ >
279
+ <For each={fillItems(props.each)}>{props.children}</For>
283
280
  </div>
284
281
  );
285
282
  };
@@ -1,10 +1,12 @@
1
- import { createSignal, splitProps } from 'solid-js';
1
+ import { createSignal } from 'solid-js';
2
2
 
3
3
  import { JSX } from '../jsx';
4
- import { combineClass, defineProperty } from '../reactive';
4
+ import { combineClass, defineProperty, omitProps } from '../reactive';
5
5
 
6
6
  const COLLAPSED_CLASS = 'collapsed';
7
7
 
8
+ const OMIT_PROPS = ['class', 'collapsed', 'collapsedSize', 'getExpandedSize', 'useTransition', 'api'] as const;
9
+
8
10
  /**
9
11
  * 可收拢面板外部调用接口
10
12
  */
@@ -52,15 +54,7 @@ export const CollapsiblePanel = (
52
54
  ) => {
53
55
  let ref: HTMLElement;
54
56
 
55
- const [thisProps, restProps] = splitProps(props, [
56
- 'class',
57
- 'collapsed',
58
- 'collapsedSize',
59
- 'getExpandedSize',
60
- 'useTransition',
61
- 'api',
62
- ]);
63
- const [collapsed, setCollapsed] = createSignal(thisProps.collapsed || false);
57
+ const [collapsed, setCollapsed] = createSignal(props.collapsed || false);
64
58
 
65
59
  const transitionTo = (size: string, fromSize?: string) => {
66
60
  let style = ref.style;
@@ -85,22 +79,22 @@ export const CollapsiblePanel = (
85
79
 
86
80
  // 设置成收拢状态
87
81
  if (value) {
88
- if (thisProps.useTransition) {
82
+ if (props.useTransition) {
89
83
  style.height = ref.offsetHeight + 'px';
90
84
 
91
85
  setTimeout(() => {
92
- style.height = thisProps.collapsedSize || '';
86
+ style.height = props.collapsedSize || '';
93
87
  classList.add(COLLAPSED_CLASS);
94
88
  });
95
89
  } else {
96
- style.height = thisProps.collapsedSize || '';
90
+ style.height = props.collapsedSize || '';
97
91
  classList.add(COLLAPSED_CLASS);
98
92
  }
99
93
  } else {
100
- let getExpandedSize = thisProps.getExpandedSize;
94
+ let getExpandedSize = props.getExpandedSize;
101
95
 
102
96
  // 设置成展开状态
103
- if (thisProps.useTransition) {
97
+ if (props.useTransition) {
104
98
  style.height = ref.offsetHeight + 'px';
105
99
 
106
100
  setTimeout(() => {
@@ -119,8 +113,8 @@ export const CollapsiblePanel = (
119
113
  }
120
114
  };
121
115
 
122
- thisProps.api &&
123
- thisProps.api(
116
+ props.api &&
117
+ props.api(
124
118
  defineProperty({ transitionTo }, 'collapsed', {
125
119
  get: collapsed,
126
120
  set: update,
@@ -130,8 +124,8 @@ export const CollapsiblePanel = (
130
124
  return (
131
125
  <div
132
126
  ref={ref as any}
133
- class={combineClass('collapsed-panel', thisProps.collapsed && COLLAPSED_CLASS, thisProps.class)}
134
- {...restProps}
127
+ class={combineClass('collapsed-panel', props.collapsed && COLLAPSED_CLASS, props.class)}
128
+ {...omitProps(props, OMIT_PROPS)}
135
129
  ></div>
136
130
  );
137
131
  };
@@ -1,8 +1,10 @@
1
1
  import { JSX } from '../jsx';
2
- import { combineClass, splitProps } from '../reactive';
2
+ import { combineClass, omitProps } from '../reactive';
3
3
  import { disableAutoCloseEvent } from '../dom';
4
4
  import { Popup, PopupApi, PopupProps } from './Popup';
5
5
 
6
+ const OMIT_PROPS = ['class', 'value', 'readonly', 'popupOnFocus', 'popup', 'onPopup', 'api', 'children'] as const;
7
+
6
8
  /**
7
9
  * 下拉框组件
8
10
  */
@@ -27,39 +29,29 @@ export const ComboBox = (
27
29
  popup?: Omit<JSX.HTMLAttributes<never>, 'children'>;
28
30
  },
29
31
  ) => {
30
- let [thisProps, restProps] = splitProps(props, [
31
- 'class',
32
- 'value',
33
- 'readonly',
34
- 'popupOnFocus',
35
- 'popup',
36
- 'onPopup',
37
- 'api',
38
- 'children',
39
- ]);
40
32
  let popup: PopupApi;
41
33
 
42
34
  const initApi = (api) => {
43
35
  popup = api;
44
- thisProps.api && thisProps.api(popup);
36
+ props.api && props.api(popup);
45
37
  };
46
38
 
47
39
  return (
48
- <div class={combineClass('combobox', thisProps.class)} {...restProps}>
40
+ <div class={combineClass('combobox', props.class)} {...omitProps(props, OMIT_PROPS)}>
49
41
  <div class="combobox-host" {...disableAutoCloseEvent}>
50
42
  <input
51
43
  class="combobox-input"
52
- value={thisProps.value || ''}
53
- readonly={thisProps.readonly}
54
- onfocus={() => thisProps.popupOnFocus && popup.openPopup()}
55
- onclick={() => thisProps.readonly && !thisProps.popupOnFocus && popup.togglePopup()}
44
+ value={props.value || ''}
45
+ readonly={props.readonly}
46
+ onfocus={() => props.popupOnFocus && popup.openPopup()}
47
+ onclick={() => props.readonly && !props.popupOnFocus && popup.togglePopup()}
56
48
  ></input>
57
49
  <svg class="icon icon-s" aria-hidden={true} onclick={() => popup.togglePopup()}>
58
50
  <use href="#icon-dropdown"></use>
59
51
  </svg>
60
52
  </div>
61
- <Popup api={initApi} onPopup={thisProps.onPopup} {...thisProps.popup}>
62
- {thisProps.children}
53
+ <Popup api={initApi} onPopup={props.onPopup} {...props.popup}>
54
+ {props.children}
63
55
  </Popup>
64
56
  </div>
65
57
  );
@@ -1,5 +1,5 @@
1
1
  import { JSX } from '../jsx';
2
- import { combineClass, createSignal, splitProps } from '../reactive';
2
+ import { combineClass, createSignal, omitProps } from '../reactive';
3
3
  import { disableAutoCloseEvent } from '../dom';
4
4
  import { For } from './For';
5
5
  import { Popup, PopupApi } from './Popup';
@@ -46,6 +46,8 @@ const formatMonth = (value: Date) => {
46
46
  // );
47
47
  // };
48
48
 
49
+ const OMIT_PROPS = ['class', 'value', 'readonly', 'format', 'children'] as const;
50
+
49
51
  /**
50
52
  * 日期选择组件
51
53
  */
@@ -65,26 +67,25 @@ export const DatePicker = (
65
67
  readonly?: boolean;
66
68
  },
67
69
  ) => {
68
- let [thisProps, restProps] = splitProps(props, ['class', 'value', 'readonly', 'format', 'children']);
69
70
  let popup: PopupApi;
70
71
 
71
- const [value, setValue] = createSignal(thisProps.value && parseDate(thisProps.value));
72
+ const [value, setValue] = createSignal(props.value && parseDate(props.value));
72
73
 
73
74
  return (
74
- <div class={combineClass('datepicker', thisProps.class)} {...restProps}>
75
+ <div class={combineClass('datepicker', props.class)} {...omitProps(props, OMIT_PROPS)}>
75
76
  <div class="datepicker-host" {...disableAutoCloseEvent}>
76
77
  <input
77
78
  class="datepicker-input"
78
- value={formatDate(value(), thisProps.format)}
79
- readonly={thisProps.readonly}
80
- onclick={() => thisProps.readonly && popup.togglePopup()}
79
+ value={formatDate(value(), props.format)}
80
+ readonly={props.readonly}
81
+ onclick={() => props.readonly && popup.togglePopup()}
81
82
  ></input>
82
83
  <svg class="icon icon-s" aria-hidden={true} onclick={() => popup.togglePopup()}>
83
84
  <use href="#icon-dropdown"></use>
84
85
  </svg>
85
86
  </div>
86
87
  <Popup api={(api) => (popup = api)} onPopup={() => showPopup()}>
87
- {thisProps.children}
88
+ {props.children}
88
89
  </Popup>
89
90
  </div>
90
91
  );