React中使用Swiper Element:避免injectStyles影响多轮播
在React中使用Swiper Element实现多轮播样式隔离
我在React组件中使用Swiper Element(WebComponent)为房产机构开发页面,需要配置多个不同样式的轮播。最初通过injectStyles成功设置第一个轮播的分页样式,但第二个轮播的样式无法生效,出现样式继承或不显示的问题。文档显示Swiper样式会注入全局作用域和Shadow DOM,但未明确隔离方法。目前已通过CSS变量修改第二个轮播颜色,希望使用injectStyles实现样式隔离,预期修改单个轮播样式不影响其他轮播。
第一个轮播代码
import React, { useRef, useEffect } from 'react'; import { register } from 'swiper/element/bundle'; import ArticleCardContainer from './ArticleCard'; import { ArrowRight, ArrowLeft } from './Icons'; register(); export const PropertiesNewsCarousel = () => { const { articles } = Homeflow.get('latestPropertyNews'); const isBackgroundWhite = Homeflow.get('isBackgroundWhite').is_background_white; const swiperElRef = useRef(null); // Swiper Element web components - css to overide shadown down styles const navigationStyles = { position: 'static', height: '14px', marginTop: '0 !important', width: 'calc(var(--swiper-navigation-size) / 44 * 27)', zIndex: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', }; useEffect(() => { const swiperContainer = swiperElRef.current; const params = { grabCursor: true, // Default parameters slidesPerView: 1, spaceBetween: 40, // Responsive breakpoints breakpoints: { // small screens 640: { slidesPerView: 1, spaceBetween: 40, }, // medium screens 768: { slidesPerView: 2, spaceBetween: 50, }, // normal laptop screens 1024: { slidesPerView: 3, spaceBetween: 60, }, }, mousewheel: { forceToAxis: true, }, paginationClickable: true, pagination: { el: '.property-news-swiper-paginations', dynamicBullets: true, clickable: true, dynamicMainBullets: 3, }, navigation: { nextEl: '.property-news-swiper-button-next', prevEl: '.property-news-swiper-button-prev', }, injectStyles: [ ` .swiper-1 .property-news-swiper-paginations .swiper-pagination-bullet, .swiper-1 .property-news-swiper-paginations .swiper-pagination-bullet-active-prev, .swiper-1 .property-news-swiper-paginations .swiper-pagination-bullet-active-next, .swiper-1 .property-news-swiper-paginations .swiper-pagination-bullet-active-prev-prev, .swiper-1 .property-news-swiper-paginations .swiper-pagination-bullet-active-next-next { background-color: transparent; } .swiper-1 .property-news-swiper-paginations .swiper-pagination-bullet.swiper-pagination-bullet-active-main { width: 10px; height: 10px; background-color: ${isBackgroundWhite ? '#002844' : '#fff'}; } .swiper-1 .swiper-pagination { bottom: -60px !important; } .swiper-1 .property-news-swiper-paginations { margin: 44px auto 0; transform: translateX(0) !important; } .swiper-1 .property-news-swiper-button-next.swiper-button-disabled, .swiper-1 .property-news-swiper-button-prev.swiper-button-disabled { opacity: .35; cursor: auto; pointer-events: none; } `, ], }; Object.assign(swiperContainer, params); swiperContainer.initialize(); }, []); return ( <section className="swiper-section"> <swiper-container ref={swiperElRef} init="false" id="swiper-container" class="swiper-1" > {articles?.map(article => ( <swiper-slide key={article?.slug}> <ArticleCardContainer imageUrl={article?.image} title={article?.title} articleUrl={`/articles/${article?.slug}`} /> </swiper-slide> ))} </swiper-container> {/* Boolet points pagination */} <div className="property-news-swiper-paginations" /> {/* isBackgroundWhite type String */} {/* Arrows navigation */} <div className={`${isBackgroundWhite ? 'swiper-buttons-box' : 'swiper-buttons-box-primary'}`}> <section className={`${isBackgroundWhite ? 'swiper-buttons-box__section' : 'swiper-buttons-box-primary__section'}`}> <div className="property-news-swiper-button-prev" style={navigationStyles}> <ArrowLeft className={`${isBackgroundWhite ? 'swiper-buttons-box__section-arrow' : 'swiper-buttons-box-primary__section-arrow'}`} /> </div> <div className="property-news-swiper-button-next" style={navigationStyles}> <ArrowRight className={`${isBackgroundWhite ? 'swiper-buttons-box__section-arrow' : 'swiper-buttons-box-primary__section-arrow'}`} /> </div> </section> </div> </section> ); }; export default PropertiesNewsCarousel;
第二个轮播代码
import React, { useRef, useEffect } from 'react'; import { uniqueKey } from 'homeflowjs'; import { register } from 'swiper/element/bundle'; register(); const PromoBoxesCarousel = () => { const promoCardsData = Homeflow.get('promoCards').promo_cards_data; const swiperElRef = useRef(null); // Swiper Element web components - css to overide shadown down styles const paginationStyles = { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '15px', transform: 'translateX(0)', }; useEffect(() => { const swiperContainer = swiperElRef.current; const params = { grabCursor: true, // Default parameters slidesPerView: 1, spaceBetween: 10, // Responsive breakpoints breakpoints: { // small screens 640: { slidesPerView: 1, }, // medium screens 768: { slidesPerView: 3, }, // small laptop screens 1024: { slidesPerView: 4, }, // normal laptop screens 1400: { slidesPerView: 5, }, }, mousewheel: { forceToAxis: true, }, paginationClickable: true, pagination: { el: '.promo-swiper-paginations', dynamicBullets: true, clickable: true, dynamicMainBullets: 3, }, injectStyles: [ ` .swiper-2 .promo-swiper-paginations .swiper-pagination-bullet, .swiper-2 .promo-swiper-paginations .swiper-pagination-bullet-active-prev, .swiper-2 .promo-swiper-paginations .swiper-pagination-bullet-active-next, .swiper-2 .promo-swiper-paginations .swiper-pagination-bullet-active-prev-prev, .swiper-2 .promo-swiper-paginations .swiper-pagination-bullet-active-next-next { background-color: transparent; } .swiper-2 .promo-swiper-paginations span.swiper-pagination-bullet.swiper-pagination-bullet-active.swiper-pagination-bullet-active-main { width: 10px; height: 10px; background-color: #fff; } .swiper-2 .swiper-pagination { bottom: -60px !important; } .swiper-2 .promo-swiper-paginations { margin: 44px auto 0; transform: translateX(0) !important; } `, ], }; Object.assign(swiperContainer, params); swiperContainer.initialize(); }, []); return ( <section className="swiper-section"> <swiper-container ref={swiperElRef} init="false" id="swiper-promo-container" class="swiper-2" > {promoCardsData?.map(card => ( <swiper-slide key={uniqueKey()}> <section className="promo-boxes__item" style={{ backgroundImage: `url(${card.image_url})` }}> <div className="promo-boxes__item-content"> <h2 className="promo-boxes__item-content-title">{ card.title }</h2> <a className="promo-boxes__item-content-mob-btn" href={card.button_url}>{ card.button_title }</a> <div className="promo-boxes__item-content-box"> <p className="promo-boxes__item-content-text">{ card.content }</p> <a className="promo-boxes__item-content-button" href={card.button_url}>{ card.button_title }</a> </div> </div> </section> </swiper-slide> ))} </swiper-container> {/* Boolet points pagination */} <div className="promo-paginations-box"> <div className="promo-swiper-paginations" style={{ ...paginationStyles, '--swiper-pagination-color': 'white' }} /> </div> </section> ); }; export default PromoBoxesCarousel;
核心修复逻辑
- 利用唯一父级选择器隔离样式:每个
swiper-container已配置唯一class(swiper-1、swiper-2),将injectStyles中的所有样式选择器前添加该class,确保样式仅作用于当前轮播组件。 - 消除全局样式冲突:原代码中
.swiper-pagination这类通用选择器会影响所有轮播,添加唯一父级后,样式作用范围被精准限制,不会互相干扰。 - 保留原有样式逻辑:仅修改选择器的作用范围,不改动原有的样式属性和逻辑,确保轮播的视觉效果符合预期。
内容的提问来源于stack exchange,提问作者Marcos Riani
相关产品推荐
相关产品推荐

