Как обновить сгенерированную JavaScript переменную HTML

Я создал это маленькое средство смены цвета фона просто для развлечения и немного поиграть с JS, но у меня возникла проблема, которую я не знаю, как решить.

Это мой HTML:

<!DOCTYPE html>
<html lang = "en">
<head>
  <meta charset = "UTF-8">
  <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
  <script src = "script.js" defer></script>
  <link rel = "stylesheet" href = "style.css">
  <link href = "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel = "stylesheet" integrity = "sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin = "anonymous">
  <title>Color picker</title>
</head>
<body>

  <div class = "container d-flex align-items-center justify-content-center">
      <div>
        <button id = "main_button" class = "btn btn-danger">Change color</button>
      </div>
  </div>

</body>
</html>

и мой JS:

const button = document.querySelector("#main_button");

function randomColor(){
  let letters = "0123456789ABCDEF";
  let color = "#";
  for(let i = 0; i < 6; i++){
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
};

function changeBackground(){
  document.body.style.backgroundColor = randomColor();
};

function createParagraph(){
  let color = randomColor();
  const div = document.querySelector(".container");
  let par = document.createElement("p");
  par.innerHTML = "Current color is " + color;
  div.appendChild(par);
}

button.addEventListener("click", changeBackground);
button.addEventListener("click", createParagraph);

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

Что именно вы хотите изменить? Вы хотите, чтобы цвет кнопки менялся при нажатии, цвет фона абзаца или текст в абзаце?

Martijn 23.12.2020 23:44

Меняется весь цвет тела. На картинке темно-синий, но он меняется каждый раз, когда вы нажимаете кнопку. Также я почти уверен, что он не показывает мне правильный цветовой код, но это другая проблема: D

Ioan Andrei 23.12.2020 23:50

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

Martijn 23.12.2020 23:52

Нет, фон должен изменить цвет. По функционалу работает корректно. Мне просто нужен абзац, чтобы показать мне правильный HEX-код и обновлять его каждый раз, когда я нажимаю кнопку.

Ioan Andrei 24.12.2020 00:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
98
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

при каждом щелчке вы добавляете еще один тег p - вместо этого создайте тег p на своей html-странице -

<p id = "colorTag"><p>

в вашей функции createParagraph - вместо let par = document.createElement("p"); делай let par = document.getElementById('colorTag') par.innerHTML = "Current color is " + color;

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

function createParagraph(){
  let color = randomColor();
  const div = document.querySelector(".container");
  let par = document.createElement("p");
  par.innerHTML = "Current color is " + color;
  div.appendChild(par);
  changeBackground(color);
}

function changeBackground(newcolor){
  document.body.style.backgroundColor = newcolor;
};

button.addEventListener("click", createParagraph);

Это сделает работу.

Ты каждый раз создаешь новый абзац -

HTML-файл:

<!DOCTYPE html>
<html lang = "en">
  <head>
    <meta charset = "UTF-8" />
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
    <script src = "script.js" defer></script>
    <link rel = "stylesheet" href = "style.css" />
    <link
      href = "https://cdn.jsdelivr.net/npm/[email protected] 
      beta1/dist/css/bootstrap.min.css"
      rel = "stylesheet"
      integrity = "sha384- 
       giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
      crossorigin = "anonymous"
    />
    <title>Color picker</title>
  </head>
  <body>
    <div class = "container d-flex align-items-center justify-content-center">
      <div>
        <button id = "main_button" class = "btn btn-danger">Change color</button>
      </div>
      <p id = "par"></p> <!-- <== You Need this for render every time color -->
    </div>

    <script src = "./script.js"></script>
  </body>
</html>

JS-файл:

const button = document.querySelector("#main_button");

function randomColor() {
  let letters = "0123456789ABCDEF";
  let color = "#";
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function changeBackground() {
  document.body.style.backgroundColor = randomColor();
}

function createParagraph() {
  let color = randomColor();
  const div = document.querySelector(".container");
  let par = document.getElementById("par"); // select paragraph as html file
  par.innerHTML = "Current color is " + color; // and render color to paragraph
}

button.addEventListener("click", changeBackground);
button.addEventListener("click", createParagraph);
Ответ принят как подходящий

На самом деле вы создаете новый <p>-элемент каждый раз, когда вызываете createParagraph().

Вместо этого вы можете заранее создать тег в своем HTML и сохранить его ссылку (которую вы можете получить, запросив его, используя, например, document.querySelector()) в переменной.
Затем вы можете изменить его содержимое, присвоив новое значение его .textContent-свойству.

Вот демонстрация:

var pElement = document.querySelector('#p-id');

document.querySelector('button').addEventListener('click', () => {
  pElement.textContent = "This is its new text, assigned using the '.textContent'-property!";
});
<button>Change &lt;p&gt;'s content!</button>
<p id = "p-id">This is the initial text.</p>

Важно отметить, что на самом деле вы не отображаете текущее значение цвета. Вы вызываете randomColor() дважды: один раз в changeBackground() и один раз в createParagraph(), при этом созданный цвет используется только для назначения <body> нового цвета фона или отображения с помощью <p>-тега.

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

  1. Напишите оба варианта использования в одной функции
  2. Используйте другую переменную для цвета
  3. Используйте значение document.body.style.background (или .backgroundColor, в зависимости от того, что вы использовали). Однако это вернет цвет в формате, подобном rgb(123, 213, 132), что может быть нежелательным.

Я покажу примеры для пунктов 1 и 2.

Пункт 1 может выглядеть так:

const button = document.querySelector('#main_button');
const pElement = document.querySelector('#p_id');

function randomColor(){
  let letters = "0123456789ABCDEF";
  let color = "#";
  for(let i = 0; i < 6; i++){
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function changeAndUpdateColor() {
  let color = randomColor();
  document.body.style.background = color;
  pElement.textContent = 'Current Color is ' + color;
}

button.addEventListener('click', changeAndUpdateColor);
<button id = "main_button">Change Color</button>
<p id = "p_id"></p>

Пункт 2 может выглядеть так:

const button = document.querySelector('#main_button');
const pElement = document.querySelector('#p_id');
var color = '';

function randomColor(){
  let letters = "0123456789ABCDEF";
  let color = "#";
  for(let i = 0; i < 6; i++){
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function changeBackground() {
  document.body.style.background = color;
}

function updateParagraph() {
  pElement.textContent = 'Current Color is ' + color;
}

function getNewColor() {
  color = randomColor();
}

button.addEventListener('click', getNewColor);
button.addEventListener('click', changeBackground);
button.addEventListener('click', updateParagraph);
<button id = "main_button">Change Color</button>
<p id = "p_id"></p>

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

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

const button = document.querySelector('#main_button');
const pElement = document.querySelector('#p_id');

function randomColor(){
  let letters = "0123456789ABCDEF";
  let color = "#";
  for(let i = 0; i < 6; i++){
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

button.addEventListener('click', function() {
  let color = randomColor();
  document.body.style.background = color;
  pElement.textContent = 'Current Color is ' + color;
});
<button id = "main_button">Change Color</button>
<p id = "p_id"></p>

Говоря о глобальном контексте:
Объявление многих переменных и/или функций в глобальном контексте загрязнит глобальное пространство имен и будет доступно пользователю, например. с помощью браузерной консоли. Это проблема для функций, в которых обрабатываются или доступны конфиденциальные данные.

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

(function() {
  // Your code ...
})();

Скобки вокруг самого функционального выражения сгруппируют его, чтобы его можно было выполнить с помощью вызывающих скобок (), подобно тому, как размещение числа внутри скобок позволит нам вызвать для него функцию, например:

(123).toString();

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

(function() {
  var aFunction = function() {
    // ...
  };
  
  aFunction(); // Executed as usual
})();

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

Рефакторинг вашего кода может выглядеть так:

// Is OK to be globally accessible
function randomColor(){
  let letters = "0123456789ABCDEF";
  let color = "#";
  for(let i = 0; i < 6; i++){
    color += letters.charAt(Math.floor(Math.random() * 16));
  }
  return color;
}

// Should be placed inside an IIFE; the global context is still accessible
(function() {
  const button = document.querySelector('#main_button');
  const pElement = document.querySelector('#p_id');

  button.addEventListener('click', function() {
    let color = randomColor();
    document.body.style.background = color;
    pElement.textContent = 'Current Color is ' + color;
  });
})();
<button id = "main_button">Change Color</button>
<p id = "p_id"></p>

Другие вопросы по теме