1盹廷,inheritAttrs
介紹
vue
默認(rèn)情況下,父組件是可以直接給子組件的根元素添加class
和style
的久橙,但是有時候我們可能需要在父組件上給子組件添加一些特性綁定(attribute bindings
)(我的理解是自定義屬性和一些原生屬性)到子組件的根元素上俄占,inheritAttrs
就是用來控制子組件根元素上是否允許添加父組件在子組件上定義的特性屬性,因?yàn)?code>inheritAttrs默認(rèn)為true
淆衷,所以我們在父組件中給子組件添加所有特性綁定缸榄,都能綁定到根元素,例如下面
<template>
<div>
<base-item class="box"
key="1"
default-id="1"
style="font-size: 14px;">
</base-item>
</div>
</template>
<script>
export default {
components: {
baseItem: {
inheritAttrs: false,
template: `
<div>
<span>good</span>
</div>
`
}
}
}
</script>
渲染后的dom節(jié)點(diǎn):
<div default-id="1" class="box" style="font-size: 14px;">
<span>good</span>
</div>
把inheritAttrs
設(shè)為false
后祝拯,
渲染后的dom節(jié)點(diǎn):
<div class="box" style="font-size: 14px;">
<span>good</span>
</div>
可以得出上述的結(jié)論甚带,inheritAttrs
是用來控制子組件根元素上是否允許添加父組件在子組件上定義的特性屬性。
注意:
inheritAttrs是用來控制父組件中傳遞的特性屬性佳头,class和style不是特性屬性欲低,不能用inheritAttrs來控制。
2畜晰,$attrs
介紹
我們可以把父作用域中傳遞的所有屬性看作一個大的對象obj
,而$attrs
會繼承obj
中的一部分屬性瑞筐,這一部分屬性的key
不能為class
凄鼻,和style
,也不能是當(dāng)前組件聲明的props
值聚假,并且父組件為v-model
的話块蚌,也是不能繼承指令封裝的value
值的,若當(dāng)前組件無props設(shè)置膘格,$attrs
則繼承除class
和style
的所有屬性峭范。
通常我們給已封裝的組件進(jìn)行中間處理的時候使用,例如element-ui
的el-input
瘪贱,我們需要把父組件中的傳遞的props
直接給子組件的子組件的時候纱控,我們就可以用到$attrs
,例如:
父組件為:
<self-input class="self-input"
:limit="2"
v-model="item.count"
count="234">
</self-input>
子組件為:
<el-input
type="text"
v-bind="$attrs"
v-model="defaultValue">
</el-input>
export default {
props: {limit: Number}
}
根據(jù)上面所說菜秦,去掉class
甜害,去掉指定的value
,去掉子組件props
聲明的limit
球昨,那時我們此的$attrs
是:
{
count: '234'
}
3尔店,$listenters
介紹
我們對ui框架中的組件進(jìn)行再封裝的時候,例如element-ui中的組件el-input
,我們把他封裝到我們自己的組件內(nèi)部嚣州。
例如self-input
組件如下鲫售,
<div>
<el-input></el-input>
</div>
我們需要把el-input
組件上自定義的事件傳遞進(jìn)去,那么就要用到$listenters
该肴。
官網(wǎng)的描述:
包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器情竹。它可以通過 v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時非常有用。
很容易理解沙庐,.native
是給子組件根元素添加事件鲤妥,自然不是用來傳給子組件上的子組件或元素。而我們在父組件上給子組件綁定的所有事件拱雏,都會放入$listeners
中棉安,我們可以在子組件中手動過濾修改后傳給子組件中的子組件或者元素上,也可以用v-on="$listeners"
铸抑,直接全部傳給子組件或者元素上贡耽。
用法也相當(dāng)簡單,例如:
父組件:
<template>
<self-input
@change="changeHandler"
@input="inputHandler"
v-model="count">
</self-input>
</template>
<script>
export default {
data () {
return {count: ''}
},
methods: {
changeHandler () {},
inputHandler () {}
}
}
</script>
子組件:
<template>
<el-input
v-on="$listeners"
v-model="defaultValue">
</el-input>
</template>
<script>
export default {
data () {
return {
defaultValue: ''
}
},
props: {
value: [String, Number] // value值
},
mounted () {
console.log(this.$listeners)
}
}
</script>
由于父組件傳入的是一個change事件和兩個input事件鹊汛,那我們打印的this.$listeners
是
{
change: fn,
input: [fn, fn]
}
下面是一個關(guān)于限制小數(shù)點(diǎn)的完整demo蒲赂,感興趣的可以了解一下
<template>
<el-input ref="input"
type="text"
v-bind="$attrs"
v-on="$listeners"
@input.native="inputHandle"
v-model="defaultValue">
</el-input>
</template>
<script>
/** 示例 當(dāng)前組件主要目的是實(shí)時控制輸入框小數(shù)點(diǎn)右側(cè)字符長度
* <self-input
* :minLimit="0.21" :maxLimit="100.22"
* @input="inputHandle"
* :limit="2" v-model="aaa"></self-input>
* limit 小數(shù)點(diǎn)有幾位
* 解釋
* v-model的作用是將value和事件傳遞給子組件el-input,并且作為中間變量來傳遞value值
* inputHandle 主要是對輸入的內(nèi)容進(jìn)行實(shí)時校驗(yàn)
*/
export default {
data () {
return {
defaultValue: '' // 作為中間變量
}
},
inheritAttrs: false, // 此處設(shè)置根元素禁用繼承特性(只繼承class屬性)
// 當(dāng)inheritAttrs為true的話刁憋,只繼承除class style props之外的屬性
props: {
limit: { // 小數(shù)點(diǎn)保留位數(shù)
type: Number,
required: true
}, // 小數(shù)點(diǎn)長度
maxLimit: Number, // 最大數(shù)值
minLimit: Number, // 最小數(shù)值
value: [String, Number] // value值
},
watch: { // watch的目的是異步獲取value值仍然可以賦值成功
value: {
handler (val) {
this.defaultValue = val
},
immediate: true // 給組件設(shè)置默認(rèn)值
}
},
methods: {
inputHandle (e) {
let val = e.target.value || ''
if (!val) {
val = this.defaultValue
}
this.formatNumber(val)
},
formatNumber (val) {
val = String(val).replace(/e/, '') // 替換e為空
if (/\./.test(val)) { // 控制小數(shù)點(diǎn)位數(shù)
// 替換掉小數(shù)點(diǎn)后面的點(diǎn)和非數(shù)字
let str = val.split('.')[1].replace(/\./g, '').replace(/\D/g, '')
val = val.split('.')[0] + '.' + str.substr(0, this.limit)
} else {
val = String(val).replace(/\D/g, '')
}
// 判斷是否超過最大值
if (this.maxLimit && Number(val) >= this.maxLimit) {
val = String(this.maxLimit)
}
// 判斷是否小于最小值 不等于0的目的是為了可以刪除所有
if (this.minLimit && Number(val) !== 0 && Number(val) <= this.minLimit) {
val = String(this.minLimit)
}
this.defaultValue = val
this.$refs.input.currentValue = val
this.$emit('input', val)
}
},
mounted () {
console.log(this.$listeners)
}
}
</script>
<style lang="scss" scoped>
</style>