Vue3從入門到精通(二)

2023-06-08 15:00:48

vue3 偵聽器

在Vue3中,偵聽器的使用方式與Vue2相同,可以使用watch選項或$watch方法來建立偵聽器。不同之處在於,Vue3中取消了immediate選項,同時提供了新的選項和API。

  1. 建立偵聽器

可以使用watch選項或$watch方法來建立偵聽器,語法與Vue2相同。範例如下:

<template>
  <div>{{ message }}</div>
</template>
​
<script>
export default {
  data() {
    return {
      message: 'Hello, Vue3!'
    }
  },
  watch: {
    message(newValue, oldValue) {
      console.log(`New value: ${newValue}, old value: ${oldValue}`)
    }
  }
}
</script>

上面的程式碼中,使用watch選項來建立偵聽器,當message的值發生變化時,會觸發偵聽器函數。

  1. 偵聽多個屬性

在Vue3中,可以使用陣列的方式偵聽多個屬性。範例如下:

<template>
  <div>{{ fullName }}</div>
</template>
​
<script>
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  watch: {
    ['firstName', 'lastName'](newValues, oldValues) {
      console.log(`New values: ${newValues}, old values: ${oldValues}`)
    }
  },
  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`
    }
  }
}
</script>

上面的程式碼中,使用陣列的方式偵聽firstNamelastName兩個屬性,當它們的值發生變化時,會觸發偵聽器函數。

  1. 深度偵聽

在Vue3中,可以使用deep選項來實現深度偵聽。範例如下:

<template>
  <div>{{ user.name }}</div>
</template>
​
<script>
export default {
  data() {
    return {
      user: {
        name: 'John Doe',
        age: 30
      }
    }
  },
  watch: {
    user: {
      handler(newValue, oldValue) {
        console.log(`New value: ${JSON.stringify(newValue)}, old value: ${JSON.stringify(oldValue)}`)
      },
      deep: true
    }
  }
}
</script>

上面的程式碼中,使用deep選項來實現深度偵聽user物件的所有屬性,當user物件的任何屬性發生變化時,都會觸發偵聽器函數。

  1. 取消偵聽器

在Vue3中,可以使用watch選項返回的取消函數來取消偵聽器。範例如下:

<template>
  <div>{{ message }}</div>
</template>
​
<script>
export default {
  data() {
    return {
      message: 'Hello, Vue3!'
    }
  },
  mounted() {
    const unwatch = this.$watch('message', (newValue, oldValue) => {
      console.log(`New value: ${newValue}, old value: ${oldValue}`)
    })
​
    setTimeout(() => {
      unwatch()
    }, 5000)
  }
}
</script>

上面的程式碼中,使用$watch方法建立偵聽器,並將返回的取消函數儲存在unwatch變數中,在5秒後呼叫取消函數,取消偵聽器。

vue3 表單輸入繫結

在Vue3中,表單輸入繫結的方式與Vue2相同,可以使用v-model指令來實現。不同之處在於,Vue3中取消了.sync修飾符,同時提供了新的修飾符和API。

  1. 基本用法

使用v-model指令可以將表單元素的值與元件的資料進行雙向繫結。範例如下:

<template>
  <div>
    <input type="text" v-model="message">
    <p>{{ message }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      message: ''
    }
  }
}
</script>

上面的程式碼中,將input元素的值與message資料進行雙向繫結,當input元素的值發生變化時,message資料也會跟著變化,同時p元素中展示message資料的值。

  1. 修飾符

在Vue3中,提供了新的修飾符來實現更靈活的表單輸入繫結。

  • .lazy修飾符:在輸入框失去焦點或按下確認鍵後才更新資料。範例如下:

<template>
  <div>
    <input type="text" v-model.lazy="message">
    <p>{{ message }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      message: ''
    }
  }
}
</script>

上面的程式碼中,使用.lazy修飾符將輸入框的值在失去焦點或按下確認鍵後才更新message資料。

  • .trim修飾符:去除輸入框的首尾空格。範例如下:

<template>
  <div>
    <input type="text" v-model.trim="message">
    <p>{{ message }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      message: ''
    }
  }
}
</script>

上面的程式碼中,使用.trim修飾符去除輸入框的首尾空格,並將處理後的值繫結到message資料上。

  • .number修飾符:將輸入框的值轉換為數位型別。範例如下:

<template>
  <div>
    <input type="text" v-model.number="age">
    <p>{{ age }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      age: 0
    }
  }
}
</script>

上面的程式碼中,使用.number修飾符將輸入框的值轉換為數位型別,並將轉換後的值繫結到age資料上。

  1. 自定義元件

在自定義元件中,可以使用v-model指令來實現自定義元件的雙向繫結。範例如下:

<template>
  <div>
    <my-input v-model="message"></my-input>
    <p>{{ message }}</p>
  </div>
</template>
​
<script>
import MyInput from './MyInput.vue'
​
export default {
  components: {
    MyInput
  },
  data() {
    return {
      message: ''
    }
  }
}
</script>

上面的程式碼中,使用v-model指令將my-input元件的值與message資料進行雙向繫結,當my-input元件的值發生變化時,message資料也會跟著變化,同時p元素中展示message資料的值。需要注意的是,my-input元件內部需要使用$emit方法觸發input事件來實現資料的更新。

vue3 模板參照

在Vue3中,模板參照使用ref來實現。ref可以用來獲取元件範例或DOM元素的參照,並將其繫結到元件範例的資料上。

  1. 元件參照

在Vue3中,使用ref可以獲取到元件範例的參照。範例如下:

<template>
  <div>
    <my-component ref="myComponent"></my-component>
  </div>
</template>
​
<script>
import MyComponent from './MyComponent.vue'
​
export default {
  components: {
    MyComponent
  },
  mounted() {
    console.log(this.$refs.myComponent) // 輸出元件範例
  }
}
</script>

上面的程式碼中,使用ref獲取到my-component元件的範例,並將其繫結到myComponent資料上。在mounted勾點函數中,可以通過this.$refs.myComponent獲取到元件範例,並進行操作。

  1. DOM元素參照

在Vue3中,使用ref可以獲取到DOM元素的參照。範例如下:

<template>
  <div>
    <input type="text" ref="myInput">
  </div>
</template>
​
<script>
export default {
  mounted() {
    console.log(this.$refs.myInput) // 輸出DOM元素
  }
}
</script>

上面的程式碼中,使用ref獲取到input元素的參照,並將其繫結到myInput資料上。在mounted勾點函數中,可以通過this.$refs.myInput獲取到DOM元素,並進行操作。

需要注意的是,在Vue3中,ref只能繫結到元件範例或DOM元素上,不能繫結到普通資料上。

vue3 元件組成

在Vue3中,元件由三部分組成:模板、邏輯和樣式。其中,模板和邏輯與Vue2中的元件相同,而樣式方面,Vue3推薦使用CSS Modules和CSS Variables來實現。

  1. 模板

元件的模板與Vue2中的模板相同,使用template標籤來定義。範例如下:

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ content }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      title: 'Hello, Vue3!',
      content: 'Vue3 is awesome!'
    }
  }
}
</script>

上面的程式碼中,定義了一個簡單的元件模板,包含一個標題和一段文字內容,使用雙花括號繫結資料。

  1. 邏輯

元件的邏輯與Vue2中的邏輯相同,使用script標籤來定義。範例如下:

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ content }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      title: 'Hello, Vue3!',
      content: 'Vue3 is awesome!'
    }
  },
  methods: {
    handleClick() {
      console.log('clicked')
    }
  }
}
</script>

上面的程式碼中,定義了一個簡單的元件邏輯,包含一個data資料物件和一個handleClick方法。

  1. 樣式

在Vue3中,推薦使用CSS Modules和CSS Variables來實現元件樣式。CSS Modules可以避免全域性樣式的汙染,而CSS Variables可以實現更靈活的樣式控制。

使用CSS Modules時,可以在style標籤中設定module屬性來啟用CSS Modules。範例如下:

<template>
  <div class="wrapper">
    <h1 class="title">{{ title }}</h1>
    <p class="content">{{ content }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      title: 'Hello, Vue3!',
      content: 'Vue3 is awesome!'
    }
  }
}
</script>
​
<style module>
.wrapper {
  padding: 20px;
  background-color: #f5f5f5;
}
​
.title {
  font-size: 24px;
  color: var(--primary-color);
}
​
.content {
  font-size: 16px;
  color: #333;
}
</style>

上面的程式碼中,使用CSS Modules設定了.wrapper.title.content三個類的樣式,並使用CSS Variables設定了--primary-color變數的值。

需要注意的是,使用CSS Modules時,類名會被自動轉換為唯一的類名,可以通過$style來參照。範例如下:

<template>
  <div :class="$style.wrapper">
    <h1 :class="$style.title">{{ title }}</h1>
    <p :class="$style.content">{{ content }}</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      title: 'Hello, Vue3!',
      content: 'Vue3 is awesome!'
    }
  }
}
</script>
​
<style module>
.wrapper {
  padding: 20px;
  background-color: #f5f5f5;
}
​
.title {
  font-size: 24px;
  color: var(--primary-color);
}
​
.content {
  font-size: 16px;
  color: #333;
}
</style>

上面的程式碼中,使用$style參照了.wrapper.title.content三個類的樣式。

vue3 元件巢狀關係

在Vue3中,元件巢狀關係與Vue2中的元件巢狀關係相同,通過在模板中巢狀元件來實現。

例如,有兩個元件ParentChild,其中Parent元件中巢狀了Child元件。範例如下:

<template>
  <div>
    <h1>{{ title }}</h1>
    <child :content="content"></child>
  </div>
</template>
​
<script>
import Child from './Child.vue'
​
export default {
  components: {
    Child
  },
  data() {
    return {
      title: 'Parent Component',
      content: 'This is the content of Parent Component.'
    }
  }
}
</script>

上面的程式碼中,Parent元件中通過<child>標籤巢狀了Child元件,並將content資料傳遞給Child元件。

Child元件的程式碼如下:

<template>
  <div>
    <h2>{{ title }}</h2>
    <p>{{ content }}</p>
  </div>
</template>
​
<script>
export default {
  props: {
    content: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      title: 'Child Component'
    }
  }
}
</script>

上面的程式碼中,Child元件接收了Parent元件傳遞的content資料,並在模板中展示出來。

需要注意的是,當元件巢狀層級較深時,可以使用provideinject來實現跨層級傳遞資料,避免層層傳遞資料的麻煩。

vue3 元件註冊方式

在Vue3中,元件註冊方式與Vue2中的元件註冊方式有所不同,Vue3提供了defineComponent函數來定義元件。具體步驟如下:

  1. 建立元件

使用defineComponent函數建立元件,範例如下:

import { defineComponent } from 'vue'
​
export default defineComponent({
  name: 'MyComponent',
  props: {
    content: {
      type: String,
      default: ''
    }
  },
  setup(props) {
    return {
      title: 'My Component',
      handleClick() {
        console.log('clicked')
      }
    }
  },
  template: `
    <div>
      <h1>{{ title }}</h1>
      <p>{{ content }}</p>
      <button @click="handleClick">Click Me</button>
    </div>
  `
})

上面的程式碼中,使用defineComponent函數定義了一個名為MyComponent的元件,包含propssetuptemplate三個部分。其中,props定義了元件的屬性,setup定義了元件的邏輯,template定義了元件的模板。

  1. 註冊元件

使用createApp函數建立Vue範例,並使用component方法註冊元件,範例如下:

import { createApp } from 'vue'
import MyComponent from './MyComponent.vue'
​
const app = createApp()
​
app.component('my-component', MyComponent)
​
app.mount('#app')

上面的程式碼中,使用component方法將MyComponent元件註冊為my-component元件,並使用mount方法將Vue範例掛載到DOM節點上。

需要注意的是,使用defineComponent函數建立的元件可以直接在component方法中註冊,無需再進行額外的處理。另外,也可以使用defineAsyncComponent函數定義非同步元件,以優化應用的載入效能。

vue3 元件傳遞資料 props

在Vue3中,元件傳遞資料的方式與Vue2中基本相同,都是通過props屬性進行傳遞。但是Vue3中對props進行了一些優化,使得元件傳遞資料更加方便和靈活。

下面是一個簡單的範例,演示瞭如何在Vue3中使用props傳遞資料:

// ChildComponent.vue
<template>
  <div>
    <h2>{{ title }}</h2>
    <p>{{ content }}</p>
  </div>
</template>
​
<script>
  import { defineComponent } from 'vue'
​
  export default defineComponent({
    name: 'ChildComponent',
    props: {
      title: {
        type: String,
        required: true
      },
      content: {
        type: String,
        default: ''
      }
    }
  })
</script>
// ParentComponent.vue
<template>
  <div>
    <h1>{{ pageTitle }}</h1>
    <child-component :title="childTitle" :content="childContent" />
  </div>
</template>
​
<script>
  import { defineComponent } from 'vue'
  import ChildComponent from './ChildComponent.vue'
​
  export default defineComponent({
    name: 'ParentComponent',
    components: {
      ChildComponent
    },
    data() {
      return {
        pageTitle: 'Parent Component',
        childTitle: 'Child Component',
        childContent: 'Lorem ipsum dolor sit amet'
      }
    }
  })
</script>

在上面的範例中,ChildComponent元件定義了兩個propstitlecontenttitle屬性是必需的,型別為字串;content屬性是可選的,型別為字串,如果沒有傳遞則預設為空字串。

ParentComponent元件中,使用child-component標籤引入了ChildComponent元件,並通過:title:content指令將資料傳遞給子元件。在data中定義了pageTitlechildTitlechildContent三個屬性,分別用於在父元件和子元件中顯示標題和內容。

需要注意的是,在Vue3中,使用props傳遞資料時,可以通過.sync修飾符實現雙向繫結,也可以使用v-model指令簡化雙向繫結的寫法。此外,還可以使用emit方法向父元件傳送事件,實現元件之間的通訊。

vue3 元件傳遞多種資料型別

在Vue3中,元件傳遞多種資料型別的方式與Vue2中基本相同,都是通過props屬性進行傳遞。下面是一個範例,演示瞭如何在Vue3中使用props傳遞多種資料型別:

// ChildComponent.vue
<template>
  <div>
    <h2>{{ title }}</h2>
    <p>{{ content }}</p>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>
​
<script>
  import { defineComponent } from 'vue'
​
  export default defineComponent({
    name: 'ChildComponent',
    props: {
      title: {
        type: String,
        required: true
      },
      content: {
        type: String,
        default: ''
      },
      list: {
        type: Array,
        default: () => []
      }
    }
  })
</script>

在上面的範例中,ChildComponent元件定義了三個propstitlecontentlisttitle屬性是必需的,型別為字串;content屬性是可選的,型別為字串,如果沒有傳遞則預設為空字串;list屬性是可選的,型別為陣列,如果沒有傳遞則預設為空陣列。

在父元件中,可以通過:title:content:list指令將資料傳遞給子元件。需要注意的是,如果要傳遞陣列型別的資料,可以使用v-bind指令或簡寫的:語法,例如:list="[ { id: 1, name: 'item 1' }, { id: 2, name: 'item 2' } ]"

需要注意的是,在Vue3中,使用props傳遞資料時,可以通過.sync修飾符實現雙向繫結,也可以使用v-model指令簡化雙向繫結的寫法。此外,還可以使用emit方法向父元件傳送事件,實現元件之間的通訊。

vue3 元件傳遞props 校驗

在Vue3中,元件傳遞props時,可以使用Props選項進行校驗。Props選項是一個物件,用於指定元件接受的props以及其型別、預設值和校驗規則等。

下面是一個範例,演示瞭如何在Vue3中使用Props選項進行校驗:

// ChildComponent.vue
<template>
  <div>
    <h2>{{ title }}</h2>
    <p>{{ content }}</p>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>
​
<script>
  import { defineComponent } from 'vue'
​
  export default defineComponent({
    name: 'ChildComponent',
    props: {
      // 校驗title屬性,型別為字串,必須傳遞
      title: {
        type: String,
        required: true
      },
      // 校驗content屬性,型別為字串,如果沒有傳遞則預設為空字串
      content: {
        type: String,
        default: ''
      },
      // 校驗list屬性,型別為陣列,如果沒有傳遞則預設為空陣列
      list: {
        type: Array,
        default: () => []
      },
      // 校驗count屬性,型別為數位,必須大於0
      count: {
        type: Number,
        validator: (value) => value > 0
      }
    }
  })
</script>

在上面的範例中,ChildComponent元件定義了四個propstitlecontentlistcount。其中,titlecount屬性是必需的,型別分別為字串和數位;contentlist屬性是可選的,型別分別為字串和陣列,如果沒有傳遞則分別預設為空字串和空陣列。此外,count屬性還定義了一個校驗規則,即必須大於0。

需要注意的是,在Vue3中,如果一個props屬性沒有指定型別,那麼它可以接受任何型別的資料。如果需要限制props屬性接受的資料型別,可以使用type選項指定。如果需要指定多個型別,可以使用陣列形式,例如type: [String, Number]

此外,如果需要對props屬性進行更復雜的校驗,可以使用validator選項。validator是一個函數,用於校驗props屬性的值是否符合指定的規則。如果校驗失敗,可以返回false或丟擲異常,Vue會在控制檯輸出警告資訊。

vue3 元件事件

在Vue3中,元件事件可以使用emits選項進行定義。emits選項是一個陣列,用於指定元件可以觸發的事件名稱。定義元件事件後,可以使用$emit方法在元件內部觸發事件,並可以在父元件中使用v-on指令監聽事件。

下面是一個範例,演示瞭如何在Vue3中定義元件事件:

// ChildComponent.vue
<template>
  <button @click="handleClick">{{ buttonText }}</button>
</template>

<script>
  import { defineComponent } from 'vue'

  export default defineComponent({
    name: 'ChildComponent',
    emits: ['click'],
    props: {
      buttonText: {
        type: String,
        required: true
      }
    },
    methods: {
      handleClick() {
        this.$emit('click')
      }
    }
  })
</script>

在上面的範例中,ChildComponent元件定義了一個emits選項,指定了可以觸發的click事件。在元件內部,使用$emit方法觸發click事件,並在父元件中使用v-on指令監聽該事件。

下面是父元件如何監聽ChildComponent元件觸發的click事件:

// ParentComponent.vue
<template>
  <div>
    <ChildComponent :buttonText="buttonText" @click="handleClick" />
  </div>
</template>
​
<script>
  import { defineComponent } from 'vue'
  import ChildComponent from './ChildComponent.vue'
​
  export default defineComponent({
    name: 'ParentComponent',
    components: {
      ChildComponent
    },
    data() {
      return {
        buttonText: 'Click me'
      }
    },
    methods: {
      handleClick() {
        console.log('ChildComponent clicked')
      }
    }
  })
</script>

在上面的範例中,ParentComponent元件使用v-on指令監聽ChildComponent元件觸發的click事件,並在handleClick方法中輸出一條紀錄檔。

需要注意的是,在Vue3中,如果一個元件觸發了未定義的事件,Vue會在控制檯輸出警告資訊。如果需要禁用這個警告,可以在createApp方法中傳遞一個config選項,設定warnHandler屬性為null。例如:

import { createApp } from 'vue'
​
const app = createApp({
  // ...
})
​
app.config.warnHandler = null
​
app.mount('#app')

vue3 元件事件配合v-model使用

在Vue3中,元件事件可以配合v-model指令使用,用於實現雙向資料繫結。要實現v-model指令,需要在元件中定義一個名為modelValue的prop,並在emits選項中指定update:modelValue事件。

以下是一個範例,演示瞭如何在Vue3中使用v-model指令:

// ChildComponent.vue
<template>
  <input :value="modelValue" @input="handleInput" />
</template>
​
<script>
  import { defineComponent } from 'vue'
​
  export default defineComponent({
    name: 'ChildComponent',
    emits: ['update:modelValue'],
    props: {
      modelValue: {
        type: String,
        required: true
      }
    },
    methods: {
      handleInput(event) {
        this.$emit('update:modelValue', event.target.value)
      }
    }
  })
</script>

在上面的範例中,ChildComponent元件定義了一個名為modelValue的prop,並在emits選項中指定了update:modelValue事件。在元件內部,使用$emit方法觸發update:modelValue事件,並傳遞輸入框的值。

下面是父元件如何使用v-model指令繫結ChildComponent元件的modelValue

// ParentComponent.vue
<template>
  <div>
    <ChildComponent v-model="inputValue" />
  </div>
</template>
​
<script>
  import { defineComponent, ref } from 'vue'
  import ChildComponent from './ChildComponent.vue'
​
  export default defineComponent({
    name: 'ParentComponent',
    components: {
      ChildComponent
    },
    setup() {
      const inputValue = ref('')
​
      return {
        inputValue
      }
    }
  })
</script>

在上面的範例中,ParentComponent元件使用v-model指令繫結ChildComponent元件的modelValue,並將其賦值給inputValue變數。此時,ChildComponent元件的輸入框和inputValue變數會實現雙向資料繫結。

需要注意的是,v-model指令實際上是語法糖,相當於同時繫結了一個value prop和一個update:value事件。因此,如果需要在元件內部使用v-model指令,也需要定義一個名為value的prop,並在emits選項中指定update:value事件。

vue3 元件資料傳遞

在 Vue3 中,元件資料傳遞可以通過 props 和 emit 實現。

  1. Props

在 Vue3 中,通過 props 定義元件的屬性,可以將資料從父元件傳遞到子元件。父元件中使用子元件時,可以通過 v-bind 或簡寫的 : 來繫結屬性值。

例如,下面的程式碼演示瞭如何使用 props 在父元件中向子元件傳遞資料:

// ChildComponent.vue
<template>
  <div>{{ message }}</div>
</template>

<script>
  import { defineComponent, PropType } from 'vue'

  export default defineComponent({
    name: 'ChildComponent',
    props: {
      message: {
        type: String,
        required: true
      }
    }
  })
</script>

// ParentComponent.vue
<template>
  <div>
    <ChildComponent :message="parentMessage" />
  </div>
</template>

<script>
  import { defineComponent } from 'vue'
  import ChildComponent from './ChildComponent.vue'

  export default defineComponent({
    name: 'ParentComponent',
    components: {
      ChildComponent
    },
    data() {
      return {
        parentMessage: 'Hello from parent component'
      }
    }
  })
</script>

在上面的程式碼中,ChildComponent 元件定義了一個名為 messageprops,並在模板中使用它來顯示資料。在 ParentComponent 元件中,使用 v-bind 或簡寫的 : 來將父元件的 parentMessage 資料傳遞給子元件的 message 屬性。

  1. Emit

在 Vue3 中,通過 emit 傳送自定義事件,可以將資料從子元件傳遞到父元件。子元件使用 $emit 方法觸發事件,並傳遞資料。父元件中通過 v-on 或簡寫的 @ 來監聽事件,並在事件處理常式中獲取資料。

例如,下面的程式碼演示瞭如何使用 emit 在子元件中向父元件傳遞資料:

// ChildComponent.vue
<template>
  <button @click="sendMessage">Send message to parent</button>
</template>
​
<script>
  import { defineComponent } from 'vue'
​
  export default defineComponent({
    name: 'ChildComponent',
    methods: {
      sendMessage() {
        this.$emit('message-sent', 'Hello from child component')
      }
    }
  })
</script>
​
// ParentComponent.vue
<template>
  <div>
    <ChildComponent @message-sent="handleMessage" />
    <div>{{ message }}</div>
  </div>
</template>
​
<script>
  import { defineComponent, ref } from 'vue'
  import ChildComponent from './ChildComponent.vue'
​
  export default defineComponent({
    name: 'ParentComponent',
    components: {
      ChildComponent
    },
    setup() {
      const message = ref('')
​
      const handleMessage = (data) => {
        message.value = data
      }
​
      return {
        message,
        handleMessage
      }
    }
  })
</script>

在上面的程式碼中,ChildComponent 元件定義了一個 sendMessage 方法,在方法中使用 $emit 方法觸發 message-sent 事件,並將資料傳遞給父元件。在 ParentComponent 元件中,使用 v-on 或簡寫的 @ 來監聽 message-sent 事件,並在事件處理常式中獲取資料。

vue3 透傳Attributes

在 Vue3 中,可以使用 v-bind="$attrs" 透傳父元件的 attributes 到子元件,子元件可以通過 inheritAttrs: false 禁用繼承父元件的 attributes,然後使用 $attrs 獲取透傳的 attributes。

例如,下面的程式碼演示瞭如何使用 $attrs 透傳父元件的 attributes 到子元件:

// ChildComponent.vue
<template>
  <div :class="computedClass" v-bind="$attrs">{{ message }}</div>
</template>
​
<script>
  import { defineComponent } from 'vue'
​
  export default defineComponent({
    name: 'ChildComponent',
    inheritAttrs: false,
    props: {
      message: {
        type: String,
        required: true
      }
    },
    computed: {
      computedClass() {
        return {
          'text-red': this.$attrs.color === 'red'
        }
      }
    }
  })
</script>
​
// ParentComponent.vue
<template>
  <div>
    <ChildComponent message="Hello from parent component" color="red" />
  </div>
</template>
​
<script>
  import { defineComponent } from 'vue'
  import ChildComponent from './ChildComponent.vue'
​
  export default defineComponent({
    name: 'ParentComponent',
    components: {
      ChildComponent
    }
  })
</script>

在上面的程式碼中,ChildComponent 元件使用 v-bind="$attrs" 透傳父元件的 attributes,並在 computedClass 計算屬性中根據 color 屬性的值來動態設定樣式。在 ParentComponent 元件中,使用 color 屬性來設定文字顏色。