feat: add usePopupState

This commit is contained in:
chenjiahan 2020-08-31 19:59:19 +08:00
parent f0675d043a
commit 10355ed849
6 changed files with 84 additions and 96 deletions

View File

@ -1,38 +1,27 @@
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { inBrowser, mountComponent } from '../utils'; import { inBrowser } from '../utils';
import { mountComponent, usePopupState } from '../utils/mount-component';
import VanDialog from './Dialog'; import VanDialog from './Dialog';
let instance; let instance;
function initInstance() { function initInstance() {
({ instance } = mountComponent({ const Wrapper = {
data() { setup() {
return { const { state, toggle } = usePopupState();
dialogProps: { return () => (
show: false,
},
};
},
methods: {
toggle(show) {
this.dialogProps.show = show;
},
setProps(props) {
this.dialogProps = props;
},
},
render() {
return (
<VanDialog <VanDialog
lazyRender={false} lazyRender={false}
{...{ {...{
...this.dialogProps, ...state,
'onUpdate:show': this.toggle, 'onUpdate:show': toggle,
}} }}
/> />
); );
}, },
})); };
({ instance } = mountComponent(Wrapper));
} }
function Dialog(options) { function Dialog(options) {
@ -46,7 +35,7 @@ function Dialog(options) {
initInstance(); initInstance();
} }
instance.setProps({ instance.setState({
...Dialog.currentOptions, ...Dialog.currentOptions,
...options, ...options,
callback: (action) => { callback: (action) => {

View File

@ -1,5 +1,6 @@
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { inBrowser, mountComponent } from '../utils'; import { inBrowser } from '../utils';
import { mountComponent, usePopupState } from '../utils/mount-component';
import VanImagePreview from './ImagePreview'; import VanImagePreview from './ImagePreview';
let instance; let instance;
@ -27,34 +28,19 @@ const defaultConfig = {
function initInstance() { function initInstance() {
({ instance } = mountComponent({ ({ instance } = mountComponent({
data() { setup() {
return { const { state, toggle } = usePopupState();
props: {
show: false, const onClosed = () => {
}, state.images = [];
}; };
},
methods: { return () => (
close() {
this.toggle(false);
},
toggle(show) {
this.props.show = show;
},
setProps(props) {
Object.assign(this.props, props);
},
onClosed() {
this.props.images = [];
},
},
render() {
return (
<VanImagePreview <VanImagePreview
{...{ {...{
...this.props, ...state,
onClosed: this.onClosed, onClosed,
'onUpdate:show': this.toggle, 'onUpdate:show': toggle,
}} }}
/> />
); );
@ -74,7 +60,7 @@ const ImagePreview = (images, startPosition = 0) => {
const options = Array.isArray(images) ? { images, startPosition } : images; const options = Array.isArray(images) ? { images, startPosition } : images;
instance.setProps({ instance.setState({
...defaultConfig, ...defaultConfig,
...options, ...options,
}); });

View File

@ -1,5 +1,6 @@
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { isObject, inBrowser, mountComponent } from '../utils'; import { isObject, inBrowser } from '../utils';
import { mountComponent, usePopupState } from '../utils/mount-component';
import VanNotify from './Notify'; import VanNotify from './Notify';
let timer; let timer;
@ -11,27 +12,13 @@ function parseOptions(message) {
function initInstance() { function initInstance() {
({ instance } = mountComponent({ ({ instance } = mountComponent({
data() { setup() {
return { const { state, toggle } = usePopupState();
notifyProps: { return () => (
show: false,
},
};
},
methods: {
toggle(show) {
this.notifyProps.show = show;
},
setProps(props) {
this.notifyProps = props;
},
},
render() {
return (
<VanNotify <VanNotify
{...{ {...{
...this.notifyProps, ...state,
'onUpdate:show': this.toggle, 'onUpdate:show': toggle,
}} }}
/> />
); );
@ -53,7 +40,7 @@ function Notify(options) {
...parseOptions(options), ...parseOptions(options),
}; };
instance.setProps(options); instance.setState(options);
clearTimeout(timer); clearTimeout(timer);
if (options.duration && options.duration > 0) { if (options.duration && options.duration > 0) {

View File

@ -1,5 +1,6 @@
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { isObject, inBrowser, mountComponent } from '../utils'; import { isObject, inBrowser } from '../utils';
import { mountComponent } from '../utils/mount-component';
import VanToast from './Toast'; import VanToast from './Toast';
const defaultOptions = { const defaultOptions = {
@ -57,14 +58,14 @@ function createInstance() {
return { return {
timer: null, timer: null,
message: null, message: null,
toastProps: { state: {
show: false, show: false,
}, },
}; };
}, },
watch: { watch: {
message(val) { message(val) {
this.toastProps.message = val; this.state.message = val;
}, },
}, },
methods: { methods: {
@ -72,7 +73,7 @@ function createInstance() {
this.toggle(false); this.toggle(false);
}, },
toggle(show, duration) { toggle(show, duration) {
this.toastProps.show = show; this.state.show = show;
if (show) { if (show) {
clearTimeout(this.timer); clearTimeout(this.timer);
@ -84,8 +85,8 @@ function createInstance() {
} }
} }
}, },
setProps(props) { setState(props) {
this.toastProps = { this.state = {
...props, ...props,
duration: undefined, duration: undefined,
}; };
@ -102,7 +103,7 @@ function createInstance() {
return ( return (
<VanToast <VanToast
{...{ {...{
...this.toastProps, ...this.state,
onClosed: this.onClosed, onClosed: this.onClosed,
'onUpdate:show': this.toggle, 'onUpdate:show': this.toggle,
}} }}
@ -132,7 +133,7 @@ function Toast(options = {}) {
...options, ...options,
}; };
toast.setProps(options); toast.setState(options);
nextTick(() => { nextTick(() => {
toast.toggle(true, options.duration); toast.toggle(true, options.duration);

View File

@ -1,5 +1,3 @@
import { createApp, Component } from 'vue';
export { addUnit, getSizeStyle } from './format/unit'; export { addUnit, getSizeStyle } from './format/unit';
export { createNamespace } from './create'; export { createNamespace } from './create';
@ -42,18 +40,3 @@ export function pick(obj: Record<string, any>, keys: string[]) {
return ret; return ret;
}, {} as Record<string, any>); }, {} as Record<string, any>);
} }
export function mountComponent(RootComponent: Component) {
const app = createApp(RootComponent);
const root = document.createElement('div');
document.body.appendChild(root);
return {
instance: app.mount(root),
unmount() {
app.unmount(root);
document.body.removeChild(root);
},
};
}

View File

@ -0,0 +1,42 @@
import { createApp, reactive, Component } from 'vue';
import { usePublicApi } from '../composition/use-public-api';
export function usePopupState() {
const state = reactive({
show: false,
});
const toggle = (show: boolean) => {
state.show = show;
};
const close = () => {
toggle(false);
};
const setState = (props: Record<string, any>) => {
Object.assign(state, props);
};
usePublicApi({ close, toggle, setState });
return {
state,
toggle,
};
}
export function mountComponent(RootComponent: Component) {
const app = createApp(RootComponent);
const root = document.createElement('div');
document.body.appendChild(root);
return {
instance: app.mount(root),
unmount() {
app.unmount(root);
document.body.removeChild(root);
},
};
}