Неперехваченная ошибка ссылки: имя функции не определено при импорте

#javascript #jquery

#javascript #jquery

Вопрос:

Я разделил функции JS с разных веб-страниц (index, login, register и другие) на их собственные файлы JS, которые затем импортируются в основной файл JS, который включает функции, которые являются общими для более чем одной страницы. Я сделал это с целью обслуживания и удобочитаемости кода (я надеюсь), иначе у меня были бы сотни строк кода в одном файле.

login.js

 export function loginSubmit() {
  $("#login-form").submit(function (event) {
    event.preventDefault();
    event.stopPropagation();
    let formValid;

    $("#login-form input").each(function () {
      if ($(this).val() === "") {
        fieldInputInvalid($(this));
        formValid = false;
      }
    });

    if (formValid !== false) {
      // submit the form for authentication
    }
  });
}
  

register.js

 export function loginSubmit() {
  $("#register-form").submit(function (event) {
    event.preventDefault();
    event.stopPropagation();
    let formValid;

    // other form validation functions (not shown as not necessary to post)  

    $("#register-form input").each(function () {
      if ($(this).val() === "") {
        fieldInputInvalid($(this));
        formValid = false;
      }
    });

    if (formValid !== false) {
      // submit the form for user registration
    }
  });
}
  

main.js

 // import all functions from these js files
import * as login from "../scripts/login.js";
import * as register from "../scripts/register.js";

// general functions used on more than one page
function fieldInputInvalid(inputField) {
  // Changes styling of inputField to display to user that it is invalid.
}

function fieldInputValid(inputField) {
  // Changes styling of inputField to display to user that it is valid.
}

function createElement(elemName, elemAttributes) {
  // Create document element
  var elem = document.createElement(elemName);
  // Check if element attirbutes were passed
  if (elemAttributes !== "undefined") {
    // Loop through each argument
    $.each(elemAttributes, function (key, value) {
      // and assign it to the document element
      elem.setAttribute(key, value);
    });
  }
  // Return document element
  return elem;
}
  

Как вы можете видеть из моих примеров кода, оба login.js и register.js функции вызывают функцию fieldInputInvalid() из main.js , однако я получаю Uncaught ReferenceError: fieldInputInvalid is not defined ошибку при отправке любой из форм. Я знаю, что могу обойти это, поместив функцию fieldInputInvalid в оба login.js и register.js , но я думал, что это нарушит правило «не дублировать код». Есть ли способ заставить это работать с моей текущей структурой или лучший способ достичь желаемого результата?

(ПРИМЕЧАНИЕ: у меня есть много других общих функций, которые не включены в этот пост, которые будут использоваться на моем веб-сайте. Я знаю, что я мог бы поместить код из login.js и register.js вместе в один файл с именем identity.js с помощью функций fieldInputInvalid и fieldInputValid и последующего экспорта, но это не решило бы ни одной из других общих функций, которые включены в мой проект.

Ответ №1:

Объявите fieldInputInvalid в своем собственном файле, а затем login и register импортируйте его:

 // fieldInputInvalid.js
export const fieldInputInvalid = () => {
  // ...
}
  
 // login.js
import { fieldInputInvalid } from './fieldInputInvalid';
// ...
  

Другим вариантом было бы при каждом loginSubmit вызове передавать ему fieldInputInvalid функцию, если вы можете, например:

 loginSubmit(fieldInputInvalid);
  
 // login.js (and register.js):
export function loginSubmit(fieldInputInvalid) {
  // ...
  

Тогда вы сможете вызывать fieldInputInvalid внутри loginSubmit .

Если у вас есть несколько общих функций, и вы не хотите передавать каждую из них по отдельности, вы также можете передать объект функций всем loginSubmit функциям, например:

 loginSubmit({ fieldInputInvalid, someOtherHelper });
  
 // login.js (and register.js):
export function loginSubmit({ fieldInputInvalid, someOtherHelper }) {
  // ...
  

Комментарии:

1. Спасибо за это решение, я попробую, но я замечаю, что выполнение этого таким образом означало бы, что все мои общие функции нужно было бы поместить в отдельный файл js, а мой main.js файл будет просто файлом импортированных функций js. Это нормально или допустимо с профессиональной точки зрения?

2. Да, я бы хотел поместить все общие функции (которые используются во многих местах) в их собственные файлы. Это зависит от длины функций — если они короткие, вы могли бы поместить их все в один файл. Если они длинные, вероятно, было бы удобнее иметь отдельные файлы для каждой функции (что я и делаю). После этого у вас все еще есть выбор: либо loginSubmit импортировать эти файлы, либо импортировать их туда, где loginSubmit вызывается, и вместо этого передать объект функций.

3. Хорошо, спасибо, что прояснили это. Вы оказали большую помощь!