简体   繁体   中英

How can I change the background of my li element upon clicking it?

I came across this post: HTML <ul> | Change particular <li> color onclick and other <li> in the same <ul> to default color

And it looks like what I'm looking for; but I was a bit confused as to how I'd do the same in a rails app (that's also using react/redux). In the rails apps that I've worked on so far, I have yet to see any jquery in them so I'm not sure where/how I'd implement the same idea. Any help is appreciated!

I thought about using the onClick event for the li elements, and then making a function to add a class to the clicked element/remove the class from all other li elements, but I'm not sure if this is on the right track.

// this is my component rendering the ul element

import React from 'react';
import TrackIndexItem from './track_index_item';

const TrackDetail = ({ tracks }) => (
  <ul>
    { tracks.map(track => <TrackIndexItem key={ track.id } track={track} />) } 
  </ul>
);

export default TrackDetail;

// this is my component rendering the li elements

import React from 'react';

const TrackIndexItem = ({ track }) => ( 
  <li>
    <div className="track-info">
      <i className="music-note-icon"></i>
      <div className="track-text">
        <p>{track.title}</p> 
        <p>{track.artist} • {track.album}</p>
      </div>
    </div>
  </li>
);

export default TrackIndexItem;

// this is my css for the li elements:

li {
        display: flex;
        flex-direction: row;
        padding: 0 20px;

        .track-info {
          display: flex;
          flex-direction: column;
          position: relative;

          .music-note-icon {
            position: absolute;
            content: image_url('music-note-icon.png');
            width: 10px;
            height: 15px;
            top: 20px;
          }

          .track-text {
            margin-left: 25px;

            p {
              font-family: 'ProximaNova-Regular';
            }

            p:first-of-type {
              font-size: 18px;
              color: $white;
            }

            p:last-of-type {
              font-size: 16px;
              color: $gray;
              margin-top: -15px;
            }
          }
        }
      }

Anonymous Function Example

 $(function() { $("li").click(function(e) { $(".clicked").removeClass(); $(this).addClass("clicked"); }); });
 .clicked { border: 1px solid #CCC; border-radius: 3px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <ol> <li> <div className="track-info"> <i className="music-note-icon"></i> <div className="track-text"> <p>{track.title}</p> <p>{track.artist} • {track.album}</p> </div> </div> </li> <li> <div className="track-info"> <i className="music-note-icon"></i> <div className="track-text"> <p>{track.title}</p> <p>{track.artist} • {track.album}</p> </div> </div> </li> <li> <div className="track-info"> <i className="music-note-icon"></i> <div className="track-text"> <p>{track.title}</p> <p>{track.artist} • {track.album}</p> </div> </div> </li> </ol>

This specifically selects all clicked class items, removes the class, and then adds it to the targeted element.

Here's a pure JS version that I was creating at the same time. It's also available on CodePen: https://codepen.io/edlucas/pen/LYEwjxO

Since you are using React, you could do something a bit different than the code example and add the onClick() directly in your JSX.

const TrackIndexItem = ({ track }) => ( 
  <li onClick={e => highlight(e)}>
    ...
  </li>
);

In that case, you could move the selectors into the highlight function (the only remaining place those variables would be used).

function highlight(e) {
    const list = document.getElementById('trackList');
    const items = list.querySelectorAll('li');

    targetItem = e.target;
    ...
}

These functions could all all be added into your TrackIndexItem component file. removeClass() and addClass() are generic enough to move to a file containing helper/utility functions and imported into your TrackIndexItem file, if you prefer.

Working code snippet:

 // Using pure JS, no jQuery const list = document.getElementById('trackList'); const items = list.querySelectorAll('li'); items.forEach((item) => { item.onclick = (e) => highlight(e); }); function highlight(e) { targetItem = e.target; // Remove the class from all items items.forEach((item) => { removeClass(item, 'active'); }); // Add the class to the "clicked" item addClass(targetItem, 'active'); } function removeClass(item, classVal) { classList = item.className.split(' '); item.className = classList.filter(item => item !== classVal).join(' '); } function addClass(item, classVal) { classList = item.className.split(' '); // Only add the class if it's not in the list if (!classList.includes(classVal)) { classList.push(classVal); } item.className = classList.join(' '); }
 li { width: 100px; padding: 5px; margin-bottom: 5px; } li.bordered { border: 1px solid green; } li.active { background-color: yellow; }
 <html> <body> <ul id="trackList"> <li class="bordered test">Test 1</li> <li class="bordered">Test 2</li> <li class="bordered">Test 3</li> </ul> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM