iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
1
自我挑戰組

前端新手筆記-Vue.js系列 第 18

Day18 Vue Component(元件)-props使用注意細項(2)

文章同時刊載於Andy's Blog

前言

延續昨天話題,今天會來繼續聊聊props使用注意細節。

狀況一:讀取遠端資料

我們今天如果使用AJAX讀取遠端資料時,並透過props將資料傳入子元件時,有可能在畫面上無法正常顯示(如下圖)。而這個原因就是AJAX非同步特性,造成遠端回傳資料尚未載入,而使畫面一片空白。
https://ithelp.ithome.com.tw/upload/images/20191004/20114645pD3pABOF0K.png

這時,我們該如何解決呢?
我們可以透過簡單v-if來判斷,當資料完全載入時,在呈現於畫面上就可以瞜。

寫法如下:

範例連結

<div id="app">
  <div class="row">
    <div class="col-sm-4">
      <!-- 這邊主要因為AJAX時間差,造成卡片載入錯誤。我們只要使用v-if成功載入時再渲染就不會跳錯 -->
      <card :user-data="user" v-if="user.gender"></card>
    </div>
  </div>
</div>


狀況二:非Prop的特性(Non-Prop Attributes)

說明:一個非prop 特性是指傳向一個組件,但是該組件並沒有相對應prop定義的特性。

我自己的理解如下(如果有錯,再請大家糾正)/images/emoticon/emoticon08.gif
如下範例:假設今天我們在元件上要放置一張圖片,而我們在template中並沒撰寫圖片的heightwidthalt屬性,這時Vue允許我們可以直接將這些特性撰寫在HTML上,如此一來這些特性就會被放置在元件實體內。(感覺有點像data-* ,自定義屬性方法)

例子如下:練習連結
HTML部分

<div id="app">
  <h2>Default</h2>
  <nicolas-cage alt="hello"></nicolas-cage>
  <p>
  <h2>H/W</h2>
  <nicolas-cage width="199" height="199"></nicolas-cage>
</div>

JavaScript

Vue.component('nicolas-cage', {
  template:'<img :src="url" />', //取得computed中url結果
  data() {
    return {
    }
  },
  computed:{
    url:function() {
      let theUrl = 'https://fakeimg.pl/'+this.width+'/'+this.height;
      return theUrl;
    }
  },
  props:{
    height:{
      default:400,
    },
    width:{
      default:400
    }
  }
});

var app = new Vue({
  el: '#app',
  data() {
    return {
    }
  }
});

說明:可以注意到元件的template中並沒有用mustache語法來綁定外部傳進來資料。

替換/合併已有的特性

我們上面提到,如果在元件template上並沒有相對應props屬性,但我們卻在HTML template上直接撰寫attribute,Vue會讓這些attribute直接寫入元件實體中。
範例
<bootstrap-date-input>的模板內容

<input type="date" class="form-control">

HTML上模板

<bootstrap-date-input
  data-date-picker="activated"
  class="date-picker-theme-dark"
></bootstrap-date-input>

最終顯示結果
form-control,這是在組件的模板內設置好的
date-picker-theme-dark,這是從組件的父級傳入的
https://ithelp.ithome.com.tw/upload/images/20191004/20114645EKBnma38qa.png

禁用特性繼承

剛有提到,因為非Prop的特性,即使我們在元件中並沒有使用props來定義型態或接受資料,Vue仍然會把在HTML上撰寫的特性放置於元件實體中。而今天如果我們不想要繼承元件內實體屬性,我們可以這樣做~
範例如下:

Vue.component('my-component', {
  inheritAttrs: false,
  // ...
})

而我們也因為可以設定inheritAttrs: false$attrs緣故,可以自行決定哪些attribute要放置到哪個元素中。像是下方範例,我們透過v-bind="$attrs",將元件內實體屬性放置在input中。
範例如下:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
      >
    </label>
  `
})

後記

在撰寫非Prop的特性(Non-Prop Attributes)時,因為我是第一次接觸這個特性,撰寫起來有點卡卡的,也不太確定是否理解正確(哈哈)。我其實對於實務上會用在哪些地方,其實我也蠻好奇的,若有前輩願意分享也歡迎下方留言,那我們就明天見啦~

參考資料


上一篇
Day17 Vue Component(元件) - props使用注意細項(1)
下一篇
Day19 Vue Component溝通($parent、$children)
系列文
前端新手筆記-Vue.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言