功能组件的子事件处理程序中的'this'上下文

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了功能组件的子事件处理程序中的'this'上下文相关的知识,希望对你有一定的参考价值。

我正在尝试为功能组件的子组件/元素创建自定义事件处理程序。问题是当使用render()函数创建子组件时,我无法访问他们的this上下文。

假设我们有以下功能组件:

const Aggregate = {
    functional: true,
    props: {
        value: Object // to work with v-model
    },
    render: function(createElement, context){
        const template = []
        const inputHandler = function(value, prop){
            const data = Object.assign({}, context.props.value, { [prop]: value })
            console.log(context.props.value)
            console.log(data)
            this.$emit('input', data)
        }
        for (const prop of Object.keys(context.props.value)){
            const child = createElement('input', {
                props: {
                    value: context.props[prop]
                },
                on: {
                    input: function(event){
                        // 'this' is not binded here - it is undefined,
                        // hence the inputHandler() function is
                        // rising an error
                        inputHandler.apply(this, [event.target.value, prop])
                    }
                }
            })
            template.push(child)
        }
        return template
    }
}

当以这种方式创建事件处理程序时,是否可以访问vnode的this上下文?

附:用例信息:我想实现一个为资源自动生成<input>元素的组件,并通过v-model指令使用双向绑定。我也想在<table>中使用它,在那里需要包装<td>,因此我使组件起作用。

答案

功能组件没有“this”,因为它们没有Vue实例。这使它们轻量级。

这也意味着从它们发出事件更难,因为你需要自己实现Vue逻辑。

缺少实例并不意味着您不能发生事件,而是需要手动解析context.listeners并手动调用事件处理程序。在v-model的情况下,你需要调用input监听器:

const Aggregate = {
    functional: true,
    props: {
        value: Object // to work with v-model
    },
    render: function(createElement, context){
        const template = []
        const inputHandler = function(value, prop, handler){
            const data = Object.assign({}, context.props.value, { [prop]: value })
            console.log(context.props.value)
            console.log(data)
            // Call handler directly instead of using this.$emit
            handler(data)
        }
        for (const prop of Object.keys(context.props.value)){
        console.log(context.props.value, prop)
            const child = createElement('input', {
                // Small bug fixes in the following section:
                domProps: {
                    value: context.props.value[prop]
                },
                // End bug fixes
                on: {
                    input: function(event){
                        // pass `context.listeners.input` instead of binding here
                        inputHandler(event.target.value, prop, context.listeners.input)
                    }
                }
            })
            template.push(child)
        }
        return template
    }
}


new Vue({
  el: "#app",
  components: {
  	Aggregate
  },
  data: {
    test: {
    	key1: "val1",
    	key2: "val2",
      
    }
  },
})
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <aggregate  v-model="test"></aggregate>
  <pre>{{ test }}</pre>
  <button @click="test = {...test, ping: 'pong'}">Add key</button>
</div>

以上是关于功能组件的子事件处理程序中的'this'上下文的主要内容,如果未能解决你的问题,请参考以下文章

React学习第三步:组件相关学习,以及事件中this指向问题

第39课 Qt中的事件处理(下)

使用on()jQuery方法将'this'作为参数传递给事件处理程序

在 Javascript 中访问事件处理程序中的类成员变量

Monodroid - 处理重用 ListView 行的子视图上的事件

如何在 KeyDown 事件的子组件中调用父组件中定义的函数?