一个tab页组建,包括三个文件,在tabs.js中,为何要 this.$emit('input',name)?
请输入代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style type="text/css" href="style.css"></style>
<title>vue</title>
</head>
<body>
<div id="app">
<tabs v-model="activeKey">
<pane label="标签1" name='1' >
标签 1的内容
</pane>
<pane label="标签2" name='2' >
标签 2的内容
</pane>
<pane label="标签3" name='3' >
标签 3的内容
</pane>
</tabs>
</div>
<script src='../vue.js'></script>
<script type="text/javascript" src="pane.js"></script>
<script type="text/javascript" src="tab.js"></script>
<script>
var app=new Vue({
el:'#app',
data(){
return {
activeKey:1
}
}
})
</script>
</body>
</html>
pane.js 文件
//label是标签页的标题,当其发生改变时候需要通知父组件进行更新。
Vue.component('pane',{
template:
`
<div class="pane" v-show="show">
<slot></slot>
</div>
`,
props:{
label:{
type:String,
default:''
},
name:{
type:String
}
},
data(){
return {
show:true
}
},
methods:{
updateNav(){
this.$parent.updateNav();
}
},
watch:{
label(){
this.updateNav();
}
},
mounted(){
this.updateNav();
}
});
tabs.js
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}}
</div>
</div>
<div class="tab-content">
<slot></slot>
</div>
</div>
`,
props:{
//为了可以使用v-model
value:{
type:[String,Number]
}
},
data(){
return {
//用于渲染tabs的标题
navList:[],
currentValue:this.value
}
},
methods:{
tabCls(item){
return ['tabs-tab',
{
'tabs-tab-active' : item.name===this.currentValue
}
]
},
//点击标题时候触发
handleChange(index){
var nav=this.navList[index];
var name=nav.name;
//改变当前选中的tab,并触发下面的watch
this.currentValue=name;
//更新value?
this.$emit('input',name);
},
getTabs(){
//遍历子组件,获得所有的pane组建
console.log(this)
console.log(this.$children);
return this.$children.filter(item=>item.$options.name==='pane')
},
updateNav(){
this.navList=[];
this.getTabs().forEach((pane,index)=>{
this.navList.push({
label:pane.label,
name:pane.name || index
});
//如果panel没有name,则默认给索引
if(!pane.name){
pane.name=index;
}
//设置当前的索引
if(index===0){
if(!this.currentValue){
this.currentValue=pane.name || index;
}
}
});
this.updateStatus();
},
updateStatus(){
var tabs=this.getTabs();
tabs.forEach(tab=>{
return tab.show=tab.name===this.currentValue;
})
}
},
watch:{
value(val){
this.currentValue=val;
},
currentValue(){
//当亲选中的tab改变时候,需要更新panel的显示状态
this.updateStatus();
}
}
})
你的
tabs
组件中v-model
拆解后就是这样的然后用
this.$emit('input',name)
就是你每次点击时候要将父组件中的activeKey
更新。