vue循环tabs标签页组件_如何在Vue.js中实现标签页组件详解前⾔
标签页组件,即实现选项卡切换,常⽤于平级内容的收纳与展⽰。
因为每个标签页的内容是由使⽤组件的⽗级控制的,即这部分内容为⼀个 slot。所以⼀般的设计⽅案是,在 slot 中定义多个 div,然后在接到切换消息时,再显⽰或隐藏相关的 div。这⾥⾯就把相关的交互逻辑也编写进来了,我们希望在组件中处理这些交互逻辑,slot 只单纯处理业务逻辑。这可以通过再定义⼀个 pane 组件来实现,pane 组件嵌在 tabs 组件中。
1 基础版
因为 tabs 组件中的标题是在 pane 组件中定义的,所以在初始化或者动态变化标题时,tabs 组件需要从 pane 组件中获取标题。
html:
标签页组件
⽕星疑似发现“外星⼈墓地”?⾄今⽆法解释
全美沸腾!湖⼈队4年1.2亿迎顶级后卫,詹姆斯:有他就能夺冠
阿⽶尔汗谈中国武侠 想拍印度版《⿅⿍记》
var app = new Vue({
el: '#app',
data: {
activeIndex: 0
}
});
pane 组件:
Vueponent('pane', {
name: 'pane',
template: '\
\
\
\
',
props: {
//标题
label: {
type: String,
default: ''
}
},
data: function () {
return {
//显⽰或隐藏
isShow: true
}
},
methods: {
//通知⽗组件,更新标题
init() {
this.$parent.init();
}
},
watch: {
//当 label 值发⽣变化时,更新标题
label() {
this.init();
}
},
//挂载时,更新标题
mounted() {
this.init();
}
});
在 pane 组件中,我们做了以下设计:
因为 pane 组件需要控制标签页内容的显⽰与隐藏,所以我们在 data 中定义了⼀个 isShow,并⽤ v-show 指令来控制内容的显⽰或隐藏。当点击这个 pane 所对应的标签页标题时,它的 isShow 被设置为 true。
我们需要⼀个标识来识别不同的标签页标题,本⽰例⽤的是 pane 组件定义顺序的索引。
在 props 中定义了 label,⽤于存放标题。因为 label 可以动态变化,所以必须在挂载 pane 以及当 label 值发⽣变化(通过监听实现)时,通知⽗组件,重新初始化标题。因为 pane 是独⽴组件,所以这⾥使⽤了 this.$parent 来调⽤⽗组件 tabs 的初始化⽅法。
tabs 组件:
Vueponent('tabs', {
template: '\
\
\
\
v-for="(item, index) in titleList"\
@click="change(index)">\
{{ item.label }}\
\
\
\
\
\
\
',
props: {
value: {
type: [String, Number]
}
},
data: function () {
return {
currentIndex: this.value,
titleList: []//存放标题
}
},
methods: {
//设置样式
tabClass: function (item) {
return ['tabs-tab', {
//为当前选中的 tab 添加选中样式
'tabs-tab-active': (item.name === this.currentIndex) }]
},
//获取定义的所有 pane 组件
getTabs() {
return this.$children.filter(function (item) {
return item.$options.name === 'pane';
})
},
//更新 pane 是否显⽰状态
updateIsShowStatus() {
var tabs = Tabs();
var that = this;
//迭代判断并设置某个标签页是显⽰还是隐藏状态tabs.forEach(function (tab, index) {
return tab.isShow = (index === that.currentIndex); })
},
//初始化
init() {
/**
* 初始化标题数组
*/
this.titleList = [];
var that = this;//设置 this 引⽤
label: tab.label,
name: index
});
//初始化默认选中的 tab 索引
if (index === 0) {
if (!that.currentIndex) {
that.currentIndex = index;
}
}
});
this.updateIsShowStatus();
},
//点击 tab 标题时,更新 value 值为相应的索引值change: function (index) {
var nav = this.titleList[index];
var name = nav.name;
this.$emit('input', name);
}
},
watch: {
//当 value 值发⽣改变时,更新 currentIndex
value: function (val) {
this.currentIndex = val;
},
//当 currentIndex 值发⽣改变时,更新 pane 是否显⽰状态
currentIndex: function () {
this.updateIsShowStatus();
}
}
});
getTabs() 中通过 this.$children 来获取定义的所有 pane 组件。因为很多地⽅都会⽤到getTabs() ,所以这⾥把它单独定义出来。
注意: methods 中如果存在回调函数,那么需要在外层事先定义⼀个 var that = this;,在 that 中引⽤ Vue 实例本⾝,也可以使⽤
ES2015 的箭头函数。
在初始化⽅法中,我们通过迭代 pane 组件,初始化了标题数组,label 取定义的标题,name 取所在的索引。 标题数组⽤于模板定义中。
updateIsShowStatus() ⽤于更新 tab 是否显⽰状态。之所以独⽴出来,是为了在监听 currentIndex 发⽣变化时,也能调⽤该⽅法。
在模板定义中,我们使⽤ v-for 指令渲染出标题,并绑定了 tabClass 函数,从⽽实现了动态设置样式。因为需要传参,所以不能使⽤计算属性。
点击每⼀个 tab 标题时,会触发 change(),来更新 value 值为相应的索引值。在 watch 中,我们监听了 value 值,当 value 值发⽣改变时,更新 currentIndex。也监听了 currentIndex 值,当 currentIndex 值发⽣改变时,更新 pane 是否显⽰状态。
总结如下:
使⽤组件嵌套⽅式,将多个 pane 组件作为 tabs 组件的 slot。position标签属性
tabs 组件与 pane 组件,通过⽗⼦链(即 $parent 与 $children)实现通信。
样式:
[v-cloak] {
display: none;
}
.
tabs {
font-size: 14px;
color: #657180;
}
.tabs-bar:after {
content: '';
display: block;
width: 100%;
height: 1px;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论