Components
Computed Properties
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</div>
Vue.createApp({
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery',
],
},
}
},
computed: {
// 计算属性的 getter
publishedBooksMessage() {
// `this` 指向 vm 实例
return this.author.books.length > 0 ? 'Yes' : 'No'
},
fullName: {
// getter
get() {
return `${this.firstName} ${this.lastName}`
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
},
},
},
}).mount('#computed-basics')
Slots
- Web Slot
nameattribute.fallbackcontent.- 插槽基本目的为自定义组件渲染细节: e.g. 高级列表组件.
- Normal Slots: 在父组件编译和渲染阶段生成 Slots VNodes, 数据作用域为父组件实例 (使用插槽的组件), 即父组件同时提供 View 与 Data.
- Scoped Slots:
在父组件编译和渲染阶段为
vnode.data添加scopedSlots对象, 在子组件编译和渲染阶段生成 Slots VNodes, 数据作用域为子组件实例 (定义插槽的组件), 即父组件提供 View, 子组件提供 Data.
Fallback Slots
<!-- SubmitButton -->
<button type="submit">
<slot>Submit</slot>
</button>
<SubmitButton></SubmitButton>
render to
<button type="submit">Submit</button>
<SubmitButton>Save</SubmitButton>
render to
<button type="submit">Save</button>
Named Slots
#:v-slotdirective shorthand.
<!-- Layout -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
<Layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</Layout>
Named slot directive shorthand:
<Layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</Layout>
Scoped Slots
Pass data from child to parent
(like Render Props in React):
app.component('TodoList', {
data() {
return {
items: ['Feed a cat', 'Buy milk'],
}
},
template: `
<ul>
<li v-for="( item, index ) in items">
<slot :item="item"></slot>
</li>
</ul>
`,
})
<TodoList>
<!-- `default` can be other named slots -->
<template v-slot:default="slotProps">
<i class="fas fa-check"></i>
<span class="green">{{ slotProps.item }}</span>
</template>
</TodoList>
Slot props shorthand
(default can be other named slots):
<TodoList v-slot="slotProps">
<i class="fas fa-check"></i>
<span class="green">{{ slotProps.item }}</span>
</TodoList>
<TodoList v-slot="{ item }">
<i class="fas fa-check"></i>
<span class="green">{{ item }}</span>
</TodoList>
<TodoList v-slot="{ item: todo }">
<i class="fas fa-check"></i>
<span class="green">{{ todo }}</span>
</TodoList>
<TodoList v-slot="{ item = 'Placeholder' }">
<i class="fas fa-check"></i>
<span class="green">{{ item }}</span>
</TodoList>
<TodoList #default="{ item }">
<i class="fas fa-check"></i>
<span class="green">{{ item }}</span>
</TodoList>
Provide and Inject
Root provide context value:
import { provide, ref } from 'vue'
const count = ref(0)
provide('key', count)
Child inject context value:
import { inject } from 'vue'
const message = inject('message', defaultValue)