Могу ли я передать функцию в реквизит на компоненте VueJS - PullRequest
0 голосов
/ 11 мая 2018

У меня довольно простой компонент. По сути, это выпадающий список select, и мне нужно запустить некоторый пользовательский код, который находится во внешней функции JavaScript. Однако эта опора не требуется для каждого экземпляра компонента. Поэтому иногда в опоре ничего не может быть. В других случаях это может делать одно, другие могут делать что-то другое.

<template id="drop-list-template">
  <select class="form-control"
          v-model="value"
          v-bind:class="{ required: isRequired, invalid: !isValid }"
          v-on:blur="validate"
          v-on:change="changed">  <-- This is the Prop I want to use
    <option v-if="showEmptyOption" value="">{{ emptyOption }}</option>
    <option v-for="i in items"
            v-bind:value="i.value"
            v-bind:selected="i.checked === value"
            v-bind:disabled="i.enabled === false">
      {{ i.text }}
    </option>
  </select>
</template>

Таким образом, в событии on-change он вызовет метод changed. Это не сработало. Затем я добавил special реквизит в файл кода:

Vue.component("drop-list", {
  template: "#drop-list-template",
  props: {
    dataset: { type: Array, required: true },
    isRequired: { type: Boolean, required: false, default: false },
    emptyOption: { type: String, required: false, default: "*Select an Option *" },
    showEmptyOption: { type: Boolean, required: false, default: true },
    special: { required: false }
  },
  data: function () {
    return {
      items: this.dataset,
      isValid: true,
      value: ""
    }
  },
  methods: {
    validate: function (event) {
      var Result = true;

      if ((this.isRequired === true) && (this.value === ""))
        Result = false;

      this.isValid = Result;

      return Result;
    },
    changed: function (event) {
      if (this.special) {
        AbnormalitiesAndImpressions(); <-- Obviously this works
        alert("After");
        this.special();  <-- Would want this to run AbnormalitiesAndImpressions
      }
    }
  }
});

И реализовать это через:

<drop-list ref="lstAbnormalities"
           v-bind:dataset="Abnormalities"
           v-bind:is-required="true"
           special="AbnormalitiesAndImpressions">
</drop-list>

Где AbnormalitiesAndImpressions прямо сейчас тупой:

function AbnormalitiesAndImpressions(lstAbs, lstImps) {
  alert("Got to here");
}

Когда я запускаю его, появляется предупреждение «Got to here», а также предупреждение «After». Затем происходит сбой, потому что this.special(); не является функцией.

Суть в том, что я пытаюсь позволить пользователю (самому себе) создать столько списков, сколько необходимо. Что произойдет с некоторыми из них, так это то, что они настроят то, что доступно в других элементах управления Таким образом, происходит своего рода проверка. Я просто хочу, чтобы это настраивалось для каждого использования компонента.

Я бы даже работал с анонимной функцией, подобной следующей:

<drop-list ref="lstAbnormalities"
           v-bind:dataset="Abnormalities"
           v-bind:is-required="true"
           special="function () { AbnormalitiesAndImpressions(); }">
</drop-list>

Обновление Я немного обновил свой компонент:

<template id="drop-list-template">
  <select class="form-control"
          v-model="value"
          v-bind:class="{ required: isRequired, invalid: !isValid }"
          v-on:blur="validate"
          v-on:change="change">
    <option v-if="showEmptyOption" value="">{{ emptyOption }}</option>
    <option v-for="i in items"
            v-bind:value="i.value"
            v-bind:selected="i.checked === value"
            v-bind:disabled="i.enabled === false">
      {{ i.text }}
    </option>
  </select>
</template>

и соответствующий ему javascript:

Vue.component("drop-list", {
  template: "#drop-list-template",
  props: {
    dataset: { type: Array, required: true },
    isRequired: { type: Boolean, required: false, default: false },
    emptyOption: { type: String, required: false, default: "*Select an Option *" },
    showEmptyOption: { type: Boolean, required: false, default: true },
    special: { type: Function, required: false }
  },
  data: function () {
    return {
      items: this.dataset,
      isValid: true,
      value: ""
    }
  },
  methods: {
    change: function (event) {
      if (this.special)
        this.special();
    }
  }
});

И реализация:

<drop-list ref="lstAbnormalities"
           v-bind:dataset="Abnormalities"
           v-bind:is-required="true"
           :special="AbnormalitiesAndImpressions">
</drop-list>

А вот код Vue страницы:

var vm = new Vue({
  el: "#app",
  data: {
    Result: {},
    Defaults: {},
    Errors: [],
    Abnormalities: [],
    Impressions: []
  },
  methods: {
    AbnormalitiesAndImpressions: function () {
      alert("Should get overridden");
    }
  }
});

vm.AbnormalitiesAndImpressions = function (lstAbs, lstImps) {
  alert("Got to here: " + lstAbs + "\n" + lstImps);
}

Я обнаружил, что если я не добавлю methods короткую версию AbnormalitiesAndImpressions, это даст мне предупреждение Vue о том, что свойство не существует. Однако версия AbnormalitiesAndImpressions в нижней части этого файла фактически работает. Мне нравится это, поскольку каждая реализация может меняться, и они должны быть на странице, а не на компоненте.

Когда я меняю выпадающий элемент, я получаю сообщение Got to here. И, конечно, у него есть два undefined, поскольку lstAbs и lspImps не были переданы.

Новый вопрос

Можно ли передать значения моей функции props? В этом случае они могут быть strings. Но если я сделаю код ниже ...

<drop-list ref="lstAbnormalities"
           v-bind:dataset="Abnormalities"
           v-bind:is-required="true"
           :special="AbnormalitiesAndImpressions('test')">
</drop-list>

Когда страница загружается, alert сразу же появляется и имеет параметр test. И когда я на самом деле меняю select, alert вообще не срабатывает.

1 Ответ

0 голосов
/ 14 мая 2018

Хорошо, давайте сделаем это шаг за шагом.

Правильное объявление метода

methods: {
    change: function (event) {
      if (this.special)
        this.special();
    }
}

Это объявление метода не подходит, оно меняет this context, всегда объявляйте методы с функциями стрелок или с кратким синтаксисом .Анонимные функции объявлены так: function () { //... } создает новый контекст this, и потому что this.special всегда неопределен.Так что измените его на:

methods: {
    change (event) {
      if (this.special)
        this.special();
    }
}

Делайте это любыми методами, это поможет избежать головной боли.Для других анонимных функций всегда используйте функции стрелок .

Метод передан как prop

По поводу вашего нового вопроса, позвольтеЯ объясню, что происходит, когда вы устанавливаете special реквизит как AbnormalitiesAndImpressions с ванильными J, чтобы прояснить ваш ум.

Подумайте о методе foo, как показано ниже:

function foo (string) {
    return string;
}

Выше мы видим объявление метода, в Js можно назначить функцию переменной, поэтому, если создать переменную a, она может быть равна foo, как это:

let a = foo;

Как видите, я передаю функцию foo в переменную a, а не возвращаю функцию foo, это то, что вы делаете, когда устанавливаете свойство special как AbnormalitiesAndImpressions, потому чточто вы не можете сделать это: :special="AbnormalitiesAndImpressions('test')", но, если мы вернемся к моему примеру, мы можем сделать одну вещь:

a('bar');

И он вернет 'bar', поэтому, применяя его к Vue, в вашем компоненте drop-list, где вы вызываете функцию как this.special, вы можете передавать параметры в функцию, получили ли выЭто?

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