Vue.js: использование метода объекта данных во встроенном обработчике событий - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть компонент Vue (2.5+), в котором я устанавливаю свойство данных для нового объекта Foo. Использование foo.bar() в обработчике кликов вызывает метод правильно, но выдает Uncaught TypeError: cannot set property 'someVariable' of null при попытке изменить свойства внутри класса Foo. Настройка так, что Foo является литералом объекта вместо класса, также не устраняет ошибку.

Я подозреваю, что с this что-то странное происходит между компонентом и классом?

Vue компонент

import Foo from './foo.js'
export default {
    template: `<div @click="foo.bar"></div>`,
    data() {
        return {
            foo: new Foo()
        }
    },
    created() {
        console.log(foo); // foo is not null here
    }
}

класс Foo

export default class Foo
{
    constructor()
    {
        this.someVariable = 0;
    }

    bar(e)
    {
        // modify this.someVariable
    }
}

но если я изменю компонент vue для ссылки на внешний метод через его собственное свойство "method", он будет работать.

Vue компонент (рабочий)

import Foo from './foo.js'
export default {
    template: `<div @click="bar"></div>`,
    data() {
        return {
            foo: new Foo()
        }
    },
    methods: {
        bar(e) {
            this.foo.bar(e);
        }
    }
}

1 Ответ

0 голосов
/ 07 ноября 2018

Как сказано в комментариях, foo.bar без какого-либо контекста к нему:

В JS-функциях есть объекты, как и у любого объекта, у них есть свой this «указатель».
При оценке их тела this привязывается к определенному объекту, называемому context, который является контекстом по умолчанию (устанавливается автоматически) или определяется пользователем (устанавливается вручную).

Наследование в JS достигается через цепочку прототипов и методы должны быть определены в / присоединены к прототипу класса. Из-за этого при звонке foo.bar():

  • Вы находитесь в контексте вызова метода, поэтому foo будет привязан к методу
  • bar сначала ищется на объекте, затем в цепочке прототипов

Но методы ведут себя так же, как и любое другое свойство: когда вы делаете foo.bar, вы получаете ссылку на фактический метод, который является несвязанной функцией (поведение по умолчанию для методов, так как оно вызывается при вызове объект).

Следовательно, в этой ситуации вам действительно нужно сделать foo.bar.bind(foo).

Я бы также предложил взглянуть на это предложение ES6 для оператора связывания и его реализацию в виде плагина Babel , который позволяет делать приятные вещи, такие как передача ::foo.bar вместо foo.bar.bind(foo)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...