분류 javascript

10 장. HTML 폼과 localStorage 사용

컨텐츠 정보

  • 조회 232 (작성일 )

본문

HTML 양식에 대한 재도입 


웹 페이지는 데이터를 표시 할 뿐입니다. 오랫동안 사용되어 온 HTML 양식 덕분에 사용자 데이터를 수집하고 조작 할 수 있습니다. 이 장에서는 일부 노트를 캡처 하기 위한 간단한 HTML 양식을 작성합니다. 나중에 해당 데이터를 브라우저에 저장합니다. 이 과정에서 8 장에서 소개 된 DOM 이벤트에 대해 더 배우게 됩니다. <form> 요소는 HTML 요소로서 다음과 같은 다른 하위 요소를 포함 할 수 있습니다.

  • 데이터 캡처를 위한 <input>
  • 텍스트를 캡처 하기 위한 <textarea>
  • 양식을 보내기 위한 <button>

이 장에서는 <input>, <textarea> 및 <button>을 포함하는 양식을 작성합니다. 이상적으로 모든 입력에는 입력 유형을 나타내는 type이라는 속성이 있어야 합니다 (예 : 텍스트, 전자 메일, 번호, 날짜 등). 유형 외에도 모든 양식 요소에 id 속성을 추가 할 수도 있습니다. 나중에 각 입력에서 데이터를 검색하는 데 유용하게 바뀌는 것을 볼 수 있습니다. 입력 및 텍스트 영역에도 이름 속성이 있을 수 있습니다. JavaScript없이 양식을 보내려면 name 속성이 중요합니다. 1 분 안에 더 자세히 알아보십시오.

또한 모든 양식 요소를 <label>과 연결하는 것이 일반적입니다. 아래 예에서 각 레이블은 관련 입력 요소의 id 속성에 속성 결합을 가지고 있습니다. 혼란스러워요? 걱정마세요.

대부분의 경우 필요에 따라 양식 입력을 표시하는 것이 좋습니다. 필요한 정보를 모두 채우지 않으면 양식을 제출할 수 없습니다. 빈 데이터를 피하기 위한 간단한 검증으로 사용자가 중요한 필드를 건너 뛰지 못하게 합니다. 이 지식으로 HTML 양식을 작성할 준비가 되었습니다. form.html이라는 새 파일을 작성하고 HTML을 빌드 하십시오.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML forms and JavaScript</title>
</head>
<body>
<h1>What's next?</h1>
<form>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required>

    <label for="description">Short description</label>
    <input type="text" id="description" name="description" required>

    <label for="task">Task</label>
    <textarea id="task" name="tak" required></textarea>

    <button type="submit">Submit</button>
</form>
</body>
<script src="form.js"></script>
</html>


보시다시피 양식 입력에는 모든 올바른 속성이 있으며 이제부터 일부 데이터를 채워서 양식을 테스트 할 수 있습니다. HTML 양식을 작성할 때 type 속성에 특히 주의하십시오 (이유가 있습니다). 사용자가 입력 할 수 있는 데이터 종류를 결정합니다.

HTML5는 또한 양식 유효성 검사를 도입했습니다. 예를 들어 전자 메일 입력은 "at"기호 @가 포함 된 전자 메일 주소 만 허용합니다. 불행히도 이것이 전자 메일 주소에 적용되는 유일한 검사입니다. 아무도 사용자가 a@a와 같은 전자 메일을 입력하지 못하게 합니다. @가 있지만 여전히 유효하지 않습니다 (이메일 입력의 패턴 속성이 문제를 완화하는 데 도움이 될 수 있음).

계속 진행하기 전에 양식 입력을 조정하십시오. <input>에는 많은 속성이 있으며 minlength와 maxlength가 가장 유용합니다. 실제 앱에서는 게으른 스팸 발송자가 "aa"또는 "testtest"를 사용하여 양식을 보내지 못하게 할 수 있습니다.

최소 길이의 정상 기본값은 5이고 최소 작업 길이는 10 일 수 있습니다 (마일리지는 다를 수 있음).


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML forms and JavaScript</title>
</head>
<body>
<h1>What's next?</h1>
<form>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required minlength="5">

    <label for="description">Short description</label>
    <input type="text" id="description" name="description" required minlength="5">

    <label for="task">Task</label>
    <textarea id="task" name="tak" required minlength="10"></textarea>

    <button type="submit">Submit</button>
</form>
</body>
<script src="form.js"></script>
</html>


그리고 양식이 제자리에 있으면 더 나아갈 준비가 되었습니다. 양식이 실제로 작동하는지 봅시다.


HTML 양식 사용 


HTML 양식은 HTMLFormElement 유형의 요소입니다. 거의 모든 HTML 요소와 마찬가지로 HTMLElement에 연결되어 EventTarget에 연결됩니다. 프로토 타입이 다시 등장합니다. DOM 요소는 도달 할 때 JavaScript 객체로 표시됩니다. 브라우저에서 이것을 시도하십시오 :


const aForm = document.createElement("form");
console.log(typeof aForm);


출력은 "object"이고 HTMLElement 또는 EventTarget과 같은 엔티티는 함수입니다.


console.log(typeof EventTarget); // "function"


HTML 요소가 EventTarget에 연결된 경우 <form>은 EventTarget의 "인스턴스"라는 의미입니까? 직접 확인해 보세요 :


const aForm = document.createElement("form");
console.log(aForm instanceof EventTarget);


결과는 "true"입니다. 양식은 특수한 종류의 EventTarget입니다. 모든 EventTarget은 DOM 이벤트를 수신하고 이에 반응 할 수 있습니다 (8 장 참조). click, blur, change 등과 같은 여러 유형의 DOM 이벤트가 있습니다.

흥미로운 점은 이제 HTML 양식을 특징으로 하는 submit 이벤트입니다. submit 이벤트는 사용자가 입력 또는 "submit"유형의 button를 클릭하면 전달됩니다 (요소는 양식 안에 표시되어야 함). 정확히 우리의 경우입니다.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML forms and JavaScript</title>
</head>
<body>
<h1>What's next?</h1>
<form>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required minlength="5">

    <label for="description">Short description</label>
    <input type="text" id="description" name="description" required minlength="5">

    <label for="task">Task</label>
    <textarea id="task" name="task" required minlength="10"></textarea>

    <button type="submit">Submit</button>
</form>
</body>
<script src="form.js"></script>
</html>


<button type="submit"> 제출 </button>은 양식 바로 안에 있습니다. 일부 개발자는 button 대신 input을 사용합니다.


<!-- I don't like it -->
<input type="submit">


대부분의 경우 특정 CSS 제약 조건에 따라 다릅니다. 모든 정직에서 나는 "input" 접근법을 좋아하지 않습니다. 버튼은 저에게 좋습니다 :


<!-- yes please -->
<button type="submit">Submit</button>


이제 코딩을 해보자. 우리의 목표는 양식에 있는 모든 사용자 입력을 가로채는 것이지만 제출하기 전에 제출 이벤트를 수신해야 합니다. 다시, 우리는 클래스에서 코드를 구성 할 것입니다. 클래스 소비자는 다음과 같이 호출 할 수 있어야 합니다.


const formSelector = document.querySelector("form");

new Form(formSelector);


또한 DOM은 페이지 내의 모든 양식 모음 인 document.forms를 제공합니다. 우리는 지금 단 하나만 필요합니다 :


const formSelector = document.forms[0];

new Form(formSelector);


이제 아이디어가 있습니다. 폼 선택기가 주어지면 폼을 보낼 때 반응하기 위해 이벤트 리스너를 등록 할 수 있습니다. 리스너를 등록하기 위해 생성자를 사용하고 init라는 메소드를 호출 할 수 있습니다. form.html의 동일한 폴더에 form.js라는 새 파일을 만들고 간단한 클래스로 시작하십시오.


"use strict";

class Form {
  constructor(formSelector) {
    this.formSelector = formSelector;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }
}


이벤트 리스너는 this.handleSubmit이며 모든 이벤트 리스너와 마찬가지로 event라는 매개 변수에 액세스 할 수 있습니다. 8 장에서 이벤트는 실제 전달되는 이벤트이며 조치 자체에 대한 유용한 정보가 많이 있음을 알아야 합니다. this.handleSubmit을 구현해 봅시다 :


"use strict";

