1. 程式人生 > >9.vue2-元件註冊,prop,插槽

9.vue2-元件註冊,prop,插槽

Author: vanessa
Date: 2018/06/19

1.元件命名

使用小寫,單詞中間加橫線,如:<my-input></my-input>

2.註冊

a.全域性註冊

Vue.component('my-component-name', {
  // ... 選項 ...
})

b.區域性註冊,components這個屬性一定是複數

var ComponentA = { 
	
}
new Vue({
  el: '#app'
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

3.prop內容

a.html對大小寫不敏感,大寫都會轉化為小寫,所以prop中大寫會被轉化為小寫加橫線,
props一般以字串陣列對形式展示,但是可以用物件表示,指定每個變數對型別,同時可以新增一些驗證

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object
}
Vue.component('my-component', {
  props: {
    // 基礎的型別檢查 (`null` 匹配任何型別)
    propA: Number,
    // 多個可能的型別
    propB: [String, Number],
    // 必填的字串
    propC: {
      type: String,
      required: true
    },
    // 帶有預設值的數字
    propD: {
      type: Number,
      default: 100
    },
    // 帶有預設值的物件
    propE: {
      type: Object,
      // 物件或陣列且一定會從一個工廠函式返回預設值
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函式
    propF: {
      validator: function (value) {
        // 這個值必須匹配下列字串中的一個
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

b.傳遞對值可以是動態對也可是靜態的,傳遞的值可以是數子,字串,布林,陣列,物件

<blog-post v-bind:title="post.title"></blog-post>

c.單向資料流,父級的改變會單向流動到子級,不能在子元件中改變prop的值
c1.子元件中使用父級的prop傳遞來的資料,最好在子元件的data中定義一個變數,或者定義一個計算屬性
c2.物件和陣列是通過引用傳入的,子元件中改變會影響父元件的值

ps:使用動態繫結的資料,必須是前面加v-bind後面資料加打括號
:my-object="{user}"

4.屬性合併和替換

絕大多少屬性會父元件中定義的屬性會替換掉子元件中的,class和style會父子間進行合併,追加到子元件的class後面

<bootstrap-date-input>的模版是這樣的
<input type="date" class="form-control">
<bootstrap-date-input type="text" class="active"></bootstrap-date-input>
子元件中type屬性會被替換成text,class將會進行合併變成  form-control active

ps:禁用特性繼承,將放棄父級中的屬性

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

可以使用$attrs在子元件中使用父元件的屬性,通過inheritAttrs:false禁止向父級繼承屬性,通過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>
	  `
	})
    <base-input  v-model="username" class="username-input" placeholder="Enter your username" data-ss="aaaa"></base-input>

4.具名插槽

<base-layout>
  <h1 slot="header">Here might be a page title</h1>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <p slot="footer">Here's some contact info</p>
</base-layout>
Vue.component("baseLayout",{
			template:`
				<div class="container">
					<slot name="header"></slot>
					<slot></slot>
					<slot name="footer"></slot>
				</div>
			`
		})
        

ps:全域性元件定義必須在new Vue()之前,否則控制檯報錯: Unknown custom element

編譯作用域

父元件模板的所有東西都會在父級作用域內編譯;子元件模板的所有東西都會在子級作用域內編譯。

<todo-list :todos="todos">
    <template slot-scope="{todo}">
        {{todo}}
    </template>
</todo-list>
Vue.component("todo-list",{
    props:['todos'],
    template:`
        <ul>
            <li v-for="todo in todos">
                <slot :todo="todo">{{todo.name}}</slot>
            </li>
        </ul>
    `
});

slot-scope能獲得子元件的資料,template能替換子元件slot中內容