vue实现一个简单的tab-panel组件
tab-panel组件主要涉及到vue的插槽和父子组件间值的传递。
组件demo位置:https://github.com/xmyxiao/WebDemo/tree/master/vueDemo/demo/web-design/src/components/tabpanel
子组件:
<template>
<div class="des-tabpanel">
<ul class="tab-head">
<li class="item" :class="{'selected':selectItem === index}" v-for="(item,index) in navList" @click="itemSelect(index)">
<div v-if="index===0" class="background-cube"></div>
<div class="text">{{item.text}}</div>
</li>
</ul>
<div class="tab-body">
<slot name="content"></slot>
</div>
</div>
</template>
<script>
export default {
name:"des-tabs",
props: {
//选中标签
selectItem: {
type: Number,
default: 0
},
navList : {
type : Array,
required : true
}
},
methods:{
itemSelect(index){
this.$emit("selectPanel",index);
var translateX = index * 100 + "%";
this.$el.querySelector('.background-cube').style = "transform: translateX("+translateX+");"
}
}
}
</script>
<style lang="scss" scoped>
.des-tabpanel{
height: 100%;
width: 100%;
>.tab-head{
display: -webkit-flex;
display: -ms-flex;
display: flex;
height: 40px;
background: #F2F2F3;
list-style: none;
margin: 0;
padding: 0;
>.item{
position: relative;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: pointer;
list-style: none;
padding: 0 10px;
>.background-cube{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: calc(100% + 1px);
background: #fff;
transition: all 0.4s ease-in-out;
z-index: 5;
}
>.text{
width: 100%;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color:#0e90d2;
z-index: 10;
}
}
>.item.selected>.text{
color:#333;
}
}
>.tab-body{
height: -webkit-calc(100% - 40px);
height: -moz-calc(100% - 40px);
height: calc(100% - 40px);
background: #fff;
>.item{
position: relative;
height: 100%;
overflow: hidden;
}
}
}
</style>
在父组件中的引用:
<desTabs v-bind="tabOps" @selectPanel = "setDesTab">
<template slot="content">
<div v-show="tabOps.selectItem===0" class="item">
面板1
</div>
<div v-show="tabOps.selectItem===1" class="item">
面板2
</div>
</template>
</desTabs>
<script>
import desTabs from './components/tabPanel/index.vue'
export default {
name: 'App',
components:{
desTabs
},
data: function (){
return {
tabOps:{
navList : [
{
text:"面板1"
},
{
text:"面板2"
}
],
selectItem : 0
}
}
},
methods:{
setDesTab(val){//设置显示面板
this.tabOps.selectItem = val;
}
}
}
</script>
这里使用到具名插槽来传递父组件中的html结构,关于插槽可以看这里,简单来说就是默认插槽直接接收所有父组件传过来的html模板,然后渲染在插槽的位置,具名插槽如上述所写,父组件中使用 slot="content"
来标识要传递到子组件的那个插槽位置,子组件则通过<slot name="content"></slot>
来接收父组件传过来的html模板。最后一个作用域插槽则是可以理解为一个带数据的插槽,与其他两个插槽的区别就是:作用域插槽只提供模板,不提供数据,数据由子模板产生。例如具名插槽中<div v-show="tabOps.selectItem===1" class="item"> 面板1 </div>
这里的面板1就是数据,而div就是模板,具名插槽和默认插槽需要提供模板和数据,作用域插槽则只提供模板,数据由子组件填充。
父子间的值传递主要通过props,父组件通过<desTabs v-bind="tabOps" @selectPanel = "setDesTab">
中的v-bind向子组件传递一个tabOps对象,子组件通过props来接收父组件传递的数据,子组件再通过this.$emit("selectPanel",index);
来触发父组件的方法从而修改父组件的数据。
更多推荐
所有评论(0)