仅通过单击特定元素的按钮更改样式表

change stylesheet by button click for specific element only

所以,这个问题是基于我目前正在做的一项作业。我得到了一个 HTML 文档和两个样式表。 HTML 文档真的很简单:

<html>
<head>
   <title>DOM-scripting: change style</title>
   <link rel="stylesheet" href="style/style1.css" id="stylesheet"/>
</head>
<body>
    <nav class="chooseStyle">
        <input type="button" id="style1Button" value="Style 1"/>
        <input type="button" id="style2Button" value="Style 2"/>
    </nav>
    <article>
        <h1>Style change using DOM-scripting</h1>
        <p> sample text </p>
        <p> sample text </p>
        <p> sample text </p>
    </article>
    <nav class="links">
        <ul>
            <li><a href="link">school name</a></li>
            <li><a href="link">school name</a></li>
       </nav>

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

style1.css 由以下内容组成:

body {
    background-color: #676632;
}

input[type="button"] {
    color: #F5F265;
    background-color: #9B9302;
}

article {
    margin-left: 150px;
    margin-right: 150px;
    text-indent: 20px;
    color: #C9C892;
}

h1 {
    color: #EEF1BA;
    text-align: center;
}

a {
    color: #A1FA56;
    text-decoration: none;
    font-weight: bold;
}

ul {
    padding: 0;
}

li {
    list-style-type: none;
}

Style2.css 由以下内容组成:

body {
    color: #EEEEAA;
}

input[type="button"] {
    color: #9B9302;
    background-color: #F5F265;
}

article {
    margin-left: auto;
    margin-right: auto;
    text-align: justify;

    color: #A3A163;
}

h1 {
    color: #AAAA66;
    text-align: left;
}

a {
    color: #CDCF9B;
}

ul {
    padding: 0;
}

li {
    list-style-type: none;
}

练习的第一部分指出我需要创建一个 javascript 文件,该文件允许网页的样式表根据单击的按钮进行更改。第一个按钮引用第一个样式表,第二个按钮引用第二个样式表。我发现这很容易,一切正常。

但是,练习的第二部分说明如下:"Now edit the javascript file so that only the style of the article is changed when the buttons are clicked. DO NOT edit the CSS file." 这意味着样式表的 href 仍应更改,就像第一部分一样,但现在它可能只会影响样式表的样式文章元素而不是整个页面的样式。

过去一个小时我一直在搜索相关问题,但似乎没有真正提供解决方案。我读过一些问题,指出在不更改样式表本身的任何内容的情况下,不可能仅将样式表应用于特定元素。请记住,我才上大学一年级,才刚刚开始学习 javascript,这意味着解决方案应该不难找到。我猜?

到目前为止我写的Javascript代码:

'use strict';

const handleLoad = () => {
    let style1 = document.getElementById('style1Button');
    let style2 = document.getElementById('style2Button');
    style1.addEventListener('click', handleClick);
    style2.addEventListener('click', handleClick);
};

const handleClick = (event) => {
    if(event.target.value === "Style 1") {
        document.getElementById("stylesheet").href = "style/style1.css";
        // should only change article style 
        // currently still referring to the whole document
    } else {
        document.getElementById("stylesheet").href = "style/style2.css";
        // should also only change article style
        // also still referring to the whole document
    }
};

window.addEventListener('load', handleLoad);

有什么方法可以阻止除 article 元素之外的所有元素的 CSS 规则?或者更改不应受影响的元素的 类 或 ID?

提前致谢:)


终于解决了这个问题。 (代码可能没有它应该的那样紧凑和正确,但它可以工作所以我很高兴 :D):

'use strict';

const handleLoad = () => {
    let style1 = document.getElementById('style1Button');
    let style2 = document.getElementById('style2Button');
    style1.addEventListener('click', handleClick);
    style2.addEventListener('click', handleClick);
    makeShadow();
};

const handleClick = (event) => {
    let article = document.querySelector('article');
    let shadow = article.shadowRoot;

    let style = event.target.value === "Style 1" ? "style/style2.css" : "style/style1.css";

    for(let node of shadow.childNodes) {
        if(node.hasAttribute('href')){
            node.href = style;
        }
    }
};

const makeShadow = () => {
    let article = document.querySelector('article');
    let articleClone = makeClone(article);

    let shadow = article.attachShadow({mode:'open'});

    let link = document.createElement('link');
    link.rel = "stylesheet";
    link.href = 'style/style1.css';

    shadow.appendChild(articleClone);
    shadow.prepend(link);
};

const makeClone = (article) => {
    let clone = article.cloneNode();
    clone.innerHTML = article.innerHTML;
    return clone;
};

window.addEventListener('load', handleLoad);

非常非常简单的例子。您说它是 Javascript 中的新内容。这就是为什么我要给你一个很容易理解的例子。事实上,一个更合乎逻辑的解决方案可以通过循环按钮来产生,弄清楚它们在哪个按钮上,根据它定义需要更改的元素,但这是现阶段最简单的示例。你必须自己调查和学习。祝你好运!

const style1Button = document.getElementById("style1Button");
style1Button.addEventListener("click", styleArticle);

function styleArticle(e) {
  let article = document.getElementById("article"); // full article
  // with querySelector, you can access the elements in the main element in this way.
  article.querySelector(".article-title").style.color = "red";
  article.querySelector(".text1").style.color = "blue";
  article.querySelector(".text2").style.color = "orange";
  article.querySelector(".text3").style.color = "gray";
}
<nav class="chooseStyle">
  <input type="button" id="style1Button" value="Style 1" />
  <input type="button" id="style2Button" value="Style 2" />
</nav>
<article id="article">. 
  <!-- you can add a class or id to each of them to get specific with javascript. -->

  <h1 class="article-title">Style change using DOM-scripting</h1> 
  <p class="text1"> sample text </p>
  <p class="text2"> sample text </p>
  <p class="text3"> sample text </p>
</article>
<nav class="links">
  <ul>
    <li><a href="link">school name</a></li>
    <li><a href="link">school name</a></li>
</nav>

更新答案:

我想你只是写错了字母。

 const handleLoad = () => {
      let style1 = document.getElementById('style1Button');
      let style2 = document.getElementById('style2Button');
      style1.addEventListener('click', handleClick);
      style2.addEventListener('click', handleClick);
    }

    //handleclick to --- handleClick
    const handleClick = (event) => { 
      if (event.target.value === "Style 1") {
        document.getElementById("styleSheet").href = "style/style.css";
        // should only change article style 
        // currently still referring to the whole document
      } else {
        document.getElementById("styleSheet").href = "style/style2.css";
        // should also only change article style
        // also still referring to the whole document
      }
    };

    window.addEventListener('load', handleLoad);

您可以 select 具有 javascript 的元素并在不更改样式表的情况下设置它们的样式。

有不同的方法可以做到这一点,但如果你不能改变这个 HTML 文件,这应该可以改变文章元素内的文本颜色:

document.querySelector('article').style.color = 'red';

除了颜色之外,您还可以设置其他样式,还可以使用 querySelector select 文章中的 H1 或段落元素,但我会让您弄明白 ;)

在这种情况下我们可以利用shadowRoot作为样式的封装。

这个想法就像在只有article元素的页面中添加一个包含大量样式的css文件,显然其他样式不会有任何效果。

我们可以使用 shadowRoot 将文章放入它自己的小世界并添加一个包含更多样式的文件。

代码有大量注释。如果您有任何问题,请发表评论:)

首先加载我们准备影子元素:

const handleLoad = () => {

    // Old Code for button handlers still needed
    let style1 = document.getElementById('style1Button');
    let style2 = document.getElementById('style2Button');
    style1.addEventListener('click', handleClick);
    style2.addEventListener('click', handleClick);


    // New Code Below

    // Select the article from the page 
    const article = document.querySelector('article');
    // Create an empty div Element to work as a bucket
    const placeholderElement = document.createElement('div');
    // set it's id attribute to select it later
    placeholderElement.setAttribute('id', 'placeholderElementShadowRot')
    // replace the article with our div in the document
    // the article element is not completly lose at this point
    // we still have in the variable article
    article.replaceWith(placeholderElement);
    // attache a shadow to the div element
    const shadow = placeholderElement.attachShadow({ mode: 'open' });
    // sets the shadow's innerHTML equal to article outerHTML
    shadow.innerHTML = article.outerHTML;


    // create a link
    const link = document.createElement('link');
    // set it's href attribute to the first style file
    link.setAttribute("href", 'style1.css');
    // set the rel attribute
    link.setAttribute("rel", "stylesheet");
    // add the link to the shadow
    shadow.appendChild(link)
};

点击按钮

const handleClick = (event) => {
    // Select our div we created before using the id
    const placeholderElement = document.querySelector('#placeholderElementShadowRot');
    // since we already attached a shadow 
    // we can use it through the property .shadowRoot
    const shadow = placeholderElement.shadowRoot;

    // based on which button we add the relevant style file
    if (event.target.value === "Style 1") {
        shadow.querySelector('link').setAttribute("href", "style1.css")
    } else {
        shadow.querySelector('link').setAttribute("href", "style2.css")
    }
};

注意:您的 JS 中有错字,处理程序称为 handleclick 小写 click 但您添加的是大写 Click handleClickaddEventListener