这章节是延伸v-if和v-show管理元件,如何用更简便的方式做tab页签。
做一个tab
按钮切会下面显示的内容,直觉的方式是直接用v-if
去写三个元件
<button v-for="tab in tabs"
:key="tab"
@click="currentTab = tab"
:class="{'active': currentTab === tab}">
{{tab}}
</button>
<tab-a v-if="currentTab === 'A'"></tab-a>
<tab-b v-if="currentTab === 'B'"></tab-b>
<tab-c v-if="currentTab === 'C'"></tab-c>
const app = Vue.createApp({
data() {
return {
currentTab: 'A',
tabs: ['A', 'B', 'C']
}
}
});
app.component('tab-a', {
template: `
<h1>aaaaaaaaaaaaaaaaaa</h1>
`
})
app.component('tab-b', {
template: `
<h1>bbbbbbbbbbbbbbbbbb</h1>
`
})
app.component('tab-c', {
template: `
<h1>ccccccccccccccccc</h1>
`
})
用更快的方式就是使用v-bind:is
,新增一个computed
,当点击按钮时会触发currentTab = tab
,此时新的tab
就会传到:is="currentTabComponent"
身上,即显示出与用v-if
一样的结果。
<button v-for="tab in tabs"
:key="tab"
@click="currentTab = tab"
:class="{'active': currentTab === tab}">
{{tab}}
</button>
<component :is="currentTabComponent"></component>
const app = Vue.createApp({
data() {
return {
currentTab: 'A',
tabs: ['A', 'B', 'C']
}
},
computed: {
currentTabComponent() {
return `tab-${this.currentTab.toLowerCase()}`;
}
}
});
app.component('tab-a', {
template: `<h1>aaaaaaaaaaaaaaaaaa</h1>`
})
app.component('tab-b', {
template: `<h1>bbbbbbbbbbbbbbbbbb</h1>`
})
app.component('tab-c', {
template: `<h1>ccccccccccccccccc</h1>`
})
改写刚刚的tab页签,内容物改成v-model
绑定的input
可以改写资料。
改写资料後按下其它标签会发先先前改写的资料会被还原成初始值。
app.component('tab-a', {
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'A component' })
})
app.component('tab-b', {
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'B component' })
})
app.component('tab-c', {
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'C component' })
})
若想让资料在切换时也能保持改写後的样子,就可以在外层包上keep-alive
。
<keep-alive>
<component :is="currentTabComponent"></component>
</keep-alive>
补充: keep-alive
同一时间只会有一个子元件被渲染
使用时必须搭配name
属性
<!-- 写法一:逗点格开 -->
<keep-alive include="A-TAB,B-TAB">
<component :is="currentTabComponent"></component>
</keep-alive>
<!-- 写法二:Regular expression -->
<keep-alive :include="/(A|B)-TAB/">
<component :is="currentTabComponent"></component>
</keep-alive>
<!-- 写法三:阵列 -->
<keep-alive :include="['A-TAB','B-TAB']">
<component :is="currentTabComponent"></component>
</keep-alive>
app.component('tab-a', {
name: 'A-TAB',
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'A component' })
})
app.component('tab-b', {
name: 'B-TAB',
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'B component' })
})
app.component('tab-c', {
name: 'C-TAB',
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'C component' })
})
只保留最後引入的两个状态
<keep-alive :max="2">
<component :is="currentTabComponent"></component>
</keep-alive>
生命周期中activated
与deactivated
两个hooks是给keep-alive使用的。
直接比对有和无keep-alive的差异在生命周期上有什麽不同。
做了同样的动作: 点击A标签→B标签→C标签
有keep-alive
切换时的顺序为「建立新元件created」→「暂停目前元件 deactivated」→「挂载新的元件 mounted」→「启用新的元件 activated」
无keep-alive
切换时的顺序为「建立新元件created」→「销毁目前元件 unmounted」→「挂载新的元件 mounted」
const app = Vue.createApp({
data() {
return {
currentTab: 'A',
tabs: ['A', 'B', 'C'],
msgs: []
}
},
computed: {
currentTabComponent() {
return `tab-${this.currentTab.toLowerCase()}`;
}
},
methods: {
notify(val) {
this.msgs.push(val)
}
},
});
app.component('tab-a', {
name: 'A-TAB',
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'A component' }),
created() {
this.$emit('update', `${this.$options.name} Created`)
},
mounted() {
this.$emit('update', `${this.$options.name} Mounted`)
},
unmounted() {
this.$emit('update', `${this.$options.name} Unmounted`)
},
activated() {
this.$emit('update', `${this.$options.name} Activated`)
},
deactivated() {
this.$emit('update', `${this.$options.name} Deactivated`)
}
})
app.component('tab-b', {
name: 'B-TAB',
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'B component' }),
created() {
this.$emit('update', `${this.$options.name} Created`)
},
mounted() {
this.$emit('update', `${this.$options.name} Mounted`)
},
unmounted() {
this.$emit('update', `${this.$options.name} Unmounted`)
},
activated() {
this.$emit('update', `${this.$options.name} Activated`)
},
deactivated() {
this.$emit('update', `${this.$options.name} Deactivated`)
}
})
app.component('tab-c', {
name: 'C-TAB',
template: `<input type="text" v-model="title">`,
data: () => ({ title: 'C component' }),
created() {
this.$emit('update', `${this.$options.name} Created`)
},
mounted() {
this.$emit('update', `${this.$options.name} Mounted`)
},
unmounted() {
this.$emit('update', `${this.$options.name} Unmounted`)
},
activated() {
this.$emit('update', `${this.$options.name} Activated`)
},
deactivated() {
this.$emit('update', `${this.$options.name} Deactivated`)
}
})
<<: Spring Framework X Kotlin Day 21 WebSocket
>>: Day11 为什麽电脑能自动完成指令 - Lua 的多值回传
Q: 这个看起来像猫爪的东西是什麽? A: 喵? 本篇开始将实作选单的微动画,比较特别的要来说说t...
我们在进到主题前先来看一段程序码,随後在开发人员工具中观察执行过程 function doSomet...
相信网路上其实已经有不少文章在谈架构了,我的资历也尚浅,今天虽然会介绍架构,但是主要会侧重的点会是...
今天要来聊标签Label方法,这个部分会分成两个主题来讲,今天会先讲widget的共通属性,明天会讲...
前言 目前标签页面的画面及功能已经完成,接下来继续新增「重复」页面,算是再熟悉一下TableView...