【前端】vue阶段案例:父子组件通信-tabControl栏

阶段案例系列:

案例链接
【前端】vue阶段案例:购物车https://blog.csdn.net/karshey/article/details/127473654
【前端】vue阶段案例:父子组件通信-tabControl栏https://blog.csdn.net/karshey/article/details/127480941
【前端】vue阶段案例:组件化-房源展示https://blog.csdn.net/karshey/article/details/127520175
【前端】vue阶段案例:vue-router使用流程https://blog.csdn.net/karshey/article/details/127554171

目标

在这里插入图片描述

  • 移动端
  • 点击tab栏对应选项,则对应选项变红,有下边框,且显示相应页面
  • 这里我们点衣服则显示"衣服页面",以此类推,要排它
  • 用flex布局

代码

0.结构:数据父传子

在这里要完成的:要把结构写出来。

  • 由于是动态的数据,我们不能直接把数据写死
  • 而是要通过 父传子 的通信方式,把数据从App.vue传给TabControl.vue,用v-for循环显示
  • 如何父传子:父写在自己的动态绑定的属性attribute里,子在props属性里接收
  • 用flex布局

App.vue:

<template>
    <div class="app">
        <!-- tabControl栏 -->
        <tab-control :titles="['衣服','裤子','鞋子']"></tab-control>
        <!-- 页面内容 -->
    </div>
</template>

<script>
import TabControl from './TabControl.vue'
export default {
    components:{
        TabControl
    },
    data:function(){
        return{
            
        }
    }
}
</script>

<style>

</style>

组件TabControl.vue:

<template>
    <div class="tab-control">
        <template v-for="(item, index) in titles" :key="index">
            <div class="tab-control-item">
                <span>
                    {{ item }}
                </span>
            </div>
        </template>
    </div>
</template>

<script>
export default {
    // 通信:父传子
    props: {
        titles: {
            type: Array,
            // 如果参数为空则返回空数组
            default: () => { }
        }
    }
}
</script>

<style>
.tab-control {
    display: flex;
    height: 44px;
    line-height: 44px;
    text-align: center;
}

.tab-control .tab-control-item {
    flex: 1;
}
</style>

效果:
在这里插入图片描述

1.点击改变样式:排它

效果:点哪里,哪里就显示红色,且有下划线。

在tab栏的item这里添加active类和点击事件:

<div :class="{active:currentIndex===index}" 
@click="itemClick(index)" class="tab-control-item">

添加currentIndex数据和itemClick方法:

export default {
    // 通信:父传子
    props: {
        titles: {
            type: Array,
            // 如果参数为空则返回空数组
            default: () => { }
        }
    },
    data:function(){
        return{
            // 排它的下标
            currentIndex:-1
        }
    },
    methods:{
        itemClick:function(index){
            this.currentIndex=index;
        }
    }
}

active后的css样式:

.active {
    color:red;
}

.active span {
    border-bottom:2px solid red ;
    padding:0 10px;
}

效果:
在这里插入图片描述

2.点击改变页面内容:子传父

效果:点”衣服“,则显示”衣服页面“,以此类推。

子传父:把事件tabItemClick传给父,且参数为index

methods:{
   itemClick:function(index){
       this.currentIndex=index;
       // 子传父:事件名称,参数
       this.$emit("tabItemClick",index)
   }
}

于是父要监听事件tabItemClick:

<tab-control @tabItemClick="tabItemClick" 
:titles="['衣服','裤子','鞋子']"></tab-control>

当触发事件tabItemClick后就执行函数tabItemClick:目的是显示对应的页面。

data:function(){
    return{
        currentIndex:-1,
        pageContent:['衣服页面','裤子页面','鞋子页面']
    }
},
methods:{
    // 这里的index是子传父时的参数
    tabItemClick:function(index){
        // 显示对应参数的页面,这里的currentIndex是数组下标
        this.currentIndex=index
    }
}

html:

<!-- 页面内容 -->
<h1>{{pageContent[currentIndex]}}</h1>

效果:
在这里插入图片描述

总代码

父App.vue

<template>
    <div class="app">
        <!-- tabControl栏 -->
        <tab-control @tabItemClick="tabItemClick" :titles="['衣服','裤子','鞋子']"></tab-control>
        <!-- 页面内容 -->
        <h1>{{pageContent[currentIndex]}}</h1>
    </div>
</template>

<script>
import TabControl from './TabControl.vue'
export default {
    components:{
        TabControl
    },
    data:function(){
        return{
            currentIndex:-1,
            pageContent:['衣服页面','裤子页面','鞋子页面']
        }
    },
    methods:{
        // 这里的index是子传父时的参数
        tabItemClick:function(index){
            // 显示对应参数的页面,这里的currentIndex是数组下标
            this.currentIndex=index
        }
    }
}
</script>

<style>

</style>

子TabControl.vue

<template>
    <div class="tab-control">
        <template v-for="(item, index) in titles" :key="index">
            <div :class="{active:currentIndex===index}" @click="itemClick(index)" class="tab-control-item">
                <span>
                    {{ item }}
                </span>
            </div>
        </template>
    </div>
</template>

<script>
export default {
    // 通信:父传子
    props: {
        titles: {
            type: Array,
            // 如果参数为空则返回空数组
            default: () => { }
        }
    },
    data:function(){
        return{
            // 排它的下标
            currentIndex:-1
        }
    },
    methods:{
        itemClick:function(index){
            this.currentIndex=index;
            // 子传父:事件名称,参数
            this.$emit("tabItemClick",index)
        }
    }
}
</script>

<style>
.tab-control {
    display: flex;
    height: 44px;
    line-height: 44px;
    text-align: center;
}

.tab-control .tab-control-item {
    flex: 1;
}

.active {
    color:red;
}

.active span {
    border-bottom:2px solid red ;
    padding:0 10px;
}
</style>

参考

Vue组件之间的通信-父传子-子传父

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值