綱要:
完整範例:
用一個外部載入的組件,可以讓組件上的白色圈圈控制移動到不同座標,來學習 Prop 和 Emit 讓父子組件之間資料能溝通的方法。
Learn More →
1. 建立新的 vue 檔案
在 components
下新增一個 vue 檔案命名為PropsEmit.vue
以及一個目錄 panel
,並在該目錄下新增 ChildPanel.vue
。
2. 設定路由
如下圖示,替 PropsEmit.vue
設置路由,而 ChildPanel.vue
是另行引入的子組件,此範例中不需要為子組件設置路由。
Learn More →
子組件本身帶有三個Button,分別是 Mode A、Mode B 與 Mode C 以及一個顯示白點座標的Panel。
我們要將Mode Button的事件以 emit
的方式傳給父組件:
Learn More →
<template>
<div class="row">
<div class="row horizontal v_center">
<!--emitModeA~C 後面的參數是預設的座標百分比值-->
<el-button @click="emitModeA(10, 50)">Mode A</el-button>
<el-button @click="emitModeB(20, 100)">Mode B</el-button>
<el-button @click="emitModeC(100, 100)">Mode C</el-button>
</div>
<!--Panel上的寬高可以由外部父組件指定Props-->
<div class="panel" :style="{width: panelWidth + 'px', height: panelHeight + 'px' }">
<!--白點座標由子組件的v-model指定預設值,也可以由Button事件或者父組件提供的Props改變-->
<span class="pos_dot" :style="{top: dotTop + '%', left: dotLeft + '%',}"></span>
</div>
</div>
</template>
<script>
export default {
name: 'ChildPanel',
// props就是開放給外部父組件指定的名稱與值的型別,必須要指定一個單一型別以及預設值
props: {
panelWidth: {
type: Number,
default: 100,
},
panelHeight: {
type: Number,
default: 100,
},
dotTop: {
type: Number,
default: 0,
},
dotLeft: {
type: Number,
default: 0,
},
},
data() {
return {
};
},
methods: {
// 對應下方Scss樣式的position座標
emitModeA(top, left) {
// 這裏命名的 handleEmitModeA B C等名稱
// 就是父組件以 on-event呼叫子組件函式的依據
this.$emit('handleEmitModeA', top, left);
},
emitModeB(top, left) {
this.$emit('handleEmitModeB', top, left);
},
emitModeC(top, left) {
this.$emit('handleEmitModeC', top, left);
},
},
};
</script>
<style lang="scss">
.panel {
position: relative;
border: 1px solid #999;
background: rgba(64, 57, 68, 0.7);
transition: all 0.3s ease-in-out;
.pos_dot{
position: absolute;
transform: translateX(-50%) translateY(-50%);
width: 30px;
height: 30px;
border: 1px solid #fff;
border-radius: 50%;
transition: all 0.3s ease-in-out;
}
}
</style>
父組件上會有 Reset 和 Center 兩個 Button 做自有事件控制座標,改變 Props 傳入的值之外,也接收子組件 Emit 過來的事件,讓被調用的子組件事件可以在父組件上運作。
Learn More →
<template>
<div class="page">
<div class="row horizontal v_center space">
<span class="row">{{ 'Props & Emit' }}</span>
</div>
<div class="row horizontal" data-space="space-vertical">
<!-- 我們引入兩個同樣的組件,兩個組件即使相同,但運作時是分開進行的,這個範例會以同時運作為例 -->
<!--還記得剛才在子組件的 this.$emit('handleEmitModeA', top, left) 吧? -->
<!--用 on-event 指定它跟父組件上的事件parentEmitModeA B C連動-->
<child-panel
@handleEmitModeA="parentEmitModeA"
@handleEmitModeB="parentEmitModeB"
@handleEmitModeC="parentEmitModeC"
:dotTop="dotPos[0].top"
:dotLeft="dotPos[0].left"
/>
<!--panelWidth、panelHeight、dotTop、dotLeft都是子組件中定義的Props-->
<ChildPanel
@handleEmitModeA="parentEmitModeA"
@handleEmitModeB="parentEmitModeB"
@handleEmitModeC="parentEmitModeC"
:panelWidth="400"
:panelHeight="400"
:dotTop="dotPos[1].top"
:dotLeft="dotPos[1].left"
/>
</div>
<div class="row horizontal">
<!--Reset 和 Center 兩個事件都是改變父組件v-model後再將之傳入子組件的Props-->
<el-button @click="resetPos">Reset</el-button>
<el-button @click="setCenter">Center</el-button>
</div>
</div>
</template>
<script>
// 引入子組件
import ChildPanel from './panel/ChildPanel.vue';
export default {
name: 'PropsEmit',
// 引入後也要記得在這裡註冊子組件才會變成合法組件
components: {
ChildPanel,
},
data() {
return {
// 組件有兩個,所以用Array包Object的方式分配所屬的v-model
dotPos: [
{ top: 50, left: 50 },
{ top: 10, left: 80 },
],
};
},
methods: {
// reset 事件,將兩個組件的座標都重設為 0, 0
resetPos() {
this.dotPos.forEach((el) => {
el.top = 0;
el.left = 0;
});
console.log('(Parent-Reset) updated dot pos to child');
},
// center 事件,將兩個組件的座標都設為 50, 50
setCenter() {
this.dotPos.forEach((el) => {
el.top = 50;
el.left = 50;
});
console.log('(Parent-Center) updated dot pos to child');
},
// 子組件事件綁定,並且改變指定的座標值
// 假如你想讓每個組件自己獨立運作,就不要使用forEach去改變this.dotPos的內容
// 而是直接指定對應的v-model: this.dotPos[0] 或 this.dotPos[1]
parentEmitModeA(top, left) { // from child: top, left
// v-model: this.dotPos
this.dotPos.forEach((el) => {
el.top = top;
el.left = left;
});
},
parentEmitModeB(top, left) {
this.dotPos.forEach((el) => {
el.top = top;
el.left = left;
});
},
parentEmitModeC(top, left) {
this.dotPos.forEach((el) => {
el.top = top;
el.left = left;
});
},
},
};
</script>
組件之間的溝通不只有父子關係組件,同層級的組件之間除了比較少見的 Event Bus 以外,一般都推薦使用Vuex狀態管理工具來讓每個不同的組件都能同時調用同樣的v-model。
而父子關係組件是屬於比較簡易使用的例子,務必要熟練。
VueJS
Props
Emit
綱要:
Feb 9, 2025一個方便大家快速上手使用的Scss庫。 如果你偏好Scss開發,且需要和UI/UX設計師按照Guideline協作,這份Library很適合你使用! 當然,你也能很輕鬆的擴充和維護這個架構! :::warning 特別注意!從 Sass 2.0 版本開始會有一些Breaking Change map-get 日後請改用 map.get() 除法不再使用 slash 符號 '/',請改用math.div() :::
Oct 30, 2024🚀 Vue 3 網頁應用秒變行動 APP,你相信嗎?是不是覺得製作 APP 很複雜、門檻很高?😵💫 別擔心,現在只要你會寫 Vue 3 網頁應用,就可以用 Capacitor 簡單地將它打包成原生 Android 或 iOS 的行動 APP!🎉
Sep 28, 2024綱要:
Aug 14, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up