文件:元件基礎 | Vue.js (vuejs.org)
什麼是元件:
vue元件可以將一個複雜的應用程式(或者是頁面)拆分成多個小的模組,每個模組可以獨立的進行開發和測試。在Vue當中元件是透過虛擬DOM來實現的,可以將複雜的頁面拆分多個小的DOM節點,每個節點對應一個元件,然後這些元件組合成一個完整的頁面。
1.定義一個元件
當使用構建步驟時,我們一般會將 Vue 元件定義在一個單獨的 .vue 檔案中,這被叫做單檔案元件 (簡稱 SFC):
ButtonCounter.vue
<!-- 寫js程式碼,或者vue程式碼 --> <script setup> import { ref } from 'vue' // 定義元件可以接收的引數 // 引數為單向資料流 // ROOT <- Button <- Submit // ROOT -> Button -> Submit // step: 只能在父元件進行修改,不能在子元件進行修改 const props = defineProps({ // 定義引數 // 引數名: 引數資料型別 // step: Number step: { type: Number, // String, Array, Object // 必須要傳遞引數 // required: true, // 設定預設值 default: 8, // 自定義校驗規則 validator: function(value) { console.log("傳遞的引數是:", value) // true: 校驗透過 // false: 校驗失敗 // 傳遞的值必須要小於10 if (value<10) { return true } else { return false } } } }) const count = ref(0) const plus = ()=>{ count.value = count.value + props.step } </script> <!-- 寫html文件 --> <template> <div> <p>你傳遞的引數是: {{ props.step }}</p> <button class="button" @click="plus">You clicked me {{ count }} times.</button> </div> </template> <!-- 寫元件的樣式,scoped表示只對當前頁有效 --> <style scoped> .button{ font-size: 20px; background-color: aqua; } </style>
要使用一個子元件,我們需要在父元件中匯入它。
<script setup> import ButtonCounter from './ButtonCounter.vue' </script> <template> <h1>Here is a child component!</h1> <ButtonCounter :step="2" /> </template>
2.觸發與監聽事件
Message.vue
<!-- 寫js程式碼,或者vue程式碼 --> <script setup> import { ref } from 'vue' // 定義元件可以接收的引數 // 引數為單向資料流 const props = defineProps({ msg: { type: String, // String, Array, Object } }) const emit = defineEmits(['changeValue']) // 子元件內不能修改父元件的值 const modifyMsg = ()=>{ // 直接改不可以的 // props.msg = "這是透過子元件直接進行修改的值" // 透過事件讓父元件進行修改,changValue對應App.vue中的@change-value emit('changeValue',"這裡是傳到父元件的引數") } </script> <!-- 寫html文件 --> <template> <div> {{ msg }} <button placeholder="請輸入值" type="button" @click="modifyMsg">修改</button> </div> </template> <!-- 寫元件的樣式 --> <style scoped> .button{ font-size: 20px; background-color: aqua; } </style>
父元件App.vue
import Message from './components/Message.vue'; import { ref } from 'vue' const msg = ref("這是父元件傳遞的引數") const modify = (value) => { // 由父元件直接更改 // msg.value = "這是一個新值,由子元件觸發" // 接收引數進行修改 msg.value = value } <template> <Message :msg="msg" @change-value="modify"></Message> </template>
3.插槽
SlotDemo.vue
<script setup> import { onBeforeMount, onMounted,onBeforeUpdate,onUpdated, onBeforeUnmount ,onUnmounted } from 'vue'; // 插槽: 插槽是vue中一種特殊的機制,他可以讓我們在元件中定義可插入區域、 // 也就是可以在不同的地方插入不同的內容 // 可以讓一個通用的元件,展示不同的內容 // beforeUpdate --> onBeforeUpdate onBeforeUpdate( () => { console.log("鉤子函式: onBeforeUpdate") } ) // updated --> onUpdated onUpdated( () => { console.log("鉤子函式: onUpdated") } ) // beforeUnmount --> onBeforeUnmount , vue2: beforeDestory onBeforeUnmount( () => { console.log("鉤子函式: onBeforeUnmount") } ) // unmounted --> onUnmounted ,vue2: destroyed onUnmounted( () => { console.log("鉤子函式: onUnmounted") } ) </script> <template> <div> <!-- 定義一個插槽 --> <!-- name=default --> <!-- 具名插槽,命名插槽 --> <slot name="header"> <p>這是插槽的預設值</p> </slot> <slot name="main"> <p>這是插槽的預設值</p> </slot> <slot name="footer"> <p>這是插槽的預設值</p> </slot> </div> </template> <style> </style>
父元件App.vue
import SlotDemo from './components/SlotDemo.vue'; <template> <!-- 使用插槽這個元件 --> <SlotDemo> <!-- 第一種寫法 --> <template v-slot:header> <p>這是header頭定義</p> </template> <template #main> <div style="background-color: aqua; width: 200px; height: 200px;"> <p>這是main中內容</p> </div> </template> <template #footer> <p>尾部的定義</p> </template> </SlotDemo> </template>
4.釋出與訂閱
父元件ProvideInject.vue
<script setup> import MessageProvide from './MessageProvide.vue' import { provide, readonly, ref } from 'vue'; // 訂閱和釋出資料 // provide:用來發布資料 // inject:用來訂閱資料 let defaultMsg = ref("這是父元件釋出的資料") // 釋出一個資料 // provide語法: provide("釋出的命令","你要釋出誰") // 釋出資料 // provide('message', defaultMsg) // 釋出只讀資料 provide('message', readonly(defaultMsg)) // 釋出一個用於修改資料的函式 const modifyHandler = (newValue) => { defaultMsg.value = newValue } provide('modifyHandler',modifyHandler) </script> <template> <MessageProvide></MessageProvide> </template>
子元件MessageProvide.vue
<script setup> import { inject,ref, onBeforeMount, onMounted,onBeforeUpdate,onUpdated, onBeforeUnmount ,onUnmounted } from 'vue'; // 訂閱父元件釋出的資料 // inject語法: inject('資料的名字') let injectMsg = inject("message") // 訂閱父元件釋出的修改資料的函式 const changeValueHandler = inject("modifyHandler") let newMsg = ref('') const submit = ()=> { console.log("提交資料") // 也是可以直接透過子元件修改資料的 // injectMsg.value = newMsg.value // 不推薦 changeValueHandler(newMsg.value) } // beforeUpdate --> onBeforeUpdate onBeforeUpdate( () => { console.log("鉤子函式: onBeforeUpdate") } ) // updated --> onUpdated onUpdated( () => { console.log("鉤子函式: onUpdated") } ) // beforeUnmount --> onBeforeUnmount , vue2: beforeDestroy onBeforeUnmount( () => { console.log("鉤子函式: onBeforeUnmount") } ) // unmounted --> onUnmounted ,vue2: destroyed onUnmounted( () => { console.log("鉤子函式: onUnmounted") } ) </script> <template> <div> <p style="color: red;">{{ injectMsg }}</p> <input placeholder="請輸入新值" v-model="newMsg" /> <button type="button" style="background-color: aqua;" @click="submit">修改</button> </div> </template>
5.生命週期鉤子
生命週期鉤子 | Vue.js (vuejs.org)