refactor(Grid): refactor with composition api

This commit is contained in:
chenjiahan 2020-09-08 17:58:27 +08:00
parent 60e08767b3
commit 38740b6c1c
2 changed files with 83 additions and 99 deletions

View File

@ -1,10 +1,13 @@
import { computed } from 'vue';
// Utils // Utils
import { createNamespace, addUnit } from '../utils'; import { createNamespace, addUnit } from '../utils';
import { BORDER } from '../utils/constant'; import { BORDER } from '../utils/constant';
import { route, routeProps } from '../composition/use-route'; import { GRID_KEY } from '../grid';
// Mixins // Composition
import { ChildrenMixin } from '../mixins/relation'; import { useParent } from '../composition/use-relation';
import { useRoute, routeProps } from '../composition/use-route';
// Components // Components
import Icon from '../icon'; import Icon from '../icon';
@ -13,24 +16,22 @@ import Badge from '../badge';
const [createComponent, bem] = createNamespace('grid-item'); const [createComponent, bem] = createNamespace('grid-item');
export default createComponent({ export default createComponent({
mixins: [ChildrenMixin('vanGrid')],
props: { props: {
...routeProps, ...routeProps,
dot: Boolean, dot: Boolean,
text: String, text: String,
icon: String, icon: String,
iconPrefix: String,
badge: [Number, String], badge: [Number, String],
iconPrefix: String,
}, },
emits: ['click'], setup(props, { slots }) {
const { parent, index } = useParent(GRID_KEY);
const route = useRoute();
computed: { const rootStyle = computed(() => {
style() { const { square, gutter, columnNum } = parent.props;
const { square, gutter, columnNum } = this.parent;
const percent = `${100 / columnNum}%`; const percent = `${100 / columnNum}%`;
const style = { const style = {
flexBasis: percent, flexBasis: percent,
}; };
@ -41,79 +42,68 @@ export default createComponent({
const gutterValue = addUnit(gutter); const gutterValue = addUnit(gutter);
style.paddingRight = gutterValue; style.paddingRight = gutterValue;
if (this.index >= columnNum) { if (index.value >= columnNum) {
style.marginTop = gutterValue; style.marginTop = gutterValue;
} }
} }
return style; return style;
}, });
contentStyle() { const contentStyle = computed(() => {
const { square, gutter } = this.parent; const { square, gutter } = parent.props;
if (square && gutter) { if (square && gutter) {
const gutterValue = addUnit(gutter); const gutterValue = addUnit(gutter);
return { return {
right: gutterValue, right: gutterValue,
bottom: gutterValue, bottom: gutterValue,
height: 'auto', height: 'auto',
}; };
} }
}, });
},
methods: { const renderIcon = () => {
onClick(event) { if (slots.icon) {
this.$emit('click', event);
route(this.$router, this);
},
genIcon() {
if (this.$slots.icon) {
return ( return (
<div class={bem('icon-wrapper')}> <div class={bem('icon-wrapper')}>
{this.$slots.icon()} {slots.icon()}
<Badge dot={this.dot} badge={this.badge} /> <Badge dot={props.dot} badge={props.badge} />
</div> </div>
); );
} }
if (this.icon) { if (props.icon) {
return ( return (
<Icon <Icon
dot={this.dot} dot={props.dot}
name={this.icon} name={props.icon}
size={this.parent.iconSize} size={parent.props.iconSize}
badge={this.badge} badge={props.badge}
class={bem('icon')} class={bem('icon')}
classPrefix={this.iconPrefix} classPrefix={props.iconPrefix}
/> />
); );
} }
}, };
getText() { const renderText = () => {
if (this.$slots.text) { if (slots.text) {
return this.$slots.text(); return slots.text();
} }
if (props.text) {
if (this.text) { return <span class={bem('text')}>{props.text}</span>;
return <span class={bem('text')}>{this.text}</span>;
} }
}, };
genContent() { const renderContent = () => {
if (this.$slots.default) { if (slots.default) {
return this.$slots.default(); return slots.default();
} }
return [renderIcon(), renderText()];
};
return [this.genIcon(), this.getText()]; return () => {
},
},
render() {
const { const {
center, center,
border, border,
@ -121,15 +111,9 @@ export default createComponent({
gutter, gutter,
direction, direction,
clickable, clickable,
} = this.parent; } = parent.props;
return ( const classes = [
<div class={[bem({ square })]} style={this.style}>
<div
style={this.contentStyle}
role={clickable ? 'button' : null}
tabindex={clickable ? 0 : null}
class={[
bem('content', [ bem('content', [
direction, direction,
{ {
@ -140,12 +124,21 @@ export default createComponent({
}, },
]), ]),
{ [BORDER]: border }, { [BORDER]: border },
]} ];
onClick={this.onClick}
return (
<div class={[bem({ square })]} style={rootStyle.value}>
<div
role={clickable ? 'button' : null}
class={classes}
style={contentStyle.value}
tabindex={clickable ? 0 : null}
onClick={route}
> >
{this.genContent()} {renderContent()}
</div> </div>
</div> </div>
); );
};
}, },
}); });

View File

@ -1,12 +1,12 @@
import { provide, reactive } from 'vue';
import { createNamespace, addUnit } from '../utils'; import { createNamespace, addUnit } from '../utils';
import { BORDER_TOP } from '../utils/constant'; import { BORDER_TOP } from '../utils/constant';
import { ParentMixin } from '../mixins/relation';
const [createComponent, bem] = createNamespace('grid'); const [createComponent, bem] = createNamespace('grid');
export default createComponent({ export const GRID_KEY = 'vanGrid';
mixins: [ParentMixin('vanGrid')],
export default createComponent({
props: { props: {
square: Boolean, square: Boolean,
gutter: [Number, String], gutter: [Number, String],
@ -27,25 +27,16 @@ export default createComponent({
}, },
}, },
computed: { setup(props, { slots }) {
style() { const children = reactive([]);
const { gutter } = this; provide(GRID_KEY, { props, children });
if (gutter) { return () => (
return {
paddingLeft: addUnit(gutter),
};
}
},
},
render() {
return (
<div <div
style={this.style} style={{ paddingLeft: addUnit(props.gutter) }}
class={[bem(), { [BORDER_TOP]: this.border && !this.gutter }]} class={[bem(), { [BORDER_TOP]: props.border && !props.gutter }]}
> >
{this.$slots.default?.()} {slots.default?.()}
</div> </div>
); );
}, },