有進階指令表示有基礎指令,在最早的第一篇 Vue3 筆記有提到 v-bind
,然後我就轟轟轟地連續數篇 Vue3 筆記飛過然後沒有再專門談過 vue 指令,但時不時還是在我的範例中看到使用,比如 v-on
。
主要是這些指令拉出來單獨開一篇個人覺得沒必要,我又不是 vue 官方文件 (笑。
所以這裡僅列出那些應該知道怎麼用的基礎 vue 指令,不做詳解:
v-bind
:綁定屬性。v-on
:綁定事件。v-if
, v-show
:條件渲染。v-for
:迭代渲染。watch
, watchEffect
:監聽。slot
:模板插槽。雖然之前講過 Vue 專案中要共用資料可以用 pinia,但假設現在我們不會 pinia 但仍然要把某組件的資料共享給比如它的曾曾曾曾...子孫組件,可以使用 Vue 原生提供的 provide-inject
方法來傳遞,避免 props
一堆到死的問題。
我們要在父組件引用 provide
:
<script setup>
import { ref, provide } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
const greeting = ref('hello world')
provide('msg', greeting)
</script>
<template>
<HelloWorld />
</template>
在子組件引用 inject
:
<script setup>
import { inject } from 'vue';
const msg = inject('msg')
</script>
<template>
<h1>{{ msg }}</h1>
</template>
之後就可以看到畫面成功渲染 Hello World!
我們可以自行定義 v-
指令來幫助我們簡化程式碼快速開發。
以官網的例子來說,我們可以在 main.js 掛上一個自定義的 hook,然後就可以在組件中使用它:
Main.js:
app.directive('color', (el, binding) => {
el.style.color = binding.value
})
App.vue:
<div v-color="'red'">maybe will change color</div>
可以看到這個 <div> 成功套用我們自定義的 v-color 內部邏輯。
這是一個 Vue 提供的內置組件,可以快速地製作一些轉場動畫。基本上 Transition
的運作基於 6 個內建的 css class
:
v-enter-from
:動畫起始階段。v-enter-active
:動畫運作階段。v-enter-to
:動畫結束階段。v-leave-from
:動畫消失起始階段。v-leave-active
:動畫消失運作階段。v-leave-to
:動畫消失結束階段看一下官方提供的範例 code 會更清楚這些 class 的書寫邏輯:
<script setup>
import { ref } from 'vue'
const show = ref(true)
</script>
<template name="hello">
<button @click="show = !show">click</button>
<Transition>
<p v-if="show">hello</p>
</Transition>
</template>
<style scoped>
.hello-enter-active,
.hello-leave-active{
transition: opacity 0.5s ease;;
}
.hello-enter-from,
.hello-leave-to{
opacity: 0;
}
.hello-enter-to,
.hello-leave-from{
opacity: 1;
}
</style>
總而言之,包在 Transition
內部的元素或組件都可以享受到這樣一個轉場的服務,更多進階操作建議看官網。
而如果是要渲染像 list 這類的內容,我指比如 v-for
之類的,可以使用 Transition
的兄弟 TransitionGroup
。
這個內置組件幫助我們在切換元件時,仍然保留其內部狀態不被重置。用官方的 code 一步步拆解。
首先有 A、B 兩個元件,內部各自都帶有自己的狀態:
CompA:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<p>Current component: A</p>
<span>count: {{ count }}</span>
<button @click="count++">+</button>
</template>
CompB:
<script setup>
import { ref } from 'vue'
const msg = ref('')
</script>
<template>
<p>Current component: B</p>
<span>Message is: {{ msg }}</span>
<input v-model="msg">
</template>
通常來說,當這兩個組件在切換時因為會從 DOM 上被卸載,所以重新載入時一切會回歸預設狀態,但如果在父組件中用 KeepAlive
把他們包起來就可以讓他們的狀態不被解除:
<script setup>
import { shallowRef } from 'vue'
import CompA from './components/CompA.vue'
import CompB from './components/CompB.vue'
const current = shallowRef(CompA)
</script>
<template>
<div class="demo">
<label><input type="radio" v-model="current" :value="CompA" /> A</label>
<label><input type="radio" v-model="current" :value="CompB" /> B</label>
<KeepAlive>
<component :is="current"></component>
</KeepAlive>
</div>
</template>
這個內置組件可以想像成一個傳送門,可以咻~地把一個元件深層的模板給傳送指定的 DOM 位置。
這項功能比較常用在建立彈出視窗等元件上。想像一下這個元件被很多父元件層層包裹,那有時難免它的 css 位置也會受到干擾,而 Teleport
就是來解決這樣的事情。通俗點說,就是避免跑版 www
舉例來說,這段 code 的意思就是把 Teleport
內部的東西給傳送到 body 上:
<Teleport to="body">
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</Teleport>