mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[improvement] Tabbar: jsx (#2663)
This commit is contained in:
parent
5b3992d4c2
commit
b8ec2ffc5d
@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Common part of Checkbox & Radio
|
* Common part of Checkbox & Radio
|
||||||
*/
|
*/
|
||||||
|
import { useSlots } from '../utils';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
import findParent from './find-parent';
|
import findParent from './find-parent';
|
||||||
|
|
||||||
@ -41,18 +42,18 @@ export default (parent, bem) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render(h) {
|
render(h) {
|
||||||
const CheckIcon = this.$scopedSlots.icon ? (
|
const { checked } = this;
|
||||||
this.$scopedSlots.icon({ checked: this.checked })
|
const slots = useSlots(this);
|
||||||
) : (
|
const CheckIcon = slots('icon', { checked }) || (
|
||||||
<Icon name="success" style={this.iconStyle} />
|
<Icon name="success" style={this.iconStyle} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const Label = this.$slots.default && (
|
const Label = slots('default') && (
|
||||||
<span
|
<span
|
||||||
class={bem('label', [this.labelPosition, { disabled: this.isDisabled }])}
|
class={bem('label', [this.labelPosition, { disabled: this.isDisabled }])}
|
||||||
onClick={this.onClickLabel}
|
onClick={this.onClickLabel}
|
||||||
>
|
>
|
||||||
{this.$slots.default}
|
{slots('default')}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ export default (parent, bem) => ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class={bem('icon', [this.shape, { disabled: this.isDisabled, checked: this.checked }])}
|
class={bem('icon', [this.shape, { disabled: this.isDisabled, checked }])}
|
||||||
onClick={this.onClickIcon}
|
onClick={this.onClickIcon}
|
||||||
>
|
>
|
||||||
{CheckIcon}
|
{CheckIcon}
|
||||||
|
54
packages/tabbar-item/index.js
Normal file
54
packages/tabbar-item/index.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { use, useSlots } from '../utils';
|
||||||
|
import Icon from '../icon';
|
||||||
|
import Info from '../info';
|
||||||
|
import RouterLink from '../mixins/router-link';
|
||||||
|
|
||||||
|
const [sfc, bem] = use('tabbar-item');
|
||||||
|
|
||||||
|
export default sfc({
|
||||||
|
mixins: [RouterLink],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
icon: String,
|
||||||
|
dot: Boolean,
|
||||||
|
info: [String, Number]
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeCreate() {
|
||||||
|
this.$parent.items.push(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
this.$parent.items.splice(this.$parent.items.indexOf(this), 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onClick(event) {
|
||||||
|
this.$parent.onChange(this.$parent.items.indexOf(this));
|
||||||
|
this.$emit('click', event);
|
||||||
|
this.routerLink();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
const { icon, active } = this;
|
||||||
|
const slots = useSlots(this);
|
||||||
|
const style = active ? { color: this.$parent.activeColor } : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={bem({ active })} style={style} onClick={this.onClick}>
|
||||||
|
<div class={bem('icon', { dot: this.dot })}>
|
||||||
|
{slots('icon', { active }) || (icon && <Icon name={icon} />)}
|
||||||
|
<Info info={this.info} />
|
||||||
|
</div>
|
||||||
|
<div class={bem('text')}>{slots('default', { active })}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
@ -1,73 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
:class="b({ active })"
|
|
||||||
:style="style"
|
|
||||||
@click="onClick"
|
|
||||||
>
|
|
||||||
<div :class="b('icon', { dot })">
|
|
||||||
<slot
|
|
||||||
name="icon"
|
|
||||||
:active="active"
|
|
||||||
>
|
|
||||||
<icon
|
|
||||||
v-if="icon"
|
|
||||||
:name="icon"
|
|
||||||
/>
|
|
||||||
</slot>
|
|
||||||
<van-info :info="info" />
|
|
||||||
</div>
|
|
||||||
<div :class="b('text')">
|
|
||||||
<slot :active="active" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Info from '../info';
|
|
||||||
import create from '../utils/create';
|
|
||||||
import RouterLink from '../mixins/router-link';
|
|
||||||
|
|
||||||
export default create({
|
|
||||||
name: 'tabbar-item',
|
|
||||||
|
|
||||||
components: {
|
|
||||||
[Info.name]: Info
|
|
||||||
},
|
|
||||||
|
|
||||||
mixins: [RouterLink],
|
|
||||||
|
|
||||||
props: {
|
|
||||||
icon: String,
|
|
||||||
dot: Boolean,
|
|
||||||
info: [String, Number]
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
active: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
style() {
|
|
||||||
return this.active ? { color: this.$parent.activeColor } : null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeCreate() {
|
|
||||||
this.$parent.items.push(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
destroyed() {
|
|
||||||
this.$parent.items.splice(this.$parent.items.indexOf(this), 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
onClick(event) {
|
|
||||||
this.$parent.onChange(this.$parent.items.indexOf(this));
|
|
||||||
this.$emit('click', event);
|
|
||||||
this.routerLink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,19 +1,8 @@
|
|||||||
<template>
|
import { use } from '../utils';
|
||||||
<div
|
|
||||||
class="van-hairline--top-bottom"
|
|
||||||
:class="b({ fixed })"
|
|
||||||
:style="style"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
const [sfc, bem] = use('tabbar');
|
||||||
import create from '../utils/create';
|
|
||||||
|
|
||||||
export default create({
|
|
||||||
name: 'tabbar',
|
|
||||||
|
|
||||||
|
export default sfc({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
items: []
|
items: []
|
||||||
@ -33,14 +22,6 @@ export default create({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
|
||||||
style() {
|
|
||||||
return {
|
|
||||||
zIndex: this.zIndex
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
items() {
|
items() {
|
||||||
this.setActiveItem();
|
this.setActiveItem();
|
||||||
@ -64,6 +45,16 @@ export default create({
|
|||||||
this.$emit('change', active);
|
this.$emit('change', active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{ zIndex: this.zIndex }}
|
||||||
|
class={['van-hairline--top-bottom', bem({ fixed: this.fixed })]}
|
||||||
|
>
|
||||||
|
{this.$slots.default}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
|
@ -1,5 +1,6 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import use from './use';
|
import use from './use';
|
||||||
|
import { useSlots } from './slots';
|
||||||
|
|
||||||
const isServer = Vue.prototype.$isServer;
|
const isServer = Vue.prototype.$isServer;
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ export {
|
|||||||
isObj,
|
isObj,
|
||||||
isDef,
|
isDef,
|
||||||
isServer,
|
isServer,
|
||||||
|
useSlots,
|
||||||
camelize,
|
camelize,
|
||||||
isAndroid
|
isAndroid
|
||||||
};
|
};
|
||||||
|
8
packages/utils/slots.js
Normal file
8
packages/utils/slots.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export function useSlots({ $slots, $scopedSlots }) {
|
||||||
|
return (name, props) => {
|
||||||
|
if ($scopedSlots[name]) {
|
||||||
|
return $scopedSlots[name](props);
|
||||||
|
}
|
||||||
|
return $slots[name];
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user