class Form {
  constructor(formSelector) {
    this.formSelector = formSelector;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }

  handleSubmit(event) {
    console.log(event);
  }
}


우리 class는 주문을 받을 준비가 되었습니다. 우리는 그것을 "인스턴트 화"할 수 있습니다 :


const formSelector = document.forms[0];

new Form(formSelector);


이제 브라우저에서 form.html을 열 수 있어야 합니다. 입력을 채우고 "submit"을 클릭하십시오. 무슨 일이야? URL 표시 줄의 내용에 놀라지 마십시오.


http://localhost:63342/little-javascript/code/ch10/form.html?name=Valentino&description=Trip+to+Spoleto&tak=We%27re+going+to+visit+the+city%21

무슨 일이야? 대부분의 DOM 이벤트에는 "기본 동작"이 있습니다. 제출 이벤트는 특히 양식 데이터를 가상 서버로 보내려고 합니다. Django, Rails 및 친구들과 같은 웹 프레임 워크를 기반으로 하는 응용 프로그램의 일부인 경우 JavaScript없이 양식을 보내는 방법입니다.

모든 입력 값은 해당 이름 속성에 매핑 됩니다. 우리의 경우에는 이름이 필요하지 않지만 대체 이름으로 포함 시키는 것이 좋습니다.

JavaScript로 폼을 제어하려면 기본 동작을 비활성화 해야 합니다. 이벤트 인터페이스의 메소드인 preventDefault를 호출하여 handleSubmit을 수정할 수 있습니다.


"use strict";

class Form {
  constructor(formSelector) {
    this.formSelector = formSelector;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }

  handleSubmit(event) {
    event.preventDefault();
    console.log(event);
  }
}

const formSelector = document.forms[0];

new Form(formSelector);


파일을 저장하고 form.html을 다시 새로 고치십시오. 양식을 작성하고 제출을 클릭하십시오. 콘솔에 이벤트 객체가 인쇄 된 것을 볼 수 있습니다 :


Event {...}
    bubbles: true
    cancelBubble: false
    cancelable: true
    composed: false
    currentTarget: null
    defaultPrevented: true
    eventPhase: 0
    isTrusted: true
    path: (5) [form, body, html, document, Window]
    returnValue: false
    srcElement: form
    target: form
    timeStamp: 8320.840000000317
    type: "submit"

이벤트 객체의 많은 속성 중에 event.target도 있습니다. 이는 HTML 입력이 모든 입력과 함께 저장되어 있음을 나타냅니다. 이것이 사실인지 봅시다.


HTML 양식에서 데이터 추출 


이 장을 마치면 JavaScript 코드가 일부 데이터를 유지하기를 원합니다. 그렇게 하려면 먼저 양식에서 모든 입력 값을 추출해야 합니다.

event.target을 검사하면 elements라는 속성이 있음을 알 수 있습니다. 찾고 계십니까? console.log (event.target.elements)로 인쇄하려고 하면 다음이 표시됩니다.


0: input#name
    1: input#description
    2: textarea#task
    3: button
    length: 4
    description: input#description
    name: input#name
    tak: textarea#task
    task: textarea#task

컬렉션의 모든 양식 입력을 알 수 있습니다. 이제 입력 값 (예 : 사용자 입력)에 액세스하는 두 가지 방법이 있습니다.

  • 배열과 같은 표기법을 통해 : event.target.elements [0] .value
  • id를 통해 : event.target.elements.some_id.value

실제로 모든 양식 요소에 적절한 id 속성을 추가했다면 event.target.elements.some_id와 동일한 요소에 액세스 할 수 있습니다. 여기서 id는 속성에 지정한 문자열입니다. event.target.elements는 무엇보다 먼저 객체이므로 ECMAScript 2015 객체 해체를 사용할 수도 있습니다.


const { name, description, task } = event.target.elements;


이것은 100% 권장되지 않습니다. 예를 들어 TypeScript에서는 오류가 발생하지만 "vanilla JS"를 작성하는 한 괜찮습니다. 값을 손에 넣으면 handleSubmit을 완성 할 수 있으며, 그 동안 saveData라는 다른 메소드를 만들 수 있습니다. 지금은 콘솔에 값을 인쇄합니다.


"use strict";

