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);来触发父组件的方法从而修改父组件的数据。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