【问题标题】:Can't access this object due to complex js function - Vuejs由于复杂的 js 函数而无法访问此对象 - Vuejs
【发布时间】:2021-03-16 05:14:05
【问题描述】:

我正在为一个 VueJs 项目使用流行的 vue-select 组件。我想自定义一个 keyDownEvent 并查看文档以了解如何实现这一点。我遇到了一个使用现代 JS 技术组合的神秘示例。

<template>
  <v-select
          taggable
          multiple
          no-drop
          :map-keydown="handlers"
          placeholder="enter an email"
  />
</template>

<script>
export default {
  name: 'CustomHandlers',
  data: {
      variableIwantAccessTo: []
  },
  methods: {
    handlers: (map, vm) => ({
      ...map, 50: e => {
        e.preventDefault();
        if( e.key === '@' && vm.search.length > 0 ) {
          vm.search = `${vm.search}@gmail.com`;
        }
      },
    }),
  },
};
</script>

我了解 if 块中的简单逻辑,但我不了解导致它的所用技术的组合。我在自定义实现中遇到的主要问题是丢失了 this 对象的上下文。我想要这样的东西:

    handlers: (map, vm) => ({
  ...map, 50: e => {
    e.preventDefault();
    if( e.key === '@' && vm.search.length > 0 ) {
      console.log(this.variableIwantAccessTo);
    }
  },

我不知道如何通过这个实现传递它。 这是文档的参考:https://vue-select.org/guide/keydown.html#mapkeydown

【问题讨论】:

  • 哦,vm 不是我想的 Vue 实例。您必须将handler: (map, vm) =&gt; ({/*...*/}) 更改为handler(map, vm) { return {/*...*/} },这样您就可以使用this 作为Vue 实例。
  • 我用 Eason Yus 的答案尝试了这个,它甚至在第一个箭头函数开始时立即注册为未定义。
  • 没有看到您尝试过的代码,我情不自禁。这是我描述的一个工作演示:codepen.io/tony19/pen/ExgPEKV
  • 啊,是的,这也是我更喜欢的写法。实际上,我只是在您的帖子之前使用 function() {} 而不是箭头符号自己解决了这个问题。

标签: javascript vue.js this arrow-functions ellipsis


【解决方案1】:

如你所见,本例实际上有两层函数,处理函数的原始样式省略了{},所以你没有地方在外部函数中定义一个self(对this的引用) .

在vue组件中,外层的this会指向组件,所以我们在这里声明self,然后在内层使用self作为闭包变量。

我想这会成功,请尝试一下。

export default {
  name: 'CustomHandlers',
  methods: {
    // handlers: (map, vm) => {
    // if it is arrow function,it can't do the trick 
    // thanks to  Yair Cohen
       handlers(map, vm) {
        const self = this;
        return {
          ...map, 50: e => {
            e.preventDefault();
            if( e.key === '@' && vm.search.length > 0 ) {
              vm.search = `${vm.search}@gmail.com`;
              // self will be this here
              const self2 = self;
            }
          },
        };
    },
  },
};

更新:代码更改,外部函数从箭头函数变为正常函数,

【讨论】:

  • 这仍然不起作用,因为处理程序函数是箭头函数而不是常规函数,所以这里仍然未定义。如果您将其更改为常规功能,它将起作用
  • 是的,你是对的,我只是做了一个演示来测试我的代码,我会编辑它以防错误地指导其他人。
  • 感谢 @YairCohen 分解函数,并感谢 tony19 提供使用“this”的工作示例。在使用此答案并最近在另一个项目中处理此问题后,我最终自己得出了结果。对于那些还不知道的人,请查看文档中的此部分vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks
【解决方案2】:

让我们分解一下这个函数:

  1. 您正在声明一个名为 handlers 的箭头函数,它接受名为 mapvm 的两个参数。

您丢失上下文的原因是因为您使用箭头函数作为方法,如果您将该箭头函数更改为常规函数,您将能够访问this

话虽如此,它似乎是故意这样设计的,通过查看代码,我可以假设您应该将上下文作为第二个参数传递 - vm

  1. 您正在返回一个对象:在对象的第一部分中,您使用扩展运算符扩展map 参数,由此我们可以假设map 也是一个对象并且您想要返回一个对象包含对象映射本身。 (通过使用扩展运算符,您实际上是将map 合并到您要返回的对象中。

你要返回的对象的第二部分是一个名为50的属性,这个属性是一个接收事件的方法,在那个事件上调用preventDefault(),然后有一个if语句,如果那个if语句通过它将vm.search 分配给某个值。

由于我们假设vm 代表上下文,这与分配this.search 相同,因此它本质上是为上下文中的变量分配特定值。

希望现在更清楚:)

【讨论】:

  • 从技术上讲,事件处理程序中不需要this。元素this 通常指向可从传入的事件对象中获得。
  • 只有当它是一个常规函数时,带有箭头函数的 this 才会等于封闭范围内的 this 值,在这种情况下它仍然是未定义的。
  • 嗯,是的,你在箭头函数中得到的this 是碰巧从上下文继承的,如果它碰巧存在的话。我的观点是:不要在事件处理程序中使用this;使用事件对象。无需切换到常规功能。
  • 不,在第一个箭头函数之后没有自调用函数,括号在那里,因为这就是您返回多行表达式的方式。查看更多关于其工作原理的示例:stackoverflow.com/questions/20824558/…
  • @YairCohen 不完全是。相反,它是箭头函数对 object literal 的隐式返回。该对象需要用括号括起来,以便解析器可以将其与 块语句 区分开来。
猜你喜欢
  • 2022-07-29
  • 1970-01-01
  • 1970-01-01
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
  • 2020-02-18
  • 2023-04-10
相关资源
最近更新 更多