iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
1
自我挑戰組

前端史萊姆與Vue的三十天時光冒險系列 第 17

Day17 萬丈高樓平地起(5):元件間的溝通橋樑Props(2)

本文同步發表於斜槓女紙部落格:Day17 萬丈高樓平地起(5):元件間的溝通橋樑Props(2)

Day17 萬丈高樓平地起(5):元件間的溝通橋樑Props(2)

嗨!承接昨天的內容,今天要繼續和大家聊props的一些眉眉角角,廢話不多說,直接開始囉!

props的命名

Vue組件命名方式有三種,如果以card component為範例的話,這三種的寫法如下

  • kebab-case(串燒):card-component (單字與單字間使用連接符號)
  • camelCase(小駝峰式命名):cardComponent (第一個單字以小寫字母開始;第二個單字的首字母大寫)
  • PascaleCase(大駝峰式命名):CardComponent (每一個單字的首字母都採用大寫字母)

在HTML中,屬性是不區分大小寫的,也就是說如果你在HTML中寫myattribute跟寫myAttribute,HTML會看成是一樣的東西,所以如果我們在元件中使用props去接收屬性的資料時,寫的是camelCase(駝峰式命名法)的屬性名稱,在HTML中就要自動轉換為kebab-case(用dash間隔的命名法)。

實際範例

//HTML
<div id="app">
    <!-- 顯示:我是 -->
  <name-card myName="鍾小呆"></name-card>
  
  <!-- 顯示:我是 鍾小呆 -->
  <name-card my-name="鍾小呆"></name-card>
</div>

//JS
Vue.component('name-card', {
  props: ['myName'],
  template: '<p>我是 {{ myName }}</p>'
})

var vm = new Vue ({
    el: '#app'
})

Props 使用上的注意事項

單向數據流(One-Way Data Flow)

經由props屬性傳遞的資料是單向綁定的,也就是當父元件屬性資料改變時,只能單向傳遞資料給子元件,反過來是不行的,目的是為了不讓子元件可以任意去更改父元件的狀態。

當父元件更新時,子元件的所有prop也會跟著更新為最新的資料。如果遇到需要更改父元件的資料狀態時,我們可以另外宣告一個變量來記錄。

直接看看實際範例,若我們想直接從input修改文字內容的話,console會產生警告訊息

props錯誤碼

若想解決這個問題的話,我們可以採用data(區域變數)這個方法來接外部傳進來的內容:

//HTML
<input type="text" class="form-control mt-3" v-model="newWord">

//JS
Vue.component('message', {
  props: ['word'],
  template: '#box',
  //區域變數data
  data: function () {
    return {
      newWord: this.word
    }
  },
});

改寫後,兩段資料的內容就被區別開來,console也不會出現錯誤訊息囉!

錯誤碼消失


AJAX 延遲 及 物件傳參考特性

直接來看 實際範例

假設我們的資料是經由ajax的方法傳入的話,Vue會先在Root中宣告一個user物件,然後透過 AJAX 行為把遠端的資料抓進來之後,才把它存進user物件裡面,在這之中會有時間差(因為執行的東西會先放在 event queue),所以card元件會報錯說找不到資料:

ajax錯誤碼

//HTML
<div id="app">
    <div class="row">
        <div class="col-sm-4">
            <card :user-data="user"></card>
        </div>
    </div>
</div>


<script type="text/x-template" id="card">
    <div class="card">
        <img class="card-img-top" :src="user.picture.large" alt="Card image cap">
        <div class="card-body">
            <h5 class="card-title">{{ user.name.first }} {{ user.name.last }}</h5>
            <p class="card-text">{{ user.email }}</p>
        </div>
        <div class="card-footer">
            <input type="email" class="form-control" v-model="user.email">
        </div>
    </div>
</script>
//JS
Vue.component('card', {
    props: ['userData'],
    template: '#card',
    data: function() {
        return {
            user: this.userData
        }
    }
});

var app = new Vue({
    el: '#app',
    data: {
        user: {},
    },
    created: function() {
        var vm = this;
        $.ajax({
            url: 'https://randomuser.me/api/',
            dataType: 'json',
            success: function(data) {
                vm.user = data.results[0];
            }
        });
    }
});

此時我們可以採用v-if的方式,假設 user 某個特性並沒有完全讀進來之前,就不要把這個卡片執行出來:

// 假設有email就把資料繪製出來
<card :user-data="user" v-if="user.email"></card>

實際出來的結果如下圖:

ajax錯誤排除

今天就先和大家分享到這兒,明天我們再繼續唷!


上一篇
Day16 萬丈高樓平地起(4):元件間的溝通橋樑Props(1)
下一篇
Day18 閒不下來的史萊姆(一):將房間列表改用x-template 建立元件
系列文
前端史萊姆與Vue的三十天時光冒險30

尚未有邦友留言

立即登入留言