1. 程式人生 > 其它 >淺談 Vue 中用於父子元件傳遞資料的方式:prop 和 slot

淺談 Vue 中用於父子元件傳遞資料的方式:prop 和 slot

簡單介紹

開發可複用元件時,經常需要父子元件間相互傳遞資料。Vue 提供了 prop 和 slot 兩種特性用於處理不同的場景:

  • prop 主要用於向子元件傳遞子元件必需的資料,類似於函式的一般引數。這類資料進入子元件後無法主動影響子元件的狀態,只能被動地被子元件使用。
  • slot 主要用於擴充套件子元件,使子元件具備原先沒有的內容或功能。插槽的內容進入子元件後,可能只是被子元件所使用(顯示額外的內容),也可能定義了使用子元件的內容或功能的表示式(這種情況類似於回撥函式)。

這裡的比喻不一定準確,但是可能有助於理解這兩種特性的使用場景和行為。

prop 的定義與使用

在子元件的 props 屬性中定義需要暴露到外部的 prop,然後在父元件中通過指定名稱傳入資料,而且可以指定 prop 的型別、是否必需、預設值等特性,這些特點都與函式引數的用法很像。

簡單示例——顯示“地區-日期-時間”的元件,<son> 表示子元件:

父元件:

<!-- HTML模板 -->
<son :region="region" :date="date" :time="time"></son>

// Javascript
... // 其他內容省略
  data() {
    return {
      region: { country: "China", province: "Beijing" },
      today: new Date(),
    };
  },
  computed: {
    date() {
      return this.today.getDate();
    },
    time() {
      return {
        hour: this.today.getHours(),
        minute: this.today.getMinutes(),
        second: this.today.getSeconds(),
      };
    },
  },
  components: {
    son,
  },
...

子元件

... // 其他內容省略
  props: {
    region: {
      country: String,
      province: String,
    },
    date: {
      type: Number,
      required: true,
    },
    time: {
      hour: {
        type: [Number, String],
        default: 0,
      },
      minute: {
        type: Number,
        default: 0,
      },
      second: {
        type: Number,
        default: 0,
      },
    },
  },
...

插槽 slot 的型別與使用

  • 預設插槽:父元件中未指定插槽名稱或作用域的內容,會進入子元件預設插槽 <slot></slot> 。同時,多個預設插槽會重複傳入的內容。使用已被廢棄的 slot="default" 方式將插槽的名字宣告為 default 相當於預設插槽。
  • 具名插槽:父元件中指定了插槽名稱的內容,會進入子元件的具名插槽,當子元件不存在指定的具名插槽時,傳遞的內容會被靜默忽略。同樣地,多個具名插槽也會重複傳入的內容。
  • 作用域插槽:父元件中

插槽使用示例

父元件:

<son>
  這是一句話。
  <template>這是另一句話。</template>
  <!-- 具名插槽 -->
  <template v-slot:header>
    <p>這是頭部</p>
  </template>
  <template #content>
    <p>這是主體</p>
  </template>
  <!-- 這裡指定了不存在的具名插槽,裡面的內容會被忽略 -->
  <template #footer>
    <p>這是底部</p>
  </template>
  <!-- 作用域插槽 -->
  <!-- 這裡將作用插槽中的預設內容姓替換為了名 -->
  <template v-slot:person="scope">
    <p>{{scope.user.firstName}}</p>
  </template>
</son>

子元件:

<div class="son">
    <!-- 具名插槽 -->
    <slot name="header"></slot>
    <!-- 相同的具名插槽會重複輸出傳入的內容 -->
    <slot name="content"></slot>
    <slot name="content"></slot>
    <!-- 預設插槽 -->
    <slot></slot>
    <!-- 作用域插槽 -->
    <slot
      name="person"
      :user="user"
    >{{ user.lastName }}</slot>
  </div>

頁面輸出結果:

總結

綜上,prop 表現得更像資料型函式引數,至於子元件使用這些資料做什麼、怎麼做,父元件無法干預;而 slot 更像是傳入了一個回撥函式,使子元件具備了更多功能,甚至可以像回撥函式操作 caller 函式內部資料一樣,操作子元件的內部資料。