2019年10月3日 星期四

[Vue] 插槽 2/2

作用域插槽

  1. 父組件可以使用子組件的data
  2. 被綁定在slot上的prop稱為: 插槽 prop
  • 父組件
<my-tab>
</my-tab>
  • 子組件
Vue.component('my-tab', {
    data: function () {
        return {
            tabName: 'Default Tab Name'
        }
    },
    template: `
    <div>
    <br>
    <a style="border: 1px solid black;">
        <slot v-bind:tabName="tabName">預設內容</slot>
    </a>
    <br>
    <slot name="content"></slot>
    </div>
    `
})

自定義插槽prop名稱

  1. 在子組件上, 用v-slot可自定義插槽prop的名稱
  2. 簡寫: <my-tab v-slot="myChildVariable">...</my-tab>
  3. 簡寫和作用愈插槽寫法不可混用
  • 父組件
        <my-tab>
            <template v-slot:default="childProp">
                {{childProp.tabName}}
            </template>
        </my-tab>
  • 子組件
Vue.component('my-tab', {
    data: function () {
        return {
            tabName: 'Default Tab Name'
        }
    },
    template: `
    <div>
    <br>
    <a style="border: 1px solid black;">
        <slot v-bind:tabName="tabName">預設內容</slot>
    </a>
    <br>
    <slot name="content"></slot>
    </div>
    `
})

解構插槽prop

1. 插槽原理: 將插槽內容包括在一個傳入單個參數的函數裡,如下

function (props) {
  // 插槽內容
}

所以可以套入"解構"的概念,控制子組件的屬性
<my-tab>
    <template v-slot="{tab}">
        {{tab.tabName2}}
    </template>
</my-tab>

2. 解構之餘,同時也可重新命名屬性
<my-tab>
    <template v-slot="{tab: myTabCollection}">
        {{myTabCollection.tabName2}}
    </template>
</my-tab>

*.v-slot的縮寫符號: #


2019年10月2日 星期三

[Vue] 插槽 1/2

<slot></slot>

  1. 可以在自定義的component中,預留一個空間,給父組件插入內容。
  2. 子組件和父組件的作用域各自獨立,不可交互使用。
  • 子組件
Vue.component('my-tab', {
    template:`
    <a style="border: 1px solid black;">
        <slot></slot>
    </a>
    `
})
  • 父組件
<my-tab>
     slot content
     <br>
    {{currentTab}}
</my-tab>

後備內容

<slot></slot>中可以設定預設內容,在無任何資料時,自動顯示
  • 子組件
Vue.component('my-tab', {
    template:`
    <a style="border: 1px solid black;">
        <slot>預設內容</slot>
    </a>
    `
})
  • 父組件
<my-tab>
     slot content
     <br>
    {{currentTab}}
</my-tab>

具名插槽

  1. slot可以給定名稱(name),就可以預留多個空間給父組件。
  2. 沒有名稱(name)的slot,預設名稱: default。
  • 子組件
Vue.component('my-tab', {
    template:`
    <div>
    <a style="border: 1px solid black;">
        <slot>預設內容</slot>
    </a>
    <br>
    <slot name="content"></slot>
    </div>
    `
})
  • 父組件
<my-tab>
    slot content
    <br>
    {{currentTab}}
    <template v-slot:content>
        具名slot,給定名稱content,插入指定位置
    </template>
</my-tab>

2019年10月1日 星期二

[Vue] 自定義事件

自定義事件命名

  • 駝峰命名不會自動轉換成kebab-case,盡量使用kebab-case
e.g.

this.$emit('myCustomEvent');

// 這行不會有效果
<component v-on:my-custom-event="onEvent"></component>
  • 但是會自動轉成小寫
上面那個宣告需要使用以下寫法才監聽的到
<component v-on:myCustomEvent="onEvent"></component>

原生事件綁定至自製組件(進階)

1. 使用自製組件,綁定原生事件的作法
  • 父組件
<my-checkbox v-model="YesOrNo" v-on:focus.native="onFocus"></my-checkbox>
  • 子組件
<input
        type="checkbox"
        v-bind:checked="checked"
        v-on:change="$emit('change',$event.target.checked)"
    >
以上可以監聽子組件根元素(input)的focus事件,並觸發父組件的onFocus

2. 當根元素不是input,卻又想要做到上面這件事情時

$listeners(進階)

  • 父組件
<my-checkbox v-model="YesOrNo" v-on:click.native="onClick"></my-checkbox>
  • 子組件
computed: {
        checkboxListener: function () {
            var vm = this;
            return Object.assign({},
                this.$listeners,
                {
                    click: function (event) {
                        vm.$emit('click', event.target.checked)
                    },
                    change: function (event) {
                        vm.$emit('change', event.target.checked)
                    },
                })
        }
    },
    template: `
    <label>
    {{label}}
        <input
            type="checkbox"
            v-bind="$attrs"
            v-bind:checked="checked"         
            v-on="checkboxListener"
        >
    </label>
    `
關鍵字預留 : .sync