深入瞭解vue自定義組件之$listeners

官方文檔地址
$listeners是vue提供的一個對象,裏面包含了所有作用在這個組件上的監聽器。
比如你要自定義一個input組件,需要監聽input獲取焦點的事件
你可以這樣做
自定義組件代碼

<template>
    <div>
        <input type="text" v-on:focus="handleFocus" v-on:input="handleInput" />
    </div>
</template>

<script>
    export default {
        name: "ListenersDemo",
        props:{
            value: String
        },
        methods:{
            handleFocus(event){
                this.$emit("focused",event)
            },
            handleInput(event){
                this.$emit("input",event)
            }
        }
    }
</script>

父組件代碼

<listeners-demo class="my-btn" v-on:focused="handleFocus" v-on:input="input" ></listeners-demo>

這樣就可以實現預期的功能,但是你也可以使用更優雅的做法
修改之後
自定義組件代碼

<template>
    <div>
<!--        接管所有原生監聽事件-->
<!--        <input type="text" v-on="$listeners" />-->
<!--        自定義監聽器 接管所有原生監聽事件 可添加自定義監聽事件並可以配合v-model使用-->
        <input type="text" v-on="inputListeners" v-bind:value="value" />
    </div>
</template>

<script>
    export default {
        name: "ListenersDemo",
        props:{
            value: String
        },
        computed:{
            inputListeners(){
                var vm = this
                // `Object.assign` 將所有的對象合併爲一個新對象
                return Object.assign({},
                    // 我們從父級添加所有的監聽器
                    this.$listeners,
                    // 然後我們添加自定義監聽器,
                    // 或覆寫一些監聽器的行爲
                    {
                        // 這裏確保組件配合 `v-model` 的工作
                        input: function (event) {
                        	// 重寫了input監聽器,你也可以理解爲自定義了一個名爲input的監聽器
                            vm.$emit('input', event.target.value)
                        }
                    }
                )
            }
        },
    }
</script>

父組件完整代碼

<template>
    <div>
        <listeners-demo v-on:focus="handleFocus" v-on:input="handleInput" v-model="value" ></listeners-demo>
    </div>
</template>

<script>
    import ListenersDemo from "@/components/ListenersDemo";
    export default {
        name: "home",
        components: {
            ListenersDemo
        },
        data: () => ({
            value: '111111'
        }),
        methods:{
            handleInput(value){
                // eslint-disable-next-line no-console
                console.log(value)
            },
            handleFocus(event){
                // eslint-disable-next-line no-console
                console.log(event)
            }
        }
    }
</script>

使用v-on="$listeners" 將所有的事件監聽器指向這個組件的某個特定的子元素
也可以使用一個計算屬性重寫$listeners,上面代碼中使用inputListeners重寫了$listeners
這樣就不用爲每一個監聽器寫一個監聽函數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章