mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-05 19:41:42 +08:00
[improvement] Notify: tsx & functional (#2810)
This commit is contained in:
parent
52e6fd2f0b
commit
da91631b0d
@ -90,6 +90,8 @@ function Actionsheet(
|
||||
class={bem()}
|
||||
value={props.value}
|
||||
position="bottom"
|
||||
overlay={props.overlay}
|
||||
closeOnClickOverlay={props.closeOnClickOverlay}
|
||||
onInput={(value: boolean) => {
|
||||
emit(ctx, 'input', value);
|
||||
}}
|
||||
|
@ -1,44 +0,0 @@
|
||||
import { use } from '../utils';
|
||||
import { RED, WHITE } from '../utils/color';
|
||||
import { PopupMixin } from '../mixins/popup';
|
||||
|
||||
const [sfc, bem] = use('notify');
|
||||
|
||||
export default sfc({
|
||||
mixins: [PopupMixin],
|
||||
|
||||
props: {
|
||||
className: null,
|
||||
message: [String, Number],
|
||||
color: {
|
||||
type: String,
|
||||
value: WHITE
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
value: RED
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
value: 3000
|
||||
},
|
||||
lockScroll: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
render(h) {
|
||||
const style = {
|
||||
color: this.color,
|
||||
background: this.background
|
||||
};
|
||||
return (
|
||||
<transition name="van-slide-down">
|
||||
<div vShow={this.value} class={[bem(), this.className]} style={style}>
|
||||
{this.message}
|
||||
</div>
|
||||
</transition>
|
||||
);
|
||||
}
|
||||
});
|
69
packages/notify/Notify.tsx
Normal file
69
packages/notify/Notify.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import { use } from '../utils';
|
||||
import { RED, WHITE } from '../utils/color';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import { PopupMixin } from '../mixins/popup';
|
||||
import Popup from '../popup';
|
||||
|
||||
// Types
|
||||
import { CreateElement, RenderContext } from 'vue/types';
|
||||
import { DefaultSlots } from '../utils/use/sfc';
|
||||
import { PopupMixinProps } from '../mixins/popup/type';
|
||||
|
||||
export type NotifyProps = PopupMixinProps & {
|
||||
color: string;
|
||||
message: string | number;
|
||||
duration: number;
|
||||
className?: any;
|
||||
background: string;
|
||||
};
|
||||
|
||||
const [sfc, bem] = use('notify');
|
||||
|
||||
function Notify(
|
||||
h: CreateElement,
|
||||
props: NotifyProps,
|
||||
slots: DefaultSlots,
|
||||
ctx: RenderContext<NotifyProps>
|
||||
) {
|
||||
const style = {
|
||||
color: props.color,
|
||||
background: props.background
|
||||
};
|
||||
|
||||
return (
|
||||
<Popup
|
||||
value={props.value}
|
||||
style={style}
|
||||
position="top"
|
||||
overlay={false}
|
||||
lockScroll={false}
|
||||
class={[bem(), props.className]}
|
||||
onInput={(value: boolean) => {
|
||||
emit(ctx, 'input', value);
|
||||
}}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
{props.message}
|
||||
</Popup>
|
||||
);
|
||||
}
|
||||
|
||||
Notify.props = {
|
||||
...PopupMixin.props,
|
||||
className: null as any,
|
||||
message: [String, Number],
|
||||
color: {
|
||||
type: String,
|
||||
default: WHITE
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: RED
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
}
|
||||
};
|
||||
|
||||
export default sfc<NotifyProps>(Notify);
|
@ -1,75 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import VanNotify from './Notify';
|
||||
import { RED, WHITE } from '../utils/color';
|
||||
import { isObj, isServer } from '../utils';
|
||||
|
||||
let timer;
|
||||
let instance;
|
||||
|
||||
const initInstance = () => {
|
||||
instance = new (Vue.extend(VanNotify))({
|
||||
el: document.createElement('div')
|
||||
});
|
||||
|
||||
document.body.appendChild(instance.$el);
|
||||
};
|
||||
|
||||
const parseOptions = message => (isObj(message) ? message : { message });
|
||||
|
||||
const Notify = options => {
|
||||
/* istanbul ignore if */
|
||||
if (isServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!instance) {
|
||||
initInstance();
|
||||
}
|
||||
|
||||
options = {
|
||||
...Notify.currentOptions,
|
||||
...parseOptions(options)
|
||||
};
|
||||
|
||||
Object.assign(instance, options);
|
||||
clearTimeout(timer);
|
||||
|
||||
if (options.duration > 0) {
|
||||
timer = setTimeout(Notify.clear, options.duration);
|
||||
}
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
Notify.clear = () => {
|
||||
if (instance) {
|
||||
instance.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
Notify.defaultOptions = {
|
||||
value: true,
|
||||
text: '',
|
||||
color: WHITE,
|
||||
background: RED,
|
||||
duration: 3000,
|
||||
className: ''
|
||||
};
|
||||
|
||||
Notify.setDefaultOptions = options => {
|
||||
Object.assign(Notify.currentOptions, options);
|
||||
};
|
||||
|
||||
Notify.resetDefaultOptions = () => {
|
||||
Notify.currentOptions = { ...Notify.defaultOptions };
|
||||
};
|
||||
|
||||
Notify.install = () => {
|
||||
Vue.use(VanNotify);
|
||||
};
|
||||
|
||||
Notify.resetDefaultOptions();
|
||||
|
||||
Vue.prototype.$notify = Notify;
|
||||
|
||||
export default Notify;
|
@ -1,9 +1,6 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-notify {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
padding: @notify-padding;
|
||||
|
73
packages/notify/index.ts
Normal file
73
packages/notify/index.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import Vue from 'vue';
|
||||
import VanNotify from './Notify';
|
||||
import { RED, WHITE } from '../utils/color';
|
||||
import { isObj, isServer } from '../utils';
|
||||
import { mount } from '../utils/functional';
|
||||
import { NotifyOptions } from 'types/notify';
|
||||
|
||||
let timer: number | NodeJS.Timeout;
|
||||
let instance: any;
|
||||
|
||||
function parseOptions(message: NotifyOptions): NotifyOptions {
|
||||
return isObj(message) ? message : ({ message } as NotifyOptions);
|
||||
}
|
||||
|
||||
function Notify(options: NotifyOptions) {
|
||||
/* istanbul ignore if */
|
||||
if (isServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!instance) {
|
||||
instance = mount(VanNotify);
|
||||
}
|
||||
|
||||
options = {
|
||||
...Notify.currentOptions,
|
||||
...parseOptions(options)
|
||||
};
|
||||
|
||||
Object.assign(instance, options);
|
||||
clearTimeout(timer as NodeJS.Timeout);
|
||||
|
||||
if (options.duration && options.duration > 0) {
|
||||
timer = setTimeout(Notify.clear, options.duration);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
function defaultOptions(): NotifyOptions {
|
||||
return {
|
||||
value: true,
|
||||
message: '',
|
||||
color: WHITE,
|
||||
background: RED,
|
||||
duration: 3000,
|
||||
className: ''
|
||||
};
|
||||
}
|
||||
|
||||
Notify.clear = () => {
|
||||
if (instance) {
|
||||
instance.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
Notify.currentOptions = defaultOptions();
|
||||
|
||||
Notify.setDefaultOptions = (options: NotifyOptions) => {
|
||||
Object.assign(Notify.currentOptions, options);
|
||||
};
|
||||
|
||||
Notify.resetDefaultOptions = () => {
|
||||
Notify.currentOptions = defaultOptions();
|
||||
};
|
||||
|
||||
Notify.install = () => {
|
||||
Vue.use(VanNotify as any);
|
||||
};
|
||||
|
||||
Vue.prototype.$notify = Notify;
|
||||
|
||||
export default Notify;
|
@ -1,11 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`create a notify 1`] = `<div class="van-notify" style="color: rgb(255, 255, 255); background: rgb(255, 68, 68); z-index: 2000;" name="van-slide-down">test</div>`;
|
||||
exports[`create a notify 1`] = `<div class="van-popup van-popup--top van-notify" name="van-popup-slide-top" style="color: rgb(255, 255, 255); background: rgb(255, 68, 68); z-index: 2000;">test</div>`;
|
||||
|
||||
exports[`notify disappear 1`] = `<div class="van-notify" style="color: red; z-index: 2000; background: blue;" name="van-slide-down">test</div>`;
|
||||
exports[`notify disappear 1`] = `<div class="van-popup van-popup--top van-notify" name="van-popup-slide-top" style="color: red; z-index: 2000; background: blue;">test</div>`;
|
||||
|
||||
exports[`notify disappear 2`] = `<div class="van-notify" style="color: red; z-index: 2000; background: blue; display: none;" name="van-slide-down">test</div>`;
|
||||
exports[`notify disappear 2`] = `<div class="van-popup van-popup--top van-notify" name="van-popup-slide-top" style="color: red; z-index: 2000; background: blue; display: none;">test</div>`;
|
||||
|
||||
exports[`notify disappear 3`] = `<div class="van-notify" style="color: rgb(255, 255, 255); z-index: 2001; background: rgb(255, 68, 68);" name="van-slide-down">text2</div>`;
|
||||
exports[`notify disappear 3`] = `<div class="van-popup van-popup--top van-notify" name="van-popup-slide-top" style="color: rgb(255, 255, 255); z-index: 2001; background: rgb(255, 68, 68);">text2</div>`;
|
||||
|
||||
exports[`notify disappear 4`] = `<div class="van-notify" style="color: rgb(255, 255, 255); z-index: 2001; background: rgb(255, 68, 68); display: none;" name="van-slide-down">text2</div>`;
|
||||
exports[`notify disappear 4`] = `<div class="van-popup van-popup--top van-notify" name="van-popup-slide-top" style="color: rgb(255, 255, 255); z-index: 2001; background: rgb(255, 68, 68); display: none;">text2</div>`;
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
export type SkuData = {
|
||||
price: string;
|
||||
none_sku: boolean;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { RenderContext, VNodeData } from 'vue/types';
|
||||
import Vue, { RenderContext, VNodeData } from 'vue';
|
||||
|
||||
type ObjectIndex = {
|
||||
[key: string]: any;
|
||||
@ -21,7 +21,10 @@ const inheritKey = [
|
||||
const mapInheritKey: ObjectIndex = { nativeOn: 'on' };
|
||||
|
||||
// inherit partial context, map nativeOn to on
|
||||
export function inherit(context: Context, inheritListeners?: boolean): InheritContext {
|
||||
export function inherit(
|
||||
context: Context,
|
||||
inheritListeners?: boolean
|
||||
): InheritContext {
|
||||
const result = inheritKey.reduce(
|
||||
(obj, key) => {
|
||||
if (context.data[key]) {
|
||||
@ -53,3 +56,18 @@ export function emit(context: Context, eventName: string, ...args: any[]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mount functional component
|
||||
export function mount(Component: any) {
|
||||
const instance = new Vue({
|
||||
el: document.createElement('div'),
|
||||
props: Component.props,
|
||||
render(h) {
|
||||
return h(Component, { props: this.$props });
|
||||
}
|
||||
});
|
||||
|
||||
document.body.appendChild(instance.$el);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
7
types/notify.d.ts
vendored
7
types/notify.d.ts
vendored
@ -1,10 +1,11 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
type NotifyMessage = string | number;
|
||||
export type NotifyMessage = string | number;
|
||||
|
||||
export type NotifyOptions = {
|
||||
message?: NotifyMessage;
|
||||
value?: boolean;
|
||||
color?: string;
|
||||
message?: NotifyMessage;
|
||||
duration?: number;
|
||||
className?: any;
|
||||
background?: string;
|
||||
@ -21,6 +22,8 @@ export interface Notify {
|
||||
(message: NotifyOptions | NotifyMessage): VanNotify;
|
||||
clear(): void;
|
||||
install(): void;
|
||||
currentOptions: NotifyOptions;
|
||||
defaultOptions: NotifyOptions;
|
||||
setDefaultOptions(options: NotifyOptions): void;
|
||||
resetDefaultOptions(): void;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user