引用Vue Components的原則,是透過父元件上import的方式,父元件中也可能存在許多子元件…這樣一個串一個的關係就成了樹狀結構的「元件樹」。今天我們要來學的就是在這個元件樹上面,組件彼此是如何傳遞資料的?
我們有一個計次按鈕的組件,希望它透過不同頁面引入時呈現不同的文字顏色,這時候就可以在按鈕組件中定義一個Prop當作接口,接收外部傳來的資料:
//CountTest.vue
<script setup>
    import { ref } from 'vue'
    const count = ref(0)
    const props = defineProps(['color']) //定義Props中有一個color
</script>
<template>
    <div>
        <text>
            <button @click="count++" :style="{'color':props.color}">互動的次數{{count}}</button>
        </text>
    </div>
</template>
//AboutView.vue 外部給值
<CountTest color="green"/> //直接在呼叫的標籤上指定color顏色

我們試著傳遞更多內容:
//CountTest.vue
<script setup>
    ...
    const props = defineProps({ //把型別都定義好
    color: String,
    fontSize: String,
    msg: String,
    state:Boolean
    })
</script>
<template>
    <div>
    <text>{{props.msg}} <input type="checkbox" :checked="props.state"></text>
    //顯示外部傳來的文字,checkbox判斷布林值
    <br>
    <button @click="count++" :style="{'color':props.color,'font-size':props.fontSize}">
        互動的次數{{count}}
    </button>
    //改變文字顏色和大小
</div>
</template>
//AboutView.vue 外部給值
<script setup>
    import {ref} from 'vue'
    import CountTest from '@/components/CountTest.vue'
    const answer = ref({
        color: 'green',
        fontSize: '18px',
        msg: '這裡是About頁面嗎?',
        state: true
    }) //把回傳內容包成物件
</script>
<template>
    <div class="about">
        <CountTest v-bind="answer" /> //用v-bind方式回傳
    </div>
</template>

傳值校驗
上面我們只指定了每個項目該有的型別,但是針對數據的校驗還能做進一步的檢查,詳見:Prop 校驗
//CountTest.vue
 const props = defineProps({ 
    color: {},
    fontSize: String,
    msg: String,
    state:Boolean
  })
//CountTest.vue
const props = defineProps({
    //型別為字串,必傳
    color:
    {
        type: String,
        required: true
    },
    //型別為多種類,字串或數字
    fontSize: [String, Number],
    //型別為字串,必傳、有預設文字
    msg: {
        type: String,
        required: true,
        default:'能夠讀取頁面嗎?'
    },
    //Boolean轉換,更貼近原生js寫法;不回傳checked為false不會報錯
    checked:Boolean
})
不符合規範的話就會在console.log中跳出警告:
[Vue warn]: Invalid prop: type check failed for prop "color". Expected String with value "null", got Null
at...
當子組件發生變化時,就會透過Emit把事件發送給父組件;可以看作是子組件的主動投遞事件訊息、也是父組件的監聽接口:
//CountTest.vue 子組件
const emit = defineEmits(['someEvent']) //新增監聽事件
const changeCount = function () { //透過click觸發監聽
     emit('someEvent','從子組件傳來消息')
}
...
<button @click="changeCount"></button>
//AboutView.vue 父組件
const newMsg = ref('') 
const handleEvent = (msg) => { //響應式資料接值
     newMsg.value = msg
}
...
<CountTest @some-event="handleEvent" /> //監聽some-event事件
<text>{{newMsg}}</text> //傳過來的值show在這裡

參考資料
Vue-Prop
Vue-組件事件
Vue 程式札記 : emit 事件發射