class Form {
  constructor(formSelector) {
    this.formSelector = formSelector;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }

  handleSubmit(event) {
    event.preventDefault();
    const { name, description, task } = event.target.elements;
    this.saveData({
      name: name.value,
      description: description.value,
      task: task.value
    });
  }

  saveData(payload) {
    console.log(payload);
  }
}

const formSelector = document.forms[0];

new Form(formSelector);


잠깐만 가장 똑똑한 구현은 아닙니다. 필드가 바뀌면 어떻게 되나요? 이제 이름, 설명 및 작업이 있지만 나중에 더 많은 입력을 추가 할 수 있습니다. 해당 필드를 동적으로 추출해야 합니다. 지금 객체를 파괴하고 event.target.elements를 살펴 보겠습니다.


    0: input#name
    1: input#description
    2: textarea#task
    3: button
    length: 4
    description: input#description
    name: input#name
    tak: textarea#task
    task: textarea#task

배열처럼 보입니다. 이름, 설명 및 작업 (버튼 유형 제출 제외)이 포함 된 다른 배열로 변환 할 수 있다면 어떻습니까? map 메소드를 사용하여 event.target.elements를 반복 해 봅시다 (여기서는 관련 코드가 있습니다)


  handleSubmit(event) {
    event.preventDefault();
    const inputList = event.target.elements.map(function(formInput) {
      if (formInput.type !== "submit") {
        return formInput.value;
      }
    });

    /*
      TODO this.saveData( maybe inputList ?)
     */
  }


브라우저에서 샷을 제공하고 콘솔을 보십시오.


Uncaught TypeError: event.target.elements.map is not a function
    at HTMLFormElement.handleSubmit (form.js:15)

나쁜 소식. ".map은 함수가 아닙니다". event.target.elements는 실제로 무엇입니까? 배열처럼 보이지만 다른 짐승입니다 .HTMLFormControlsCollection입니다. 8 장에서 일부 DOM 메소드가 HTMLCollection을 리턴하는 것을 보았을 때 이 내용을 엿볼 수 있었습니다.


// Returns an HTMLCollection
document.chidren;


HTML 컬렉션은 배열과 비슷해 보이지만 요소를 반복하기 위한 map 또는 filter와 같은 메서드가 없습니다. 여전히 괄호 표기법으로 모든 요소에 액세스 할 수 있지만 이제는 좀 더 역동적으로 작업하고 싶습니다. ECMAScript 2015는 거의 모든 소스에서 array를 생성하기 위해 Array 내장 객체에 메소드를 추가했습니다. Array.from입니다. 핸들을 다시 수정 해 봅시다.


  handleSubmit(event) {
    event.preventDefault();

    const arrOfElements = Array.from(event.target.elements);

    const inputList = arrOfElements.map(function(formInput) {
      if (formInput.type !== "submit") {
        return formInput.value;
      }
    });

    console.log(inputList);

    /*
      TODO this.saveData( maybe inputList ?)
     */
  }


여기서 map에 전달되는 event.target.elements에서 배열을 생성합니다. 그러나 여기 또 다른 보석이 있습니다. Array.from은 두 번째 인수로 맵핑 함수를 승인합니다. 한 번에 모든 작업을 수행 할 수 있습니다.


  handleSubmit(event) {
    event.preventDefault();

    const inputList = Array.from(event.target.elements, function(formInput) {
      if (formInput.type !== "submit") {
        return formInput.value;
      }
    });

    console.log(inputList);

    /*
      TODO this.saveData( maybe inputList ?)
     */
  }


form.html을 새로 고치고 양식을 채우고 "submit"을 누르십시오. 콘솔에 다음 배열이 표시되어야 합니다.


["Valentino", "Trip to Spoleto", "We're going to visit the city!", undefined]


마무리 터치로 모든 객체에 관련 양식 입력의 이름 속성이 있는 객체 배열을 생성하고 싶습니다.


  handleSubmit(event) {
    event.preventDefault();

    const inputList = Array.from(event.target.elements, function(formInput) {
      if (formInput.type !== "submit") {
        return {
          name: formInput.name,
          value: formInput.value
        };
      }
    });

    console.log(inputList);

    /*
      TODO this.saveData( maybe inputList ?)
     */
  }


form.html을 다시 새로 고치고 양식을 채우면 다음이 표시됩니다.


[
  {
    "name": "name",
    "value": "Valentino"
  },
  {
    "name": "description",
    "value": "Trip to Spoleto"
  },
  {
    "name": "task",
    "value": "We're going to visit the city!"
  },
  undefined
]


잘 했어. 정의되지 않은 빈 값이 있습니다. 버튼 요소에서 가져옵니다. map의 기본 동작은 "빈"값의 경우 undefined를 반환하는 것입니다. (formInput.type! == "submit") 여부를 확인했기 때문에 버튼 요소는 map에서 반환 되지 않고 undefined로 대체됩니다. 나중에 제거 할 수 있습니다. 이제 localStorage에 주의를 기울이겠습니다.


localStorage를 배우고 클래스 배치 


조만간 사용자를 위해 일부 데이터를 유지해야 합니다. 그렇게 하는 데는 여러 가지 이유가 있습니다. 예를 들어 노트 앱을 생각해 보십시오. 사용자는 HTML 양식에 수행 할 새로운 작업을 삽입하고 나중에 해당 메모를 보러 다시 올 수 있습니다. 다음에 그녀는 페이지를 열면 모든 것을 찾을 수 있습니다.

브라우저에 데이터를 저장하기 위해 어떤 옵션이 있습니까? 데이터를 유지하기 위한 심각한 접근 방식에는 데이터베이스가 포함되지만 여기에는 HTML, JavaScript 및 브라우저가 있습니다.

그러나 모든 것이 사라지는 것은 아닙니다. 최신 브라우저에는 매우 간단한 데이터베이스처럼 작동하는 내장 도구가 있으며 우리의 요구에 완벽하게 부합합니다 : localStorage. localStorage는 JavaScript 객체처럼 작동하며 다음과 같은 많은 메소드가 있습니다.

  • 데이터 저장을 위한 setItem
  • 데이터를 읽기 위한 getItem
  • "데이터베이스"정리를 위해 clear
  • 데이터 제거를 위한 item

잠시 후에 간단한 "앱"에 대해 setItem 및 getItem이 작동하는 것을 볼 수 있지만 먼저 우리가 어디를 떠났는지 살펴 보겠습니다. 여기 있습니다. 메모를 삽입하기 위해 form.html에 HTML 양식이 있습니다.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML forms and JavaScript</title>
</head>
<body>
<h1>What's next?</h1>
<form>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required minlength="5">

    <label for="description">Short description</label>
    <input type="text" id="description" name="description" required minlength="5">

    <label for="task">Task</label>
    <textarea id="task" name="task" required minlength="10"></textarea>

    <button type="submit">Submit</button>
</form>
</body>
<script src="form.js"></script>
</html>


submit 이벤트를 가로 채기 위한 관련 JavaScript 코드도 있습니다.


"use strict";

class Form {
  constructor(formSelector) {
    this.formSelector = formSelector;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }

  handleSubmit(event) {
    event.preventDefault();

    const inputList = Array.from(event.target.elements, function(formInput) {
      if (formInput.type !== "submit") {
        return {
          name: formInput.name,
          value: formInput.value
        };
      }
    });

    console.log(inputList);

    /*
      TODO this.saveData( maybe inputList ?)
     */
  }

  saveData(payload) {
    console.log(payload);
  }
}

const formSelector = document.forms[0];

new Form(formSelector);


이 시점에서 모든 메모를 localStorage에 저장하기 위해 this.saveData를 구현해야 합니다. 그렇게 하는 동안 우리는 가능한 한 일반적인 상태를 유지해야 합니다. 즉, this.saveData를 localStorage에 직접 저장하기 위한 논리로 채우고 싶지 않습니다. 대신 우리는 Form 클래스에 실제 코드를 구현하는 외부 종속성 (다른 클래스)을 제공합니다. 나중에 노트를 localStorage 또는 데이터베이스에 유지할지 여부는 중요하지 않습니다.

요구 사항이 변경됨에 따라 Form마다 다른 "스토리지"를 제공 할 수 있어야 합니다. 이를 위해 먼저 새로운 "storage"인수를 허용하도록 생성자를 조정 해 보겠습니다.


class Form {
  constructor(formSelector, storage) {
    this.formSelector = formSelector;
    this.storage = storage;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }

  handleSubmit(event) {
    event.preventDefault();

    const inputList = Array.from(event.target.elements, function(formInput) {
      if (formInput.type !== "submit") {
        return {
          name: formInput.name,
          value: formInput.value
        };
      }
    });
  }

  saveData(payload) {
    console.log(payload);
  }
}


이제 클래스가 성장함에 따라 생성자의 인수를 검증해야 합니다. HTML 양식 작업을 위해 설계된 클래스이기 때문에 최소한 formSelector가 양식 유형의 HTML 요소인지 확인해야 합니다. 확인 방법은 다음과 같습니다.


  constructor(formSelector, storage) {
    // Validating the arguments
    if (!(formSelector instanceof HTMLFormElement))
      throw Error(`Expected a form element got ${formSelector}`);
    //
    this.formSelector = formSelector;
    this.storage = storage;
    this.init();
  }


양식이 아닌 것을 전달하면 코드가 실패합니다. 또한 사용자 입력을 어딘가에 보내야 하기 때문에 스토리지의 유효성을 검사합니다.


  constructor(formSelector, storage) {
    // Validating the arguments
    if (!(formSelector instanceof HTMLFormElement))
      throw Error(`Expected a form element got ${formSelector}`);
    // Validating the arguments
    if (!storage) throw Error(`Expected a storage, got ${storage}`);
    //
    this.formSelector = formSelector;
    this.storage = storage;
    this.init();
  }


스토리지 구현은 다른 클래스가 될 것입니다. 우리의 경우 일반적인 LocalStorage와 같은 것일 수 있습니다. 여전히 form.js에서 클래스의 최소 구현을 만듭니다.


class LocalStorage {
  save() {
    return "saveStuff";
  }

  get() {
    return "getStuff";
  }
}


좋은. 이제 구조가 완성되면 Form과 LocalStorage를 연결할 수 있습니다.

  • 양식의 saveData는 스토리지 구현을 호출해야 합니다.
  • LocalStorage.save 및 LocalStorage.get은 정적 일 수 있습니다.

여전히 form.js에서 클래스 메소드를 다음과 같이 변경하십시오.


"use strict";

/*
Form implementation
 */
class Form {
  constructor(formSelector, storage) {
    // Validating the arguments
    if (!(formSelector instanceof HTMLFormElement))
      throw Error(`Expected a form element got ${formSelector}`);
    // Validating the arguments
    if (!(storage instanceof Storage))
      throw Error(`Expected a storage, got ${storage}`);
    //
    this.formSelector = formSelector;
    this.storage = storage;
    this.init();
  }

  init() {
    this.formSelector.addEventListener("submit", this.handleSubmit);
  }

  handleSubmit(event) {
    event.preventDefault();

    const inputList = Array.from(event.target.elements, function(formInput) {
      if (formInput.type !== "submit") {
        return {
          name: formInput.name,
          value: formInput.value
        };
      }
    });

    this.saveData(inputList);
  }

  saveData(payload) {
    this.storage.save(payload);
  }
}

/*
Storage implementation
 */
class LocalStorage {
  static save() {
    return "saveStuff";
  }

  static get() {
    return "getStuff";
  }
}

const formSelector = document.forms[0];
const storage = LocalStorage;

new Form(formSelector, storage);


페이로드를 전달하는 동안 Form의 saveData가 어떻게 this.storage.save를 호출하는지 확인하십시오. 그러나 정적 키워드는 저장 및 저장에서 가져 오기 앞에 무엇입니까? 이전 섹션을 기억한다면 HTML 컬렉션에서 배열을 만들기 위해 Array.from을 사용했습니다. const arr = new Array() 다음에 arr.from()을 호출하지 않았습니다. 실제로 Array.from은 new를 호출하지 않고 사용할 수 있습니다. 클래스를 "인스턴트 화"하지 않고. 정적 방법입니다. 정적 메소드는 "인스턴스"가 필요 없는 유틸리티 함수로 유용합니다. 우리는 잘 지내고 있습니다. 다음 섹션에서는 마지막으로 localStorage를 사용하여 데이터를 지속적으로 만듭니다.