<m-button @click="app">給我一輛坦克車</m-button>
... in new Vue()
methods: {
app () {
alert('請給我一輛十階坦克車')
}
}
<m-button @click.native="app">給我一輛坦克車</m-button>
in m-button ...
template: `
<button
type="button"
class="btn"
:class=" 'btn-' + dynamicClass"
@click="$emit('click')"
>
<slot></slot>
</button>
`
<m-button @click="app">給我一輛坦克車</m-button>
template: `
<button
type="button"
class="btn"
:class=" 'btn-' + dynamicClass"
@click="$emit('click', { name: 'aka allen'} )"
>
<slot></slot>
</button>
`
父層用 $event 接收此值並傳進 app 方法 ...
<m-button @click="app($event)">給我一輛坦克車</m-button>
Vue 實例中 ...
methods: {
app (e) {
alert('請給我一輛十階坦克車')
console.log(e) // 得到 { name: 'aka allen'} 物件
}
}
用途 : 合併物件通通到第一個物件,若有重複的成員名稱,後面覆蓋前面。
let a = {
banana: 1,
apple: 4
}
let b = {
apple: 10,
bottle: 11
}
console.log(Object.assign(a, b))
/*
輸出
{
banana: 1,
apple: 10,
bottle: 11
}
*/
我們從組件父層透過 tag attribute 的方式傳入資訊時,若此 attribute 有通過子層的 prop 驗證,那麼就會被提取進去子層,若是沒有通過 prop 驗證或者是此 tag attribute 根本不可能是 props 的成員之一時,此 tag attribute 將會被退貨,成為顯示在 HTML 上的屬性。
設定 inheritAttrs: false,那麼此默認行為會取消,你在 HTML 上加入的 tag attribute 將不會顯示並且全部被傳進子層,但是並不代表通過 prop 驗證,但是你可以在子層使用這些沒通過的值。
// 沒有 inheritAttrs: false
Vue.component('case-inherit-attrs', {
props: ['label'],
template: '<div>{{ label }}</div>'
})
<case-inherit-attrs
label="case-inheritAttrs 測試"
apple="123"
banana="321"
>
</case-inherit-attrs>
看 apple 和 banana 被退貨到父層等待發落,只有 label 通過進子層
現在換下面加入 inheritAttrs: false
// 有 inheritAttrs: false
Vue.component('case-inherit-attrs', {
inheritAttrs: false,
props: ['label'],
template: '<div>{{ label }}</div>'
})
負責收集沒有通過 prop 驗證的成員。不受 inheritAttrs 狀態影響,不管你是被退到哪裏,通通都在這,透過子層 {{ $attrs }} 可以很清楚看見,可使用 v-bind="$attrs" 向下傳遞,晚點會有示範。
<case-attrs-with-inherit-false
label="$attrs 測試 : 被退貨在子層等待發落"
apple="不管退貨位置通通被綁架1"
banana="不管退貨位置通通被綁架2"
></case-attrs-with-inherit-false>
<br>
<case-attrs-no-inherit-false
label="$attrs 測試 : 被退貨在父層,請自行F12查看"
apple="不管退貨位置通通被綁架3"
banana="不管退貨位置通通被綁架4"
></case-attrs-no-inherit-false>
... in script tag
Vue.component('case-attrs-with-inherit-false', {
inheritAttrs: false,
props: ['label'],
template: '<div>{{ label }} <br> {{ $attrs }}</div>'
})
Vue.component('case-attrs-no-inherit-false', {
props: ['label'],
template: '<div>{{ label }} <br> {{ $attrs }}</div>'
})
用途 : 包含了組件父層監聽自定義事件的物件集合,可使用 v-on="$listeners" 向下傳遞,晚點會有示範。
<case-listeners
@click="app"
@input.native="app"
@focus="app"
@change="app"
label="$listeners 測試,但因為子層沒有發射自定義事件,所以app沒用"
></case-listeners>
in script tag ...
Vue.component('case-listeners', {
props: ['label'],
template: `
<input :value="label" />
`,
created () {
console.log('case-listeners', this.$listeners)
}
})
<transfer-attrs-listeners
aka-allen="aka allen 被傳到了 receieve-aka-allen (子層裡註冊的子組件,紅色框框的部分),要用 props 接出來,把 props 和 {{ akaAllen }} 拿掉,我就會進 $attrs"
elvis="elvis 無憂無慮 飄盪著沒被用到,如果把 receieve-aka-allen 內的 props 和 {{ akaAllen }} 拿掉,aka allen就會跑來我這邊了。"
talfin="talfin在子層"
@input="app"
@focus="app2"
></transfer-attrs-listeners>
in script tag ...
Vue.component('transfer-attrs-listeners', {
props: ['talfin'],
components: {
'receieve-aka-allen': {
props: ['akaAllen'],
template: `<div style= "border: solid 1px red;">
akaAllen: {{ akaAllen }} <br><br>
$attrs : {{ $attrs }} <br><br>
<input
v-on="$listeners"
/>
</div>`,
created () {
console.log('this.$listeners: ', this.$listeners)
}
}
},
template: `
<div style= "border: solid 2px green;">
<label> {{ talfin }} </label>
<receieve-aka-allen
v-bind="$attrs"
v-on="$listeners"
>
</receieve-aka-allen>
</div>
`
})
in Vue 實例
methods: {
app (e) {
alert('給我一輛十階坦克車')
console.log(e)
},
app2 (e) {
console.log(e)
}
}
<base-input v-on:focus.native="onFocus"></base-input>
...
let baseInput = {
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>
`
}
而如果你有這樣的需求的話,透過 Object.assign() 在知識點介紹到的後面覆蓋前面的特性,就可對特定的事件做複寫,並且 Object.assign() 返回的是相同的格式,所以也能夠無痛放回去 v-on 。
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input: function (event) {
// 如果我沒記錯的話,原本預設發射回去父層的附帶值只有event而已
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
</label>
`
})
沒事也可以逛逛我們其他團隊成員的文章啦 ~~
eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列
PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列
阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列
喬依司: 實作經典 JavaScript 30 系列