[improvement] functional inherit context (#2716)

This commit is contained in:
neverland 2019-02-11 20:46:46 +08:00 committed by GitHub
parent 9947ab00e8
commit 0bf4a9e799
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 104 additions and 85 deletions

View File

@ -1,4 +1,5 @@
import { use } from '../utils';
import { inheritContext } from '../utils/functional';
import Loading from '../loading';
const [sfc, bem] = use('button');
@ -30,7 +31,7 @@ export default sfc({
}
},
render(h, context, inherit) {
render(h, context) {
const { props, listeners } = context;
const { type, disabled, loading } = props;
@ -58,7 +59,7 @@ export default sfc({
}
])}
onClick={onClick}
{...inherit}
{...inheritContext(context)}
>
{loading ? (
<Loading size="20px" color={type === 'default' ? undefined : ''} />

View File

@ -1,4 +1,5 @@
import { use } from '../utils';
import { inheritContext } from '../utils/functional';
import Cell from '../cell';
const [sfc, bem, t] = use('contact-card');
@ -20,7 +21,7 @@ export default sfc({
}
},
render(h, context, inherit) {
render(h, context) {
const { props, listeners } = context;
const { type, editable } = props;
@ -37,7 +38,7 @@ export default sfc({
listeners.click(event);
}
}}
{...inherit}
{...inheritContext(context)}
>
{type === 'add'
? props.addText || t('addText')

View File

@ -1,4 +1,5 @@
import { use, noop } from '../utils';
import { inheritContext } from '../utils/functional';
import Icon from '../icon';
import Cell from '../cell';
import Button from '../button';
@ -16,7 +17,7 @@ export default sfc({
addText: String
},
render(h, context, inherit) {
render(h, context) {
const { props, listeners } = context;
const List = props.list.map((item, index) => (
@ -50,7 +51,7 @@ export default sfc({
));
return (
<div class={bem()} {...inherit}>
<div class={bem()} {...inheritContext(context)}>
<RadioGroup value={props.value} class={bem('group')}>
{List}
</RadioGroup>

View File

@ -1,4 +1,5 @@
import { use, noop } from '../utils';
import { inheritContext } from '../utils/functional';
import Icon from '../icon';
const [sfc, bem] = use('nav-bar');
@ -22,7 +23,7 @@ export default sfc({
}
},
render(h, context, inherit) {
render(h, context) {
const { props, listeners } = context;
const slots = context.slots();
@ -30,7 +31,7 @@ export default sfc({
<div
class={[bem({ fixed: props.fixed }), { 'van-hairline--bottom': props.border }]}
style={{ zIndex: props.zIndex }}
{...inherit}
{...inheritContext(context)}
>
<div class={bem('left')} onClick={listeners['click-left'] || noop}>
{slots.left || [

View File

@ -1,4 +1,5 @@
import { use, noop } from '../utils';
import { inheritContext } from '../utils/functional';
import Button from '../button';
const [sfc, bem, t] = use('submit-bar');
@ -26,14 +27,14 @@ export default sfc({
}
},
render(h, context, inherit) {
render(h, context) {
const { props, listeners } = context;
const { tip, price } = props;
const slots = context.slots();
const hasPrice = typeof price === 'number';
return (
<div class={bem()} {...inherit}>
<div class={bem()} {...inheritContext(context)}>
{slots.top}
{(slots.tip || tip) && (
<div class={bem('tip')}>

View File

@ -1,4 +1,5 @@
import { use } from '../utils';
import { inheritContext } from '../utils/functional';
import Cell from '../cell';
import Switch from '../switch';
import SwitchMixin from '../mixins/switch';
@ -19,11 +20,11 @@ export default sfc({
}
},
render(h, context, inherit) {
render(h, context) {
const { props } = context;
return (
<Cell center title={props.title} border={props.border} class={bem()} {...inherit}>
<Cell center title={props.title} border={props.border} class={bem()} {...inheritContext(context)}>
<Switch {...{ props, on: context.listeners }} />
</Cell>
);

View File

@ -0,0 +1,33 @@
import { RenderContext, VNodeData } from 'vue';
type ObjectIndex = {
[key: string]: any;
};
type Context = RenderContext & { data: VNodeData & ObjectIndex };
type InheritContext = Partial<VNodeData> & ObjectIndex;
const inheritKey = [
'style',
'class',
'attrs',
'nativeOn',
'directives',
'staticClass',
'staticStyle'
];
const mapInheritKey: ObjectIndex = { nativeOn: 'on' };
export function inheritContext(context: Context): InheritContext {
return inheritKey.reduce(
(obj, key) => {
if (context.data[key]) {
obj[mapInheritKey[key] || key] = context.data[key];
}
return obj;
},
{} as InheritContext
);
}

View File

@ -1,73 +0,0 @@
/**
* Create a basic component with common options
*/
import '../../locale';
import { camelize } from '..';
import SlotsMixin from '../../mixins/slots';
const arrayProp = {
type: Array,
default: () => []
};
const numberProp = {
type: Number,
default: 0
};
function defaultProps(props) {
Object.keys(props).forEach(key => {
if (props[key] === Array) {
props[key] = arrayProp;
} else if (props[key] === Number) {
props[key] = numberProp;
}
});
}
function install(Vue) {
const { name } = this;
Vue.component(name, this);
Vue.component(camelize(`-${name}`), this);
}
const inheritKey = [
'style',
'class',
'attrs',
'nativeOn',
'directives',
'staticClass',
'staticStyle'
];
const mapInheritKey = { nativeOn: 'on' };
function functional(sfc) {
const { render } = sfc;
sfc.render = (h, context) => {
const inherit = inheritKey.reduce((obj, key) => {
if (context.data[key]) {
obj[mapInheritKey[key] || key] = context.data[key];
}
return obj;
}, {});
return render(h, context, inherit);
};
}
export default name => sfc => {
sfc.name = name;
sfc.install = install;
sfc.mixins = sfc.mixins || [];
sfc.mixins.push(SlotsMixin);
if (sfc.props) {
defaultProps(sfc.props);
}
if (sfc.functional) {
functional(sfc);
}
return sfc;
};

53
packages/utils/use/sfc.ts Normal file
View File

@ -0,0 +1,53 @@
/**
* Create a basic component with common options
*/
import '../../locale';
import { camelize } from '..';
import SlotsMixin from '../../mixins/slots';
import Vue, { VueConstructor, ComponentOptions } from 'vue';
type VantComponentOptions = ComponentOptions<Vue> & {
functional?: boolean;
install?: (Vue: VueConstructor) => void;
};
const arrayProp = {
type: Array,
default: () => []
};
const numberProp = {
type: Number,
default: 0
};
function defaultProps(props: any) {
Object.keys(props).forEach(key => {
if (props[key] === Array) {
props[key] = arrayProp;
} else if (props[key] === Number) {
props[key] = numberProp;
}
});
}
function install(this: ComponentOptions<Vue>, Vue: VueConstructor) {
const { name } = this;
if (name) {
Vue.component(name, this);
Vue.component(camelize(`-${name}`), this);
}
}
export default (name: string) => (sfc: VantComponentOptions) => {
sfc.name = name;
sfc.install = install;
sfc.mixins = sfc.mixins || [];
sfc.mixins.push(SlotsMixin);
if (sfc.props) {
defaultProps(sfc.props);
}
return sfc;
};