點燈坊

失くすものさえない今が強くなるチャンスよ

Prop 也能 Reactive

Sam Xiao's Avatar 2024-02-20

若希望外部對 Component 不只提供初始值而已,還能繼續與外部 State 連動,則要使用 defineProps() + computed() 組合完成。

Version

Vue 3.4

computed()

computed001

  • Prop 不只提供 component 的初始值,之後外部 state 變動也會影響 component 內部 state

App.vue

<template>
  <div>
    <button @click="onClick">Outer +</button>
    <span>External State: {{ count }}</span>
  </div>
  <MyCounter :initialCount="count" />
</template>

<script setup>
import { ref } from 'vue'
import MyCounter from '@/components/MyCounter.vue'

let count = ref(10)
let onClick = () => count.value++
</script>

Line 2

<div>
  <button @click="onClick">Outer +</button>
  <span>External State: {{ count }}</span>
</div>
  • 外部 state 可不斷遞增

Line 6

<MyCounter :initialCount="count" />
  • 外部 state 透過 initialCount prop 傳進 MyCounter component

MyCounter.vue

<template>
  <div class="box">Internal State: {{ count }}</div>
</template>

<script setup>
import { computed } from 'vue'

let props = defineProps({ initialCount: Number })
let count = computed(() => props.initialCount * 10)
</script>

<style scoped>
.box {
  border-style: solid;
  border-width: 2px;
  border-color: red;
  width: fit-content;
}
</style>

Line 8

let props = defineProps({ initialCount: Number })
let count = computed(() => props.initialCount * 10)
  • defineProps():定義 initialCount prop
  • computed():在 computed() 內讀取 prop 並加工,因為使用了 computed(),所以 count state 與 initialCount prop 有連動性

Options API

App.vue

<template>
  <div>
    <button @click="onClick">Outer +</button>
    <span>External State: {{ count }}</span>
  </div>
  <MyCounter :initialCount="count" />
</template>

<script>
import MyCounter from '@/components/MyCounter.vue'

export default {
  components: {
    MyCounter
  },
  data: () => ({
    count: 10
  }),
  methods: {
    onClick() {
      this.count++
    }
  }
}
</script>
  • 最後附上相同功能的 Options API 供參考
  • Component 除了要 import 外,還要在 components 下宣告

MyCounter.vue

<template>
  <div class="box">Internal State: {{ count }}</div>
</template>

<script>
export default {
  props: {
    initialCount: Number
  },
  computed: {
    count() {
      return this.initialCount * 10
    }
  }
}
</script>

<style scoped>
.box {
  border-style: solid;
  border-width: 2px;
  border-color: red;
  width: fit-content;
}
</style>
  • Prop 在 props key 下以 Object 宣告
  • 可在 computed 下以 this 直接讀取 prop

Conclusion

  • 若 component 不只需外部 state 提供初始值,還要與外部 state 連動,則適合使用 defineProps() + computed() 組合