问题
I want to set a theme preference cookie for a link function. Here's how the HTML of the element looks like:
<li class="menu-item theme-item">
<a href="javascript:void()" class="btn" aria-pressed="false">Theme Toggle</a>
</li>
And here's how the jQuery function for this element is set:
$('.theme-item .btn').on('click', function(e) {
e.preventDefault();
$(this).attr('aria-pressed', $(this).attr('aria-pressed') === 'false' ? 'true' : 'false');
$('html').attr('data-theme', $('html').attr('data-theme') === 'dark' ? 'light' : 'dark');
if ('false' === $(this).attr('aria-pressed')) {
localStorage.setItem('themeChoice', 'dark');
} else {
localStorage.setItem('themeChoice', 'light');
}
});
var isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
if ('dark' === localStorage.getItem('themeChoice')) {
isDarkMode = true;
} else if ('light' === localStorage.getItem('themeChoice')) {
isDarkMode = false;
}
if (isDarkMode) {
$('html').attr('data-theme', 'dark');
$('.theme-item .btn').attr('aria-pressed', 'true');
} else {
$('html').attr('data-theme', 'light');
}
The problem with this code is, it's not saving toggled value, and the theme preference not loading after page reload. The link clicks changing HTML attribute without any problem, but after page reload preference disappears.
Can anyone fix the problems in this code? Thanks in advance!
回答1:
There is two things here. Storing user preference in localStorage and the user's preference from the browser settings.
But first, your code was very close to be working.
In the onload isDarkMode
comparison, if true
, you had a reversed logic about setting the aria-pressed
value... And if false
, you were not setting any value.
Here are the changes and a working CodePen
if (isDarkMode) {
$("html").attr("data-theme", "dark");
$(".theme-item .btn").attr("aria-pressed", "false"); // Was true here
} else {
$("html").attr("data-theme", "light");
$(".theme-item .btn").attr("aria-pressed", "true"); // This line was missing
}
Now about prefers-color-sheme
var isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
This will return a true/false... And you do not have access to change this value from JS. It is a browser setting and only the user can set it.
So the best you can do is to save change a value to override it if the user clicked on the link to change it.
I guess the aria-pressed
value is to visually show the change. I don't get the use of the data-theme
, so I just discarded that.
So I made a demo and simplified your code. You can see it working in this Codepen, since SO isn't allowing localStorage. It is fully documented with comments and console logs.
To keep it simple here, this is only the necessary code:
var isDarkMode_browserPref = window.matchMedia("(prefers-color-scheme: dark)").matches;
var isDarkMode_storage = localStorage.getItem("isDarkMode")
var isDarkMode = isDarkMode_storage !== null ? (isDarkMode_storage === "true") : isDarkMode_browserPref
$(".theme-item .btn").attr("aria-pressed", isDarkMode);
if(!isDarkMode){
$("body").toggleClass("dark light")
}
// Click handler
$(".theme-item .btn").on("click", function (e) {
e.preventDefault();
isDarkMode = !isDarkMode
$(this).attr("aria-pressed", isDarkMode);
localStorage.setItem("isDarkMode", isDarkMode.toString());
$("body").toggleClass("dark light")
});
来源:https://stackoverflow.com/questions/65759324/jquery-click-function-with-localstorage-not-working