Skip to content

Commit 618dea7

Browse files
feat: 抽离 CreateComponent 函数,用于 函数式组件开发 (#1876)
* fix: 修复 ImagePreview 在Taro编译成H5后报错的问题 * fix: 地址关闭时, Close 事件触发两次问题解决 * feat: 组件DatePicker 添加双向绑定 * docs: 组件Picker文档修改 * feat: 组件Picker与DatePicker新增属性safe-area-inset-bottom * feat: imagepreview * fix: 组件imagepreview点击视频遮罩关闭(#1729) * fix: 解决 Picker 在微信小程序中无法使用问题 (#1774) * fix: 修改 Picker 组件 v-model 失效问题 * fix: 组件NoticeBar修改height之后,垂直轮播会卡顿 * fix: 删除Datepicker Demo演示多余内容 * fix: 组件Picker在JD小程序上适配 * fix: 组件Address京东小程序适配 * feat: 京东小程序适配 * fix: 删除空格 * feat: 删除console * fix: 京东小程序imagepreview适配 * fix: 修复 imagepreview 动态设置 initNo 显示不正确问题 * fix: 组件 InfiniteLoading 某些情况下会错误触发下拉刷新#1819 * fix: 删除pullrefresh * feat: 组件 imagepreview瘦身 * feat: 组件Picker 瘦身 * fix: address线上问题修改 * fix: 完善imagepreview * feat: 公共函数提取 * feat: 函数式改用 createComponent
1 parent 24e1e74 commit 618dea7

27 files changed

+370
-1179
lines changed

src/config.json

-10
Original file line numberDiff line numberDiff line change
@@ -729,16 +729,6 @@
729729
"show": true,
730730
"author": "wangyue217"
731731
},
732-
{
733-
"version": "3.0.0",
734-
"name": "PullRefresh",
735-
"type": "component",
736-
"cName": "下拉刷新",
737-
"desc": "下拉刷新",
738-
"sort": 16,
739-
"show": false,
740-
"author": "yangxiaolu3"
741-
},
742732
{
743733
"version": "3.0.0",
744734
"name": "Switch",

src/packages/__VUE/address/index.vue

+11-9
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,17 @@
5858
:class="[selectedRegion[tabName[tabIndex]].id == item.id ? 'active' : '']"
5959
@click="nextAreaList(item)"
6060
>
61-
<nut-icon
62-
class="region-item-icon"
63-
type="self"
64-
v-bind="$attrs"
65-
:name="selectedIcon"
66-
size="13px"
67-
v-if="selectedRegion[tabName[tabIndex]].id == item.id"
68-
></nut-icon
69-
>{{ item.name }}
61+
<div>
62+
<nut-icon
63+
class="region-item-icon"
64+
type="self"
65+
v-bind="$attrs"
66+
:name="selectedIcon"
67+
size="13px"
68+
v-if="selectedRegion[tabName[tabIndex]].id == item.id"
69+
></nut-icon
70+
>{{ item.name }}
71+
</div>
7072
</li>
7173
</ul>
7274
</view>

src/packages/__VUE/dialog/index.ts

+25-42
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import Dialog from './index.vue';
2-
import { render, createVNode, h, VNode, CSSProperties } from 'vue';
2+
import { h, VNode, CSSProperties } from 'vue';
3+
import Popup from '../popup/index.vue';
4+
import Icon from '../icon/index.vue';
5+
import Button from '../button/index.vue';
6+
import OverLay from '../overlay/index.vue';
7+
import { CreateComponent } from '@/packages/utils/create';
38
export class DialogOptions {
49
title?: string = '';
510
content?: string | VNode = '';
@@ -37,51 +42,29 @@ class DialogFunction {
3742
instance: any;
3843
constructor(_options: DialogOptions) {
3944
let options = Object.assign(this.options, _options);
40-
let elWarp: HTMLElement = document.body;
41-
let teleport = options.teleport as string;
42-
if (teleport != 'body') {
43-
if (typeof teleport == 'string') {
44-
elWarp = document.querySelector(teleport) as HTMLElement;
45-
} else {
46-
elWarp = options.teleport as HTMLElement;
47-
}
48-
}
49-
const root = document.createElement('view');
50-
root.id = 'dialog-' + options.id;
51-
const Wrapper = {
52-
setup() {
53-
options.onUpdate = (val: boolean) => {
54-
if (val == false) {
55-
elWarp.removeChild(root);
45+
const { unmount } = CreateComponent(options, {
46+
name: 'dialog',
47+
components: [Popup, Icon, Button, OverLay],
48+
wrapper: (elWarp: any, root: any) => {
49+
return {
50+
setup() {
51+
options.onUpdate = (val: boolean) => {
52+
if (val == false) {
53+
unmount();
54+
}
55+
};
56+
if (options?.onOpened) {
57+
options?.onOpened();
58+
}
59+
options.teleport = `#${root.id}`;
60+
return () => {
61+
return h(Dialog, options);
62+
};
5663
}
5764
};
58-
if (options?.onOpened) {
59-
options?.onOpened();
60-
}
61-
options.teleport = `#${root.id}`;
62-
return () => {
63-
return h(Dialog, options);
64-
};
6565
}
66-
};
67-
this.instance = createVNode(Wrapper);
68-
elWarp.appendChild(root);
69-
render(this.instance, root);
66+
});
7067
}
71-
72-
close = () => {
73-
// if (this.instance) {
74-
// this.instance.component.ctx.close();
75-
// }
76-
};
77-
78-
setDefaultOptions = (options: DialogOptions) => {
79-
// Object.assign(this.currentOptions, options);
80-
};
81-
82-
resetDefaultOptions = () => {
83-
// Dialog.currentOptions = { ...Dialog.defaultOptions };
84-
};
8568
}
8669

8770
const _Dialog = function (options: DialogOptions) {

src/packages/__VUE/dialog/index.vue

+10-24
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,13 @@
4747
import { onMounted, computed, watch, ref, PropType, VNode, CSSProperties } from 'vue';
4848
import { createComponent } from '@/packages/utils/create';
4949
const { componentName, create, translate } = createComponent('dialog');
50-
import Popup from '../popup/index.vue';
50+
import { funInterceptor, Interceptor } from '@/packages/utils/util';
5151
import { popupProps } from '../popup/props';
52-
import Button from '../button/index.vue';
52+
5353
import { isPromise } from '@/packages/utils/util';
5454
export default create({
5555
inheritAttrs: false,
56-
components: {
57-
[Popup.name]: Popup,
58-
[Button.name]: Button
59-
},
56+
components: {},
6057
props: {
6158
...popupProps,
6259
closeOnClickOverlay: {
@@ -114,9 +111,7 @@ export default create({
114111
popStyle: {
115112
type: Object as PropType<CSSProperties>
116113
},
117-
beforeClose: {
118-
type: Function
119-
}
114+
beforeClose: Function as PropType<Interceptor>
120115
},
121116
emits: ['update', 'update:visible', 'ok', 'cancel', 'opened', 'closed'],
122117
setup(props, { emit }) {
@@ -152,22 +147,13 @@ export default create({
152147
};
153148
154149
const closed = (action: string) => {
155-
if (props.beforeClose) {
156-
const result = props.beforeClose(action);
157-
if (isPromise(result)) {
158-
result.then((bool) => {
159-
if (bool) {
160-
update(false);
161-
emit('closed');
162-
} else {
163-
// 用户阻止删除
164-
}
165-
});
150+
funInterceptor(props.beforeClose, {
151+
args: [action],
152+
done: () => {
153+
update(false);
154+
emit('closed');
166155
}
167-
} else {
168-
update(false);
169-
emit('closed');
170-
}
156+
});
171157
};
172158
173159
const onCancel = () => {

src/packages/__VUE/imagepreview/demo.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,13 @@ export default createDemo({
116116
ImagePreview({
117117
show: true,
118118
images: resData.imgData,
119-
onClose
119+
onClose: () => onClose()
120120
});
121121
};
122122
123123
const hideFn = (i: number) => {
124124
(resData as any)['showPreview' + i] = false;
125+
console.log('guansebi');
125126
};
126127
127128
return {

src/packages/__VUE/imagepreview/imagePreviewItem.vue

+23-73
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,28 @@
33
<view
44
:style="imageStyle"
55
class="nut-imagepreview-box"
6-
v-if="image && image.src"
76
@touchstart="onTouchStart"
87
@touchmove="onTouchMove"
98
@touchend="onTouchEnd"
109
@touchcancel="onTouchEnd"
1110
>
12-
<img :src="image.src" class="nut-imagepreview-img" @load="imageLoad" />
13-
</view>
14-
15-
<view
16-
class="nut-imagepreview-box"
17-
v-if="video && video.source"
18-
@click="videoClick"
19-
@touchstart="onTouchStart"
20-
@touchmove="onTouchMove"
21-
@touchend="onTouchEnd"
22-
@touchcancel="onTouchEnd"
23-
>
24-
<nut-video :source="video.source" :options="video.options"></nut-video>
11+
<img v-if="image && image.src" :src="image.src" class="nut-imagepreview-img" @load="imageLoad" />
12+
<nut-video v-if="video && video.source" :source="video.source" :options="video.options"></nut-video>
2513
</view>
2614
</nut-swiper-item>
2715
</template>
2816
<script lang="ts">
2917
import { toRefs, reactive, watch, computed, CSSProperties, PropType } from 'vue';
3018
import { createComponent } from '@/packages/utils/create';
31-
import Popup from '../popup/index.vue';
32-
import Video from '../video/index.vue';
33-
import Swiper from '../swiper/index.vue';
34-
import SwiperItem from '../swiperitem/index.vue';
35-
import Icon from '../icon/index.vue';
3619
import { useTouch } from '@/packages/utils/useTouch';
20+
import { preventDefault } from '@/packages/utils/util';
3721
import { ImageInterface } from './types';
22+
import { baseProps } from './types';
3823
const { create } = createComponent('imagepreviewitem');
3924
4025
export default create({
4126
props: {
42-
show: {
43-
type: Boolean,
44-
default: false
45-
},
46-
initNo: Number,
27+
...baseProps,
4728
image: {
4829
type: Object as PropType<ImageInterface>,
4930
default: () => ({})
@@ -52,36 +33,17 @@ export default create({
5233
type: Object,
5334
default: () => ({})
5435
},
55-
56-
showIndex: {
57-
type: Boolean,
58-
default: true
59-
},
6036
rootWidth: {
6137
type: Number,
6238
default: 0
6339
},
6440
rootHeight: {
6541
type: Number,
6642
default: 0
67-
},
68-
minZoom: {
69-
type: Number,
70-
default: 1 / 3
71-
},
72-
maxZoom: {
73-
type: Number,
74-
default: 3
7543
}
7644
},
7745
emits: ['close', 'scale'],
78-
components: {
79-
[Popup.name]: Popup,
80-
[Video.name]: Video,
81-
[Swiper.name]: Swiper,
82-
[SwiperItem.name]: SwiperItem,
83-
[Icon.name]: Icon
84-
},
46+
components: {},
8547
8648
setup(props, { emit }) {
8749
const state = reactive({
@@ -103,20 +65,25 @@ export default create({
10365
return state.imageRatio > rootRatio;
10466
});
10567
106-
// 图片放大
68+
// 图片缩放
10769
const imageStyle = computed(() => {
108-
const { scale, moveX, moveY, moving, zooming } = state;
109-
const style: CSSProperties = {
110-
transitionDuration: zooming || moving ? '0s' : '.3s'
111-
};
112-
113-
if (scale !== 1) {
114-
const offsetX = moveX / scale;
115-
const offsetY = moveY / scale;
116-
style.transform = `scale(${scale}, ${scale}) translate(${offsetX}px, ${offsetY}px)`;
70+
const images = props.image;
71+
if (images && images.src) {
72+
const { scale, moveX, moveY, moving, zooming } = state;
73+
const style: CSSProperties = {
74+
transitionDuration: zooming || moving ? '0s' : '.3s'
75+
};
76+
77+
if (scale !== 1) {
78+
const offsetX = moveX / scale;
79+
const offsetY = moveY / scale;
80+
style.transform = `scale(${scale}, ${scale}) translate(${offsetX}px, ${offsetY}px)`;
81+
}
82+
83+
return style;
11784
}
11885
119-
return style;
86+
return {};
12087
});
12188
12289
const maxMoveX = computed(() => {
@@ -258,10 +225,8 @@ export default create({
258225
};
259226
260227
const onTouchEnd = (event: TouchEvent) => {
261-
console.log('ontauchend');
262228
let stopPropagation = false;
263229
264-
/* istanbul ignore else */
265230
if (state.moving || state.zooming) {
266231
stopPropagation = true;
267232
@@ -291,30 +256,15 @@ export default create({
291256
}
292257
}
293258
294-
// eliminate tap delay on safari
295259
preventDefault(event, stopPropagation);
296260
297261
checkTap();
298262
touch.reset();
299263
};
300264
301-
// 阻止
302-
const preventDefault = (event: Event, isStopPropagation?: boolean) => {
303-
if (typeof event.cancelable !== 'boolean' || event.cancelable) {
304-
event.preventDefault();
305-
}
306-
307-
if (isStopPropagation) {
308-
event.stopPropagation();
309-
}
310-
};
311-
312265
const clamp = (num: number, min: number, max: number): number => Math.min(Math.max(num, min), max);
313266
314-
// 视频点击
315-
const closeSwiper = (event: any) => {
316-
console.log('关闭视频');
317-
// event.preventDefault();
267+
const closeSwiper = () => {
318268
emit('close');
319269
};
320270

0 commit comments

Comments
 (0)