iT邦幫忙

2025 iThome 鐵人賽

DAY 4
0
Vue.js

Vue 新手學習紀錄系列 第 4

Day 4|Props 與 Emit: 資料如何在元件之間傳遞

  • 分享至 

  • xImage
  •  

Day3 的文章有使用到資料傳遞,感覺開發上會蠻常用到的,今天就稍微深入了解一下兩個的區別

Props:由外向內傳資料

靜態傳入
最簡單的情境是父元件直接把一個靜態字串傳給子元件,子元件接收到 url,並顯示圖片。

const app = Vue.createApp({})

app.component('photo', {
  props: ['url'],
  template: `<img :src="url" class="img-thumbnail" alt>`
})

<photo url="https://example.com/demo.png"></photo>

動態傳入
大多時候我們要傳的會是父元件的資料,這時候就要用 v-bind,這樣當父元件的 imgUrl 改變時,子元件也會自動更新。

const app = Vue.createApp({
  data() {
    return {
      imgUrl: 'https://example.com/dynamic.png',
    }
  },
})

app.component('photo', {
  props: ['url'],
  template: `<img :src="url" class="img-thumbnail" alt>`
})

<photo v-bind:url="imgUrl"></photo>

使用 Props 需要注意的事

  • 單向數據流: v-model 無法改變由外面傳入的資料
  • 命名限制: 若 props 為小駝峰命名,則 HTML 名稱需加入 "-",並改為全小寫
    例如: props 命名為 superUrl,在 HTML 須使用 :super-url

Props 型別與驗證

前面知道了 props 可以把資料從父元件傳給子元件,但其實 Vue 還提供了「型別檢查」和「驗證」的功能,讓元件更好維護。
內部型別驗證: 較常用於是否有預設值、是否為必填欄位

const app = Vue.createApp({
	data(){
		return {
			money: 300,
			big: 100n,
			boo: truw,
			fn: () => {return 'a'}
		};
	},
});

app.component('validation',{
	props: {
		propA: Function,
		propB: [String, Number],
		//是否為必填
		propC: {
			type: String,
			required: true,
		},
		//是否有預設值
		propD: {
			type: Number,
			default: 10,
		},
	}
});
<validation
	:prop-a="fn"
	prop-c="123" 
> <!--prop-c 為判斷有沒有填資料,若有資料則不會報錯,若沒有資料則會報錯-->
</validation>

Emit: 由內向外傳遞事件

在 Vue 裡,資料是由外往內傳(props),但如果子元件需要把「使用者操作」回報給父元件,就要用 emit。
可以把它想像成:子元件丟一個事件給父元件,父元件再決定要怎麼處理。

使用步驟

  1. 在外層 methods 中定義接收方法,例如: 加一個數字、接收一段文字
  2. 在內層 methods 中定義 $emit 觸發方法,例如: $emit('事件名稱', 傳遞資料)
  3. 在父元件使用 v-on 或縮寫 @ 監聽事件
<button-counter v-on:emit-num="addNum"></button-counter>
<button-text @emit-text="getData"></button-text>
<button-named></button-named>
const app = Vue.createApp({
	data() {
		return {
			num: 0,
			text: '',
		};
	},
	methods: {
		addNum(){
			this.num++;
		}
		getData(text){
			this.text = text;
		}
	}
});
app.component('button-counter',{
	methods:{
		click(){
			this.$emit('emit-num')
		}
	},
	template: `<button type="button" @click="click">add</button>`
)};

//將內層文字往外傳
app.component('button-text',{
	data() {
		return {
			text: '內部',
		}
	},
	methods:{
		emit(){
			this.$emit('emit-text', this.text)
		}
	},
	template: `<button type="button" @click="emit">emit data</button>`
)};

Emit 驗證

不只可以在 props 上做型別驗證,連 emit 出去的事件也能做檢查,這樣能避免子元件亂丟錯誤資料。

app.component('button-counter2',{
	emits: {
		add:(num) => {
			return typeof num === "number"; //會回傳 true 或 false
		}
	},
	template: `<button type="button" @click="$emit('add',num)">add</button>`
)};

小結

  • Props 將資料由外向內傳入
  • Emit 將事件由內向外傳

上一篇
Day 3|文章列表雛型:用 v-for 做出表格
下一篇
Day 5|Computed + filter 製作簡易搜尋功能
系列文
Vue 新手學習紀錄5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言