Передача строки в функцию, но ожидание массива

1

У меня есть раскрывающийся список выбора, который при изменении я хочу, чтобы он запускал функцию и передавал значение выбора в эту функцию. Однако функция ожидает переменную, удерживающую массив, и то, что передается, является строкой (значение выбора).

Вы можете увидеть, как он работает (или не работает) в коде ниже. Выбранное значение должно представлять соответствующую переменную.

Как я могу это сделать?

var str = ["Paul", "John", "Melissa", "Mike"];
var int = [8, 4, 55, 7];
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(arr){
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

testFunc(mix);

sel.addEventListener('change', testFunc(sel.value));
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

РЕДАКТИРОВАТЬ:

Я должен отметить, что массивы данных поступают динамически, и я действительно хотел бы избежать манипулирования ими, чтобы не вызывать дополнительный код и путаницу в будущих изменениях.

  • 0
    Почему вы хотите жалить функцию? Это вызвало у вас какие-либо проблемы?
  • 0
    Ваша функция когда-нибудь передала массив? Если нет, то перекодировать. Если это так, то почему бы просто не иметь другую функцию для строк?
Показать ещё 1 комментарий
Теги:
select
arrays

5 ответов

1
Лучший ответ

В вашем коде есть две проблемы:

  1. В функции обработчика события, указав скобки после функции, вызываемой функцией при загрузке страницы. Просто вызовите функцию внутри тела функции. Это заставит функцию вызываться только при срабатывании события.

  2. sel.value - это строка, но функция ожидает массив. Для оценки массива динамически меняйте testFunc(mix) на testFunc('mix') (оберните значение параметра кавычками) и используйте объект window например:

    arr = window[arr]
    

Заменить:

sel.addEventListener('change', testFunc(sel.value));

С

sel.addEventListener('change', function (){testFunc([sel.value])});

var str = ["Paul", "John", "Melissa", "Mike"];
var int = [8, 4, 55, 7];
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(arr){
  arr = window[arr]
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

testFunc('mix');

sel.addEventListener('change', function (){testFunc(sel.value)});
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>
  • 0
    это вызовет ту же ошибку, вы передаете строковое значение и пытаетесь перебрать его как массив. это бесполезно
  • 0
    @ mr.void, [sel.value] определенно не строка ........
Показать ещё 10 комментариев
1

как я понимаю, вы хотите сделать это:

let model = {
    str : ["Paul", "John", "Melissa", "Mike"];
    int : [8, 4, 55, 7];
    mix : ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];
}


function testFunc(key){
    var arr = []
    if(model[key]){
        arr = model[key]
    }


    //TODO: clear parent node...
    arr.forEach((i) => {
        var p = document.createElement('p');
        p.innerHTML = i;
        main.appendChild(p);
    });
}
  • 0
    К сожалению, массивами, которые передаются, я не могу манипулировать ... Я имею в виду, что могу, но я бы предпочел просто использовать то, что приходит, как-только для того, чтобы сохранить код "чище".
  • 0
    @ Sergio Динамический доступ к переменным - плохой дизайн, он ограничивает возможности использования функции. Замена динамических переменных объектами является правильным подходом.
1
arr = eval(arr);

var str = ["Paul", "John", "Melissa", "Mike"];
var int = [8, 4, 55, 7];
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(arr){
  arr = eval(arr);
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

testFunc(mix);

sel.addEventListener('change', function(){testFunc(this.value)});
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>
  • 0
    eval следует избегать. Это действительно не обязательно, чтобы сделать эту работу.
  • 0
    @trincot Не могли бы вы объяснить, почему Eval следует избегать. Это на самом деле сработало для меня, и я не могу манипулировать передачей массивов ... Я мог бы, но я бы предпочел нет.
Показать ещё 3 комментария
1

Несколько вещей, которые нужно изменить:

  • Не вызывайте функцию, которую вы передаете методу addEventListener. Вместо этого передайте ссылку на функцию. Это может быть встроенное выражение функции. Но не называйте это.

  • Сделайте свои разные свойства массивов одной переменной объекта, поэтому вы можете легко ссылаться на них на основе выбранного значения.

  • Удаляйте вывод при каждом изменении выбора.

  • Запустите исходное изменение на основе элемента, выбранного при загрузке страницы.

Вот рабочая версия:

var arr = {
    str: ["Paul", "John", "Melissa", "Mike"],
    int: [8, 4, 55, 7],
    mix: ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]
};

var main = document.querySelector('#main');
var sel = document.querySelector('select');

function testFunc(arr){
  main.innerHTML = ""; // clear the previous result
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

sel.addEventListener('change', () => testFunc(arr[sel.value]));
testFunc(arr[sel.value]); // initial load
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

Если ваши массивы определены в глобальной области действия, и вы ничего не можете с этим поделать, просто скопируйте ссылки на них в новом объекте:

// Defined beforehand: you cannot change this:
var str = ["Paul", "John", "Melissa", "Mike"],
var int = [8, 4, 55, 7],
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]

// In your part of the code, still create array as in above solution:
var arr = {str: str, int: int, mix: mix};
// If you have ES6 support you can shorten the above to:
var arr = {str, int, mix};
  • 0
    trincot, ваше решение работает, но как я могу это сделать, не манипулируя массивами? Они приходят динамически, и я действительно хотел бы избежать возни с ними, чтобы не генерировать дополнительный код / путаницу.
  • 0
    Что вы имеете в виду под «входить динамически»? Вы можете быть более конкретным?
Показать ещё 1 комментарий
0

Если я не неправильно понял ваше требование, вы должны внести небольшие изменения в свои текущие переменные JS и перейти к Object. После этого попробуйте этот способ добавить новые элементы абзаца в каждое event изменения выпадающего меню, удалив существующий с помощью main.innerHTML=''

addEventListener: https://developer.mozilla.org/en-US/docs/Web/Events/change

Структура объекта: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics

var data_types = {
  str: ["Paul", "John", "Melissa", "Mike"],
  int: [8, 4, 55, 7],
  mix: ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]
}

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(event) {
   main.innerHTML = '';
  // You can use "this" to refer to the selected element.
  if (!event.target.value) alert('Please Select One');
  var arr = data_types[event.target.value];
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}
  
document.addEventListener('DOMContentLoaded', function() {
  document.querySelector('select[name="data-types"]').onchange = testFunc;
}, false);
<select name="data-types">
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>
  • 0
    Будучи солнечным, я бы предпочел не манипулировать массивами и хранить их так, как я перечислил изначально. Они входят динамически, и, чтобы избежать путаницы и дополнительного кода, я, скорее, остаюсь их собственным массивом / переменной.
  • 0
    @ Sergio, если это происходит динамически, тогда вы можете нажать их со значением ключа в этом шаблоне объекта.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню