您的位置:首页 > Web前端 > Vue.js

Vue实战--标签页组件

2019-07-09 10:30 246 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_42874245/article/details/95171996

  好久没有写文章了,这一段时间在忙着准备期末考试和找实习,上周已经在一家公司开始实习了,公司是用Vue开发项目,Boss让我们实习生看几个项目的代码,第一次接触完整的上线项目,发现代码结构分的很细,几乎每个文件都在使用export、import导入导出,有些Vue用法是之前没有接触过的,实习一周下来看代码看的有点蒙。。。所以打算利用空余时间,重新学习Vue,至少一周写一篇Vue实践总结~

这是我第一次在CSDN写文章,有些地方可能有误或描述不清楚,请谅解。本篇文章首发于掘金

  Vue作为一个前端轻量级的MVVM框架,组件化是其一个重要的功能和特点,组件化的优点是显而易见的,一个页面的不同部分可以拆分成独立的组件,然后在不同的页面就可以共享这些组件,避免重复开发。下面是我编写的一个标签页组件,先上最终效果图~

组件文件结构

  • index.html 入口页
  • style.css 样式页
  • tab.js 标签页组件 tabs
  • pane.js 标签页组件 pane

初始化各个文件

index.js:

<html>
<head>
<meta charset="UTF-8">
<title>标签页组件</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app" v-cloak>
<tabs v-model="activeKey">
<pane label="标签一" name="1">
标签一的内容
</pane>
<pane label="标签二" name="2" :closable="false">
标签二的内容很重要,不能关闭
</pane>
<pane label="标签三" name="3">
标签三的内容
</pane>
</tabs>
</div>
<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
<script src="pane.js"></script>
<script src="tabs.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
activeKey: '1'
}
})
</script>
</body>
</html>

tab.js:

Vue.component('tabs',{
template:'\
<div class="tabs">\
<div class="tabs-bar">\
<!--标签页的标题,需要使用v-for-->\
<div \
</div>\
</div>\
<div class="tabs-content">\
<!--这里的slot即是嵌套的pane组件-->\
<sl
3ff7
ot></slot>\
</div>\
</div>',
})

pane.js

Vue.component('pane',{
name:'pane',
template: '\
<div>\
<slot></slot>\
</div>',
data: function(){
return{
show:true
}
}
})

pane需要控制标签页内容的显示与隐藏,设置一个data:show,通过这个属性来动态添加class

功能实现

在pane.js里设置

prop: name
唯一的值来标识这个 pane,但它不是必需的,如果使用者不设置,可以默认从0开始自动设置;设置
prop: label
其内容显示在标签页标题里;还有
prop: closable
用来是否显示关闭标签按钮。这部分代码如下:

props:{
name: {
type:String
},
label: {
type:String,
default:''
},
closable: {
type: Boolean,
default: true
}
}

由于上面的

prop: label
用户是可以动态调整的,所以在pane初始化及label更新时,都要通知父组件更新,更新方法定为
updateNav

methods:{
updateNav (){
this.$parent.updateNav();
}
},
watch:{
label(){
this.updateNav();
}
},
mounted(){
this.updateNav();
}

pane.js功能基本实现了,剩余任务就是完成tabs.js组件。
首先需要把pane组件设置的标题动态谊染出来,也就是当pane触发tabs的updateNav方法时,更新标题内容。这部分的代码:

methods: {
getTabs () {
// 通过遍历子组件,得到所有的pane组件
return this.$children.filter(function(item){
return item.$options.name==='pane';
})
},
updateNav () {
this.navList=[];
var _this=this;
this.getTabs().forEach(function(pane,index){
_this.navList.push({
label: pane.label,
name: pane.name||index,
closable: pane.closable
});
if(!pane.name){
pane.name=index;
}
if(index==0){
if(!_this.currentValue){
_this.currentValue=pane.name||index;
}
}
});
this.updateStatus();
},
updateStatus () {
var tabs=this.getTabs();
var _this=this;
// 显示当前选中的tab对应的pane组件
tabs.forEach(function(tab){
return tab.show = tab.name === _this.currentValue;
})
}
}

拿到navList后,就需要对它用v-for指令把tab的标题渲染出来,并且判断每个tab当前的状态:是否选择,是否可以关闭。这部分代码如下:

Vue.component('tabs',{
template:' \
<div class="tabs"> \
<div class="tabs-bar"> \
<div \
:class="tabCls(item)" \
v-for="(item,index) in navList" \
@click="handleChange(index)">\
{{item.label}} \
<span v-if="ifShowClose(item)" class="close icon" @click.stop="closeTab(index)"></span> \
</div> \
</div> \
<div class="tabs-content"> \
<slot></slot> \
</div> \
</div>'
})

上面标签绑定了三个方法:

handleChange
,
ifShowClose
,
closeTab
,其代码如下

handleChange: function(index){
var nav=this.navList[index];
var name=nav.name;
// 更新当前选择的tab
this.currentValue=name;
// 更新value
this.$emit('input',name);
},
ifShowClose (item) {
// 是否显示关闭标签按钮
return item.closable;
},
// 点击关闭按钮触发的事件
closeTab (index) {
// console.log(this.navList[index].name, this.currentValue);
// 如果关闭的是当前选择的tab,则将currentValue转到前一个tab
if (this.navList[index].name == this.<
4000
/span>currentValue) {
let toIndex = index - 1;
toIndex = toIndex >=0 ? toIndex : this.navList.length + toIndex;
console.log(toIndex);
this.currentValue = this.navList[toIndex].name;
}
//关闭当前标签页
this.navList.splice(index, 1);
}

另外通过CSS3的

transform: translateX
来增加标签页内容切换动画:

.pane {
visibility: hidden;
width: 100%;
height: 0;
transform: translateX(-100%);
transition: all .5s ease-in;
}
.pane-active {
visibility: visible;
transform: translateX(0);
}

完整代码

完整代码已经上传到github上了,传送门

最后

  以上是该组件的基本实现,这是我结合《Vue.js实战》这本书完成的,通过这个实例,巩固了Vue的一些基本用法,对Vue的组件化思想有了更清晰的认识。另外这是我第一次在CSDN写文章,有些地方可能有误或描述不清楚,请谅解。个人感觉标签页切换动画比较生硬,如果有更好的实现方法欢迎提出了~

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: