使用 javascript 和 CSS 变量的 localStorage 制作切换主题按钮但面临许多问题

Making a switch theme button using localStorage of javascript and CSS variables but facing many issues

我无法相信我无法使用我所知道的所有资源来实现这一点,并且自从过去 5-6 小时以来我一直坚持实现这个小功能,但它就是这样。我需要帮助在用户的 localStorage 上存储一个最初值为 1 的变量。如果用户单击一个按钮,则 localStorage 值更新为 0。如果他再次单击,它再次变为 1。此值用于在灯光之间切换网站的模式和黑暗模式。最初我将 css 变量设置为 1(对于暗模式),并且我想在用户单击按钮时仅使用普通 javascript(无库)更新它。按钮的代码在第二次尝试的代码中。或者也可以在我的 中找到关于同一个项目。

以下是我尝试实现它的一些代码:

代码实现并在没有本地存储且初始变量值为 0 的情况下完美运行:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        :root {
            --numvar: 0;
        }

        html {
            filter: invert(var(--numvar));
        }


        body {
            background: #fff;
        }

        .outer-button {
            display: inline-block;
            height: 28px;
            width: 28px;
            position: relative;
            margin: 0 3px;
        }

        .inner-button {
            display: inline-block;
            position: absolute;
            width: 100%;
            height: 100%;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), inset 0px 0px 1px 2px white;
            border-radius: 20px;
            background: #f5f5f5;
        }

        span {
            display: inline-block;
            vertical-align: middle;
        }

        .status-text {
            color: white;
            text-transform: uppercase;
            font-size: 11px;
            font-family: Futura, sans-serif;
            transition: all 0.2s ease;
        }

        .sliding-switch {
            height: 28px;
            width: 72px;
            position: relative;
        }

        .outer-switch-box {
            overflow: hidden;

            height: 100%;
            width: 100%;
            display: inline-block;
            border-radius: 20px;
            position: relative;
            box-shadow: inset 0 1px 3px 0px #818181, 0px 1px 2px 1px white;
            transition: all 0.3s ease;
            transition-delay: 65ms;
            position: absolute;
            z-index: 1;
        }

        .inner-switch-box {
            position: relative;
            width: 175px;
            transition: all 0.3s ease;
        }

        /* .switch-checkbox:checked+.outer-switch-box .unchecked-text {
            color: transparent;
        }

        .switch-checkbox:not(:checked)+.outer-switch-box .checked-text {
            color: transparent;
        } */

        .switch-checkbox:checked+.outer-switch-box .inner-switch-box {
            left: 20px;
        }

        .switch-checkbox:not(:checked)+.outer-switch-box .inner-switch-box {
            left: -27px;
        }

        .switch-checkbox:checked+.outer-switch-box {
            /* background-image: linear-gradient(#b6d284, #b6d284); */
            background: #492d7b;
            /* background: #b6d284; */
        }

        .switch-checkbox:not(:checked)+.outer-switch-box {
            /* background-image: linear-gradient(#cbcbcb, #dbdbdb); */
            background: #dbdbdb;
        }

        [type="checkbox"] {
            margin: 0;
            padding: 0;
            appearance: none;
            width: 100%;
            height: 100%;
            border: 1px solid black;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            opacity: 0;
        }

        .unchecked-text{
            color: black !important;
            font-weight: 700;
        }

        .btn-heading{
            color: black;
            font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif';
            padding: .4vw 0;
        }
        body{
            float: left;
        }
    </style>
</head>

<body>
    
    <div class="btn-heading">Change Mode</div>
    <div class="sliding-switch">
        <input type="checkbox" id="btn" class="switch-checkbox" />
        <div class="outer-switch-box">
            <div class="inner-switch-box">
                <span class="status-text checked-text">on</span>
                <span class="outer-button">
                    <span class="inner-button"></span>
                </span>
                <span class="status-text unchecked-text" >off</span>
            </div>
        </div>
    </div>
    <script>
        document.getElementById("btn").addEventListener("click", myfunc);

        function myfunc() {
            let root = document.documentElement;
            let elem = getComputedStyle(root).getPropertyValue("--numvar");

            
            console.log(elem);
            if (elem == 0 ) {
                elem = 1;
            }
            else if (elem == 1 ) {
                elem = 0;
            }
            // alert(elem);
            console.log(elem);
            root.style.setProperty("--numvar", elem);
        }
        
    </script>
</body>

</html>

在此之前:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        :root {
            --numvar: 0;
        }

        html {
            filter: invert(var(--numvar));
        }


        body {
            background: #fff;
        }

        .outer-button {
            display: inline-block;
            height: 28px;
            width: 28px;
            position: relative;
            margin: 0 3px;
        }

        .inner-button {
            display: inline-block;
            position: absolute;
            width: 100%;
            height: 100%;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), inset 0px 0px 1px 2px white;
            border-radius: 20px;
            background: #f5f5f5;
        }

        span {
            display: inline-block;
            vertical-align: middle;
        }

        .status-text {
            color: white;
            text-transform: uppercase;
            font-size: 11px;
            font-family: Futura, sans-serif;
            transition: all 0.2s ease;
        }

        .sliding-switch {
            height: 28px;
            width: 72px;
            position: relative;
        }

        .outer-switch-box {
            overflow: hidden;

            height: 100%;
            width: 100%;
            display: inline-block;
            border-radius: 20px;
            position: relative;
            box-shadow: inset 0 1px 3px 0px #818181, 0px 1px 2px 1px white;
            transition: all 0.3s ease;
            transition-delay: 65ms;
            position: absolute;
            z-index: 1;
        }

        .inner-switch-box {
            position: relative;
            width: 175px;
            transition: all 0.3s ease;
        }

        /* .switch-checkbox:checked+.outer-switch-box .unchecked-text {
            color: transparent;
        }

        .switch-checkbox:not(:checked)+.outer-switch-box .checked-text {
            color: transparent;
        } */

        .switch-checkbox:checked+.outer-switch-box .inner-switch-box {
            left: 20px;
        }

        .switch-checkbox:not(:checked)+.outer-switch-box .inner-switch-box {
            left: -27px;
        }

        .switch-checkbox:checked+.outer-switch-box {
            /* background-image: linear-gradient(#b6d284, #b6d284); */
            background: #492d7b;
            /* background: #b6d284; */
        }

        .switch-checkbox:not(:checked)+.outer-switch-box {
            /* background-image: linear-gradient(#cbcbcb, #dbdbdb); */
            background: #dbdbdb;
        }

        [type="checkbox"] {
            margin: 0;
            padding: 0;
            appearance: none;
            width: 100%;
            height: 100%;
            border: 1px solid black;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            opacity: 0;
        }

        .unchecked-text{
            color: black !important;
            font-weight: 700;
        }

        .btn-heading{
            color: black;
            font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif';
            padding: .4vw 0;
        }
        body{
            float: left;
        }
    </style>
</head>

<body>
    
    <div class="btn-heading">Change Mode</div>
    <div class="sliding-switch">
        <input type="checkbox" id="btn" class="switch-checkbox" />
        <div class="outer-switch-box">
            <div class="inner-switch-box">
                <span class="status-text checked-text">on</span>
                <span class="outer-button">
                    <span class="inner-button"></span>
                </span>
                <span class="status-text unchecked-text" >off</span>
            </div>
        </div>
    </div>
    <script>
        document.getElementById("btn").addEventListener("click", myfunc);
        let avar = true; //assume it exists
        if (localStorage.hardtoimplement) {
            avar = true;
        }
        else {
            localStorage.setItem("hardtoimplement", "on")
        }
        console.log(localStorage.getItem("hardtoimplement"));
        var num = 1;
        function myfunc() {
            let root = document.documentElement;
            let elem = getComputedStyle(root).getPropertyValue("--numvar");

            
            if (typeof (Storage) !== "undefined") {
                // console.log(num);
                if (localStorage.getItem("hardtoimplement") == "on") {
                    num = 1;
                }
                else if (localStorage.getItem("hardtoimplement") == "off") {
                    num = 0;
                }
                console.log(num);
            }
            else {
                alert("Sorry, your browser does not support web storage");
            }
            // console.log(num);
            console.log(localStorage.getItem("hardtoimplement"));

            if (localStorage.getItem("hardtoimplement") == "on") {
                localStorage.hardtoimplement = "off";
            }
            else if (localStorage.getItem("hardtoimplement") == "off") {
                localStorage.hardtoimplement = "on";
            }

            console.log(elem);
            if (num == 0 ) {
                num = 1;
            }
            else if (num == 1 ) {
                num = 0;
            }
            // alert(num);
            console.log(num);
            root.style.setProperty("--numvar", num);
        }
        
    </script>
</body>

</html>

第一次尝试:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>

        let avar = true; //assume it exists
        if (localStorage.thisisvar) {
            avar = true;
        }
        else {
            localStorage.setItem("thisisvar", "on")
        }
        console.log(localStorage.getItem("thisisvar"));
        var num = 0;
        function myfunc() {
            if (typeof (Storage) !== "undefined") {
                // console.log(num);
                if (localStorage.getItem("thisisvar") == "on") {
                    num = 1;
                }
                else if (localStorage.getItem("thisisvar") == "off") {
                    num = 0;
                }
                console.log(num);
            }
            else {
                alert("Sorry, your browser does not support web storage");
            }
            // console.log(num);
            console.log(localStorage.getItem("thisisvar"));

            if (localStorage.getItem("thisisvar") == "on") {
                localStorage.thisisvar = "off";
            }
            else if (localStorage.getItem("thisisvar") == "off") {
                localStorage.thisisvar = "on";
            }
        }
        function func2(){
            alert(num);  //initial value is 0 here
        }
    </script>
</head>

<body>
    <button id="result" onclick=" myfunc()">hi</button>
    <button onclick="func2()">b2</button>

</body>

</html>

我尝试在 google、codepen、Whosebug 等很多地方寻找这个功能,我确实找到了这个功能的许多实现,但我无法将它们中的任何一个集成到我的项目中拥有。

需求基本上可以定义为:
CSS 变量最初设置为 1,它应该在单击按钮时更改为 0。
如果用户刷新页面,它应该仍然是 0。

谢谢。

编辑:

答案与项目的整合:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    :root {
            --numvar: 0;
        }

        html {
            filter: invert(var(--numvar));
        }


        body {
            background: #fff;
        }

        .outer-button {
            display: inline-block;
            height: 28px;
            width: 28px;
            position: relative;
            margin: 0 3px;
        }

        .inner-button {
            display: inline-block;
            position: absolute;
            width: 100%;
            height: 100%;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), inset 0px 0px 1px 2px white;
            border-radius: 20px;
            background: #f5f5f5;
        }

        span {
            display: inline-block;
            vertical-align: middle;
        }

        .status-text {
            color: white;
            text-transform: uppercase;
            font-size: 11px;
            font-family: Futura, sans-serif;
            transition: all 0.2s ease;
        }

        .sliding-switch {
            height: 28px;
            width: 72px;
            position: relative;
        }

        .outer-switch-box {
            overflow: hidden;

            height: 100%;
            width: 100%;
            display: inline-block;
            border-radius: 20px;
            position: relative;
            box-shadow: inset 0 1px 3px 0px #818181, 0px 1px 2px 1px white;
            transition: all 0.3s ease;
            transition-delay: 65ms;
            position: absolute;
            z-index: 1;
        }

        .inner-switch-box {
            position: relative;
            width: 175px;
            transition: all 0.3s ease;
        }

        /* .switch-checkbox:checked+.outer-switch-box .unchecked-text {
            color: transparent;
        }

        .switch-checkbox:not(:checked)+.outer-switch-box .checked-text {
            color: transparent;
        } */

        .switch-checkbox:checked+.outer-switch-box .inner-switch-box {
            left: 20px;
        }

        .switch-checkbox:not(:checked)+.outer-switch-box .inner-switch-box {
            left: -27px;
        }

        .switch-checkbox:checked+.outer-switch-box {
            /* background-image: linear-gradient(#b6d284, #b6d284); */
            background: #492d7b;
            /* background: #b6d284; */
        }

        .switch-checkbox:not(:checked)+.outer-switch-box {
            /* background-image: linear-gradient(#cbcbcb, #dbdbdb); */
            background: #dbdbdb;
        }

        [type="checkbox"] {
            margin: 0;
            padding: 0;
            appearance: none;
            width: 100%;
            height: 100%;
            border: 1px solid black;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            opacity: 0;
        }

        .unchecked-text{
            color: black !important;
            font-weight: 700;
        }

        .btn-heading{
            color: black;
            font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif';
            padding: .4vw 0;
        }
        body{
            float: left;
        }

    </style>
</head>

<body>
    <div class="btn-heading">Change Mode</div>
    <div class="sliding-switch">
        <input type="checkbox" id="btn" class="switch-checkbox" onclick="change()" />
        <div class="outer-switch-box">
            <div class="inner-switch-box">
                <span class="status-text checked-text">on</span>
                <span class="outer-button">
                    <span class="inner-button"></span>
                </span>
                <span class="status-text unchecked-text" >off</span>
            </div>
        </div>
    </div>
    <script>
    if (!localStorage.getItem('thisvarisgud4me')) {
        localStorage.setItem("thisvarisgud4me", "1")
    }

    function change() {
        if (localStorage.getItem('thisvarisgud4me') == '1') {
        localStorage.setItem("thisvarisgud4me", '0')
        } else {
        localStorage.setItem("thisvarisgud4me", '1')
        }

        var num = Number(localStorage.getItem('thisvarisgud4me'));
        let root = document.documentElement;
        root.style.setProperty("--numvar", num);
    }
    var num = Number(localStorage.getItem('thisvarisgud4me'));
    let root = document.documentElement;
    root.style.setProperty("--numvar", num);

    </script>
</body>

</html>

这是正确的版本:

我认为你应该多学一点js,因为有很多语法错误。

这里有一些资源:

  1. JavaScript Reference
  2. Learn JS at freecodecamp.org
  3. Learn JS at Codecademy
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
      :root {
        --numvar: 0;
      }

      html {
        filter: invert(var(--numvar));
      }

    </style>
  </head>

  <body>
    <button id="res" onclick="change()">hi</button>
    <script>
      if (!localStorage.getItem('thisvarisgood')) {
         localStorage.setItem("thisvarisgood", "1")
      }

      function change() {
        if (localStorage.getItem('thisvarisgood') == '1') {
          localStorage.setItem("thisvarisgood", '0')
        } else {
          localStorage.setItem("thisvarisgood", '1')
        }

        var num = Number(localStorage.getItem('thisvarisgood'));
        let root = document.documentElement;
        root.style.setProperty("--numvar", num);
      }
      var num = Number(localStorage.getItem('thisvarisgood'));
      let root = document.documentElement;
      root.style.setProperty("--numvar", num);

    </script>
  </body>

</html>

最近尝试的最大问题是您将变量设置为名称“thisvarisgood”并使用“thisvarisgud”访问它。

一旦你更正了它,你需要更正修改 css 的方式。在脚本中这样做是行不通的,因为脚本只运行一次。您需要在被调用以更改本地存储值的函数中以及在页面加载时设置样式。

编辑:如您所见,另一个答案已为您解决。他更正了 localStorage 变量名称并在函数中设置了样式(第 35-37 行)。 “页面加载”样式是第 40-41 行。