此次呢就带你们封装一个tabbar。html
咱们此次封装的tabbar 须要有那些功能???vue
我们开发的时候为了方便其实能够直接在App.vue里写代码,而后在拷贝到对应的文件里。(cv 没法避免了😱)git
先新建几个文件,须要用到。 github
view ===> div
text ===> p
<div class="cu-bar foot tabbar bg-black">
<div class="action text-orange">
<p class="icon-homefill"></p> 首页
</div>
<div class="action text-gray">
<p class="icon-similar"></p> 分类
</div>
<div class="action text-gray">
<p class="icon-recharge"></p>
积分
</div>
<div class="action text-gray">
<div class="icon-cart">
<p class="cu-tag badge">99</p>
</div>
购物车
</div>
<div class="action text-gray">
<div class="icon-my">
<p class="cu-tag badge"></p>
</div>
个人
</div>
</div>
复制代码
这一步我要把 Tabbar 和 TabbarItem 分割开。小程序
export default {
name: 'Tabbar',
render(h) {
return (
<div class="cu-bar foot tabbar bg-black">{this.$slots.default}</div>
);
}
}
// 有同窗可能注意到了this.$slots.default
// 下文有讲解,莫慌!
复制代码
import Tabbar from './src/main';
Tabbar.install = function(Vue) {
Vue.component(Tabbar.name, Tabbar);
};
export default Tabbar;
复制代码
import Tabbar from '../packages/tabbar';
Vue.use(Tabbar);
复制代码
<Tabbar></Tabbar>
复制代码
emmmmmmmmm……好像有点翻车……球的麻袋……数组
我们继续如法炮制 TabberItembash
Tips:
在tabbar-item/src/main.js 中咱们只须要放一个 TabbarItem.
export default {
name: 'TabbarItem',
render(h) {
return (
<div class="action text-gray">
<div class="icon-my">
<p class="cu-tag badge"></p>
</div>
个人
</div>
);
}
}
为啥?
由于每个TabbarItem 都是要传入不一样icon和文字的撒!
复制代码
哎,成了?好像还有点问题……icon都是写死的,文字也是写死的,最重要的是切换效果呢?跳转呢?????ide
import Icon from '../../icon'; // 上一篇文章我们封装icon
export default {
name: 'TabbarItem',
props: {
icon: String
},
components: {
Icon
},
render(h) {
return (
<div class="action text-gray">
<Icon icon={icon}></Icon> // 这里呢直接调用……
个人
</div>
);
}
}
复制代码
App.vue
<Tabbar>
<TabbarItem icon="icon-homefill">首页</TabbarItem>
<TabbarItem icon="icon-similar">分类</TabbarItem>
<TabbarItem icon="icon-cart">购物车</TabbarItem>
<TabbarItem icon="icon-my">个人</TabbarItem>
</Tabbar>
复制代码
这里我直接上代码,慢慢给你们讲解。ui
/packages/tabbar/src/main.js
export default {
name: 'Tabbar',
data() {
return {
items: [] // 这里放一个数组用于存放 TabbarItem
};
},
props: {
value: Number, // 确定会有人纳闷这个是啥??? 下文解释1
fixed: Boolean,
activeColor: String, // 请看下文解释2
bgColor: {
type: String,
default: 'bg-black'
}
},
methods: {
setActiveItem() { // 判断 item.active 是否为true
this.items.forEach((item, index) => {
item.active = index === this.value;
});
},
onChange(active) {
if (active !== this.value) {
this.$emit('input', active); // 通知App.vue 更改data值。
this.$emit('change', active); // 解释3
}
}
},
watch: {
items() {
this.setActiveItem();
},
value() {
this.setActiveItem();
}
},
components: {
},
render(h) {
const { fixed, bgColor, $slots } = this;
const classed = [
{
'foot': fixed,
},
bgColor,
'cu-bar tabbar'
]
return (
<div class={classed}>
{$slots.default}
</div>
);
}
}
复制代码
export default {
name: 'TabbarItem',
props: {
icon: String
},
data() {
return {
active: false
};
},
beforeCreate() { // Tabbar组件 = this.$parent,是的之后你能够经过this.$parent 直接获取父组件.
this.$parent.items.push(this);
},
destroyed() {
this.$parent.items.splice(this.$parent.items.indexOf(this), 1);
},
methods: {
onClick(event) { // Big Boss…… 不用过多解释了吧……
this.$parent.onChange(this.$parent.items.indexOf(this));
}
},
render(h) {
const { icon, $slots, active } = this;
const avtive = active ? this.$parent.activeColor + ' action' : 'action text-gray';
return (
<div onClick={this.onClick} class={avtive}>
<div class={icon}>
</div>
<span>{$slots.default}</span>
</div>
);
}
}
复制代码
App.vue
<Tabbar v-model="data" fixed :activeColor="'text-green'" :bgColor="'bg-black'">
<TabbarItem icon="icon-homefill">首页</TabbarItem>
<TabbarItem icon="icon-similar">分类</TabbarItem>
<TabbarItem icon="icon-cart">购物车</TabbarItem>
<TabbarItem icon="icon-my">个人</TabbarItem>
</Tabbar>
复制代码
还记得我上一篇文章说过Tabbar 是一个父容器么?
那么咱们能够把一些公用的属性放到父容器上面……
在子组件须要使用的时候 能够经过this.$parent 来获取父容器上的属性方法等等……
你也能够设置一个 默认不选中的颜色哟!
若是你想的话你也能够在每一个TabbarItem 上面加……
路由这个……就留到下一章把……毕竟有些人基础不是那么好。一会儿写太多内容不太好!
源码的话……