1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-eloquent-js-3e-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
18.md 36 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 02:25 369bafd

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

Поскольку он сравнительно новый, поэтому им удобно пользоваться Promise (в интерфейсе браузера это встречается редко).

fetch("example/data.txt").then(response => {
  console.log(response.status);
  // → 200
  console.log(response.headers.get("Content-Type"));
  // → text/plain
});

Вызов fetch возвращает Promise, который анализируется как объект Response, содержащий информацию о сервере, такую как код состояния и заголовки протокола. Заголовки протокола заключены в объект класса Map, который не различает регистр ключей (заголовков), потому что имена заголовков не должны различаться регистром. Это означает, что header.get("Content-Type") и headers.get("content-TYPE") вернут одно и то же значение.

Обратите внимание, что даже если сервер отвечает с ошибочным кодом, Promise, возвращаемый fetch, все равно будет успешно проанализирован. Если есть сетевая ошибка или сервер не найден, он также может быть отклонен.

Первый параметр fetch — это URL запроса. Когда этот URL не начинается с имени протокола (например, http:), он рассматривается как относительный путь, что означает, что он интерпретируется как путь относительно текущего документа. Когда он начинается с косой черты (/), он заменяет текущий путь, то есть часть после имени сервера. В противном случае текущий путь до и включая последнюю косую черту помещается перед относительным URL.

Чтобы получить фактическое содержимое ответа, можно использовать его метод text. Поскольку начальный Promise анализируется сразу после получения заголовков ответа и чтение тела ответа может занять некоторое время, это снова возвращает Promise.

fetch("example/data.txt")
  .then(resp => resp.text())
  .then(text => console.log(text));
// → This is the content of data.txt

Существует аналогичный метод под названием json, который возвращает Promise, анализируемый как значение, полученное при анализе тела как JSON, или отклоняется, если это не действительный JSON.

По умолчанию fetch использует метод GET для отправки запроса и не включает тело запроса. Вы можете настроить различные конфигурации, передав объект с дополнительными параметрами в качестве второго параметра. Например, этот запрос пытается удалить example/data.txt.

fetch("example/data.txt", {method: "DELETE"}).then(resp => {
  console.log(resp.status);
  // → 405
});

Код состояния 405 означает «метод не разрешен», что является способом HTTP-сервера сказать «я не могу этого сделать».

Вы можете включить тело запроса, включив опцию body. Чтобы установить заголовок, существует опция headers. Например, этот запрос содержит Range протокол, указывающий серверу возвращать только часть ответа.

fetch("example/data.txt", {headers: {Range: "bytes=8-19"}})
  .then(resp => resp.text())
  .then(console.log);
// → the content

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

HTTP Sandbox

Отправка HTTP-запросов из веб-скриптов снова вызывает опасения по поводу безопасности. Интересы контролирующего скрипт человека могут отличаться от интересов владельца компьютера, на котором он работает. Более конкретно, если я посещаю themafia.org, я не хочу, чтобы его скрипты могли отправлять запросы от моего имени на mybank.com, приказывая перевести все мои деньги на какой-то случайный счет.

Из-за этого браузеры защищают нас, запрещая скриптам отправлять HTTP-запросы на другие домены, такие как themafia.org и mybank.com.

Это может стать раздражающей проблемой при создании системы, которая должна иметь законный доступ к нескольким доменам. К счастью, серверы могут включать такие заголовки в свои ответы, явно указывая браузеру, что запросы могут поступать из другого домена:

Access-Control-Allow-Origin: *

Using HTTP

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

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

Когда рассматривается удаленный вызов процедуры, HTTP является просто носителем связи, и вы, вероятно, напишете абстрактный уровень, скрывающий детали.

Другой метод заключается в использовании некоторых ресурсов и методов HTTP для создания собственной связи. В отличие от удаленного вызова метода addUser, вам нужно отправить PUT запрос на users/larry, вместо того чтобы кодировать свойства пользователя и передавать их в качестве параметров, вы определяете формат документа JSON (или используете существующий формат) для представления пользователя. Тело PUT-запроса — это документ, используемый для создания нового ресурса. Ресурсы, полученные методом GET, такие как /users/larry, возвращают документ, представляющий ресурс.

Второй метод использует некоторые особенности HTTP, делая его более кратким. Например, поддержка кэширования ресурсов (хранение копии на клиенте для быстрого доступа). Концепции, используемые в HTTP, хорошо разработаны и предоставляют набор полезных принципов для проектирования серверных интерфейсов.

Security and HTTPS

Данные, распространяемые через Интернет, часто проходят долгий и опасный путь. Чтобы добраться до места назначения, ему приходится преодолевать все, от кафе Wi-Fi до сетей, управляемых различными компаниями и странами. На любом участке своего пути он может быть обнаружен или даже изменен.

Если конфиденциальность важна, например, пароль вашей учетной записи электронной почты или важно, чтобы она достигла пункта назначения без изменений, например номер счета, когда вы используете его на веб-сайте банка, простого HTTP недостаточно.

Безопасный протокол HTTP, URL которого начинается с https://, представляет собой способ защиты трафика HTTP от чтения и подделки. Перед обменом данными клиент подтверждает, что сервер является тем, за кого себя выдает, запрашивая у него сертификат, выданный признанным центром сертификации. Затем все данные, передаваемые по соединению, шифруются таким образом, чтобы предотвратить прослушивание и подделку.

Таким образом, когда HTTPS работает правильно, он может помешать кому-либо выдать себя за сайт, с которым вы хотите поговорить, а также кому-либо шпионить за вашим общением.

Это не идеально, поскольку существуют различные аварии, связанные с поддельными или украденными сертификатами и скомпрометированным программным обеспечением, но это безопаснее, чем простой HTTP.

Form Fields

Формы изначально были разработаны для веб-страниц до появления JavaScript, позволяя веб-сайтам отправлять информацию, введенную пользователем, через HTTP-запрос. Этот дизайн предполагает взаимодействие с сервером, всегда осуществляемое путем перехода на новую страницу.

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

Веб-страница формы содержит несколько полей ввода в своем теге <form>. HTML позволяет использовать несколько различных типов полей ввода, от простых переключателей до раскрывающихся меню и полей ввода. Эта книга не будет подробно обсуждать каждый тип поля ввода, но мы начнем с общего обзора.

Многие типы полей используют тег <input>. Атрибут type тега используется для выбора типа поля, вот некоторые общие типы <input>:

  • text: однострочное текстовое поле ввода.

  • password: аналогично text, но скрывает вводимый контент.

  • checkbox: флажок.

  • radio: один из нескольких вариантов в поле.

  • file: позволяет пользователю выбрать файл для загрузки с локального компьютера.

Поля формы не обязательно должны находиться внутри тега <form>, вы можете разместить поля формы где угодно на странице. Но такие поля без формы нельзя отправить (можно отправить только полную форму), и когда требуется ответ JavaScript, мы обычно не хотим отправлять форму обычным способом.

Эти элементы имеют разные интерфейсы JavaScript в зависимости от типа элемента. Выбор элемента <select>

Элемент <select> используется для создания поля, из которого пользователь может выбирать один из заранее заданных вариантов.

<select>
  <option>Pancakes</option>
  <option>Pudding</option>
  <option>Ice cream</option>
</select>

Событие change происходит при изменении содержимого поля формы.

Фокус

В отличие от других элементов HTML-документа, поля форм могут получать фокус клавиатуры. Когда они активируются щелчком мыши или каким-либо другим способом, они становятся активными элементами и принимают ввод с клавиатуры.

Таким образом, вы можете вводить текст только в том случае, если поле имеет фокус. Другие поля по-разному реагируют на события клавиатуры. Например, меню <select> пытается переместиться к опции, содержащей пользовательский ввод текста, и реагирует на стрелки вверх и вниз перемещением своих опций.

Мы можем контролировать фокус с помощью методов JavaScript focus и blur. Первый фокусируется на определённом элементе DOM, а второй размывает его. Значение в document.activeElement будет связано с текущим сфокусированным элементом.

<input type="text">
<script>
  document.querySelector("input").focus();
  console.log(document.activeElement.tagName);
  // → INPUT
  document.querySelector("input").blur();
  console.log(document.activeElement.tagName);
  // → BODY
</script>

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

Браузер также позволяет пользователю перемещаться по фокусу с помощью клавиши TAB. Атрибут tabindex изменяет порядок, в котором элементы получают фокус. В следующем примере фокус перемещается с текстового поля на кнопку OK, а не на ссылку помощи.

<input type="text" tabindex=1> <a href=".">(help)</a>
<button onclick="console.log('ok')" tabindex=2>OK</button>

По умолчанию большинство элементов HTML не могут получить фокус. Однако любой элемент можно сделать фокусируемым, добавив атрибут tabindex. Значение tabindex, равное -1, заставляет клавишу TAB пропускать элемент, даже если он обычно фокусируемый.

Отключённые поля

Все поля формы можно отключить с помощью атрибута disabled. Это атрибут, значение которого можно не указывать — фактически, оно присутствует во всех отключённых элементах.

<button>I'm all right</button>
<button disabled>I'm out</button>

Отключенные поля не могут иметь фокус или изменяться, браузер делает их серыми.

Когда программа обрабатывает события, инициированные клавишами или другими способами управления, и эти события могут потребовать связи с сервером, рекомендуется отключать элементы до завершения действия. Таким образом, если пользователь потеряет терпение и снова нажмёт кнопку, действие не повторится случайно.

Форма как единое целое

Если поле формы содержится в элементе <form>, его элемент DOM будет иметь атрибут form, указывающий на элемент DOM формы. Элемент <form> будет иметь атрибут elements, содержащий коллекцию, подобную данным, которая включает все поля.

Атрибут name поля формы определяет способ идентификации его содержимого при отправке формы. Он также может использоваться как атрибут имени при доступе к form.elements, поэтому elements можно использовать как массив (доступ через индекс) или как карту (доступ по имени).

<form action="example/submit.html">
  Name: <input type="text" name="name"><br>
  Password: <input type="password" name="password"><br>
  <button type="submit">Log in</button>
</form>
<script>
  let form = document.querySelector("form");
  console.log(form.elements[1].type);
  // → password
  console.log(form.elements.password.type);
  // → password
  console.log(form.elements.name.form == form);
  // → true
</script>

Кнопка типа submit отправляет форму при нажатии. Если форма имеет фокус, нажатие клавиши ввода также будет иметь тот же эффект.

Обычно при отправке формы браузер перенаправляет страницу на URL, указанный в атрибуте action формы, используя запрос GET или POST. Однако перед этим происходит событие "submit". Это событие можно обработать с помощью JavaScript, и обработчик может предотвратить поведение по умолчанию, вызвав preventDefault объекта события.

<form action="example/submit.html">
  Value: <input type="text" name="value">
  <button type="submit">Save</button>
</form>
<script>
  let form = document.querySelector("form");
  form.addEventListener("submit", event => {
    console.log("Saving value", form.elements.value.value);
    event.preventDefault();
  });
</script>

У события submit в JavaScript есть несколько применений. Мы можем написать код для проверки правильности ввода пользователя и немедленного отображения ошибок, вместо отправки формы. Или мы можем отключить обычную отправку, как в этом примере, чтобы наша программа обработала ввод, возможно, используя fetch для отправки его на сервер без перезагрузки страницы.

Текстовые поля

Поля, созданные элементами <input> с типом text или password и тегами textarea, имеют одинаковый интерфейс. Их элементы DOM имеют атрибут value, который содержит текущее содержимое в виде строки. Изменение этого атрибута на другое значение изменит содержимое поля.

Текстовые поля selectionStart и selectEnd содержат информацию о позиции курсора и выделенном тексте. Когда ничего не выделено, значения этих атрибутов совпадают, указывая позицию курсора. Например, 0 означает начало текста, 10 означает, что курсор находится после десятого символа. Когда часть поля выбрана, значения этих двух атрибутов различаются, указывая начальную и конечную позиции выделения.

Эти атрибуты также можно изменить, как и обычные значения.

Представьте, что вы пишете статью о Knaseknemwy, но имя написано с ошибкой. Следующий код связывает тег <textarea> и обработчик событий, который вставляет Knaseknemwy при нажатии F2.

<textarea></textarea>
<script>
  let textarea = document.querySelector("textarea");
  textarea.addEventListener("keydown", event => {
    // The key code for F2 happens to be 113
    if (event.keyCode == 113) {
      replaceSelection(textarea, "Khasekhemwy");
      event.preventDefault();
    }
  });
  function replaceSelection(field, word) {
    let from = field.selectionStart, to = field.selectionEnd;
    field.value = field.value.slice(0, from) + word +
                  field.value.slice(to);
    // Put the cursor after the word
    field.selectionStart = from + word.length;
    field.selectionEnd = from + word.length;
  }
</script>

Функция replaceSelection заменяет текущий выделенный текст в поле ввода заданным текстом и перемещает курсор после вставленного текста, позволяя пользователю продолжить ввод. Событие change не вызывается каждый раз при вводе, а срабатывает, когда содержимое изменяется и теряет фокус. Чтобы немедленно реагировать на изменения в текстовом поле, необходимо зарегистрировать обработчик для события input, которое будет срабатывать каждый раз, когда пользователь вводит или изменяет данные. ### Клиентское сохранение данных

Использование простого HTML-кода на JavaScript может стать хорошим способом реализации некоторых небольших приложений. Можно использовать небольшие вспомогательные программы для автоматизации некоторых основных задач. Связывая некоторые поля формы и обработчики событий, вы можете реализовать преобразование градусов Фаренгейта в градусы Цельсия и наоборот. Также можно реализовать различные задачи, такие как генерация пароля на основе мастер-пароля и имени сайта.

Когда приложению необходимо хранить что-то для использования в нескольких диалогах, нельзя использовать привязку к JavaScript, так как эти значения будут потеряны при каждом закрытии страницы. Вы можете создать сервер, подключённый к интернету, и хранить некоторые данные сервисов на нём. В главе 20 будет рассказано, как это сделать, хотя это требует много работы и имеет определённую сложность. Иногда достаточно просто сохранить данные в браузере.

Объект localStorage можно использовать для сохранения данных, которые остаются после перезагрузки страницы. Этот объект позволяет вам сохранять строки под определёнными именами (также строками). Вот конкретный пример:

localStorage.setItem("username", "marijn");
console.log(localStorage.getItem("username")); // → marijn
localStorage.removeItem("username");

Значение в localStorage сохраняется до тех пор, пока оно не будет перезаписано. Его также можно удалить с помощью removeItem или очистить вручную пользователем.

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

Браузер ограничивает размер данных, которые сайт может хранить в localStorage. Это ограничение, а также возможность заполнения жёсткого диска пользователя ненужными данными, не является полезным фактом, предотвращая использование этой функции для хранения слишком большого объёма данных.

Следующий код реализует грубое приложение для заметок. Программа сохраняет заметки пользователя в виде объекта, связывая заголовок и содержимое заметки со строкой. Объект кодируется в формате JSON и сохраняется в localStorage. Пользователь может выбирать заметки из списка выбора, редактировать их в текстовом поле и добавлять новые заметки, нажимая кнопку.

Notes: <select></select> <button>Add</button><br>
<textarea style="width: 100%"></textarea>

<script>
  let list = document.querySelector("select");
  let note = document.querySelector("textarea");

  let state;
  function setState(newState) {
    list.textContent = "";
    for (let name of Object.keys(newState.notes)) {
      let option = document.createElement("option");
      option.textContent = name;
      if (newState.selected == name) option.selected = true;
      list.appendChild(option);
    }
    note.value = newState.notes[newState.selected];

    localStorage.setItem("Notes", JSON.stringify(newState));
    state = newState;
   }
  setState(JSON.parse(localStorage.getItem("Notes")) || {
    notes: {"shopping list": "Carrots\nRaisins"},
    selected: "shopping list"
  });
  }

  list.addEventListener("change", () => {
    setState({notes: state.notes, selected: list.value});
  });
  note.addEventListener("change", () => {
    setState({
      notes: Object.assign({}, state.notes,
                           {[state.selected]: note.value}),
      selected: state.selected
    });
  });

  document.querySelector("button")
    .addEventListener("click", () => {
      let name = prompt("Note name");
      if (name) setState({
        notes: Object.assign({}, state.notes, {[name]: ""}),
        selected: name
      });
    });
</script>

Скрипт получает начальное состояние из localStorage и, если значение отсутствует, создаёт пример состояния с одним списком покупок. Чтение несуществующего поля из localStorage возвращает null.

Метод setState обеспечивает отображение текущего состояния в DOM и сохранение нового состояния в localStorage. Обработчики событий вызывают эту функцию для перехода в новое состояние.

В этом примере используется Object.assign для создания нового объекта, который является клоном старого state.notes, но добавляет или заменяет свойство. Object.assign принимает первый параметр и добавляет все свойства остальных параметров. Таким образом, предоставление пустого объекта заполняет новый объект. Квадратные скобки в третьем параметре используются для создания имени свойства на основе динамического значения.

Существует ещё один объект, похожий на localStorage, называемый sessionStorage. Разница между этими двумя объектами заключается в том, что содержимое sessionStorage теряется при завершении каждого сеанса, а для большинства браузеров сеанс завершается при закрытии браузера.

Резюме этой главы

В этой главе мы обсудили принцип работы протокола HTTP. Клиент отправляет запрос, содержащий метод (обычно GET) и путь, идентифицирующий ресурс. Затем сервер решает, как обработать запрос, и отвечает состоянием и телом ответа. Запросы и ответы могут содержать дополнительную информацию в виде заголовков протокола.

С помощью интерфейса fetch в JavaScript можно создавать HTTP-запросы. Пример создания запроса:

fetch("/18_http.html").then(r => r.text()).then(text => {
  console.log(`The page starts with ${text.slice(0, 15)}`);
});

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

HTML может представлять различные типы полей форм, такие как текстовые поля, поля выбора, флажки и поля выбора файлов.

Эти поля можно контролировать и читать с помощью JavaScript. Изменение содержимого вызывает событие изменения, ввод текста вызывает событие ввода, а получение фокуса клавиатуры вызывает события клавиатуры. Например, атрибуты «value» (для текстовых полей и полей выбора) или «checked» (для флажков и кнопок) используются для чтения или установки содержимого поля.

При отправке формы происходит событие отправки, которое можно предотвратить с помощью вызова preventDefault в обработчике JavaScript. Элементы поля формы не обязательно должны быть заключены в тег

.

Когда пользователь выбирает файл на локальном компьютере в поле выбора файла, содержимое файла можно получить с помощью интерфейса FileReader в JavaScript.

Объекты localStorage и sessionStorage можно использовать для хранения информации, которая остаётся после перезагрузки страницы. Первый сохраняет данные навсегда (пока пользователь не решит их очистить), а второй сохраняет данные до закрытия браузера.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-eloquent-js-3e-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-eloquent-js-3e-zh.git
oschina-mirror
wizardforcel-eloquent-js-3e-zh
wizardforcel-eloquent-js-3e-zh
master