Как получить React. js и Bootstrap 4 модальной карусели, чтобы всегда отображать первое изображение при открытии - PullRequest
0 голосов
/ 20 января 2020

Я использую React. js с модальной / каруселью Bootstrap 4 и хочу, чтобы первое изображение всегда отображалось при открытии / открытии модального окна. Прямо сейчас первое изображение показывается при первом открытии модального окна, но когда пользователь прокручивает другое изображение, затем закрывает и снова открывает модальное, оно показывает последнее изображение, просмотренное пользователем, и не всегда первое. Я попытался использовать jquery в моем componentDidMount для принудительного индекса карусели, но он не работает.

Вот пример сценария моего предполагаемого поведения ...
1. Откройте модал (показано первое изображение)
2. Карусель для 2-го предмета
3. Закрыть модал
4. Открыть модал (показано первое изображение)

Вот Демо

index. js

import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.scss';
import $ from 'jquery';

class App extends Component {
    constructor() {
        super();
    }

  componentDidMount() {
    // My attempts to always have carousel begin at index 0 on show event
    // $('.largeModal').on('show.bs.modal', function() {
        // console.log('show.bs.modal event');
        // $('.carousel').carousel(0);
    // });

    // $('.largeModal').on('show.bs.modal', function() {
        // console.log('show.bs.modal event');
        // $('#myCarousel').carousel(0);
    // });
  }

    render() {
        return (
            <div className='container'>
                <h3 className='text-center mb-4'>React with Bootstrap 4 Modal & Carousel</h3>

                <div class='row mb-4'>
                    <div class='col text-center'>
                        <button
                            type='button'
                            className='btn btn-primary '
                            data-toggle='modal'
                            data-target='#largeModal'
                        >
                            Open Modal
                        </button>
                    </div>
                </div>

                {/* Modal*/}
                <div
                    className='modal fade'
                    id='largeModal'
                    tabIndex='-1'
                    role='dialog'
                    aria-labelledby='basicModal'
                    aria-hidden='true'
                >
                    <div className='modal-dialog modal-lg'>
                        <div className='modal-content'>
                            <div className='modal-body'>
                                {/* Carousel */}
                                <div
                                    id='myCarousel'
                                    className='carousel slide'
                                    data-ride='carousel'
                                >
                                    <ol className='carousel-indicators'>
                                        <li
                                            data-target='#myCarousel'
                                            data-slide-to='0'
                                            className='active'
                                        ></li>
                                        <li
                                            data-target='#myCarousel'
                                            data-slide-to='1'
                                        ></li>
                                        <li
                                            data-target='#myCarousel'
                                            data-slide-to='2'
                                        ></li>
                                    </ol>
                                    <div className='carousel-inner'>
                                        <div className='carousel-item active'>
                                            <img
                                                className='img-size'
                                                src='https://images.unsplash.com/photo-1485470733090-0aae1788d5af?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1391&q=80'
                                                alt='First slide'
                                            />
                                        </div>
                                        <div className='carousel-item'>
                                            <img
                                                className='img-size'
                                                src='https://images.unsplash.com/photo-1491555103944-7c647fd857e6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80'
                                                alt='Second slide'
                                            />
                                        </div>
                                        <div className='carousel-item'>
                                            <img
                                                className='img-size'
                                                src='https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80'
                                                alt='Third slide'
                                            />
                                        </div>
                                    </div>
                                    <a
                                        className='carousel-control-prev'
                                        href='#myCarousel'
                                        role='button'
                                        data-slide='prev'
                                    >
                                        <span
                                            className='carousel-control-prev-icon'
                                            aria-hidden='true'
                                        >
                                            {' '}
                                        </span>
                                        <span className='sr-only'>Previous</span>
                                    </a>
                                    <a
                                        className='carousel-control-next'
                                        href='#myCarousel'
                                        role='button'
                                        data-slide='next'
                                    >
                                        <span
                                            className='carousel-control-next-icon'
                                            aria-hidden='true'
                                        ></span>
                                        <span className='sr-only'>Next</span>
                                    </a>
                                </div>
                            </div>
                            <div className='modal-footer'>
                                <button
                                    type='button'
                                    className='btn btn-default'
                                    data-dismiss='modal'
                                >
                                    Close
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

render(<App />, document.getElementById('root'));

style.s css

.img-size{
    height: 450px;
    width: 700px;
    background-size: cover;
    overflow: hidden;
}
.modal-content {
   width: 700px;
  border:none;
}
.modal-body {
   padding: 0;
}

.carousel-control-prev-icon {
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23009be1' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
    width: 30px;
    height: 48px;
}
.carousel-control-next-icon {
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23009be1' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E");
    width: 30px;
    height: 48px;
}

index. html

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

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>React Modal with Carousel</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</head>

<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
</body>

</html>

упаковка. json

{
  "name": "react",
  "version": "0.0.0",
  "private": true,
  "dependencies": {
    "bootstrap": "^4.4.1",
    "jquery": "1.9.1 - 3",
    "node-sass": "^4.13.1",
    "popper.js": "^1.16.0",
    "react": "^16.9.0",
    "react-dom": "^16.9.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {
    "react-scripts": "latest"
  }
}

Ответы [ 2 ]

0 голосов
/ 21 января 2020

tl, dr;

Импортированный jQuery в вашем приложении отличается от импортированного в объекте окна. Поэтому не распространяется на Bootstrap с помощью метода .carousel(), который вы используете. Вы можете получить доступ к объекту в окне, используя функцию

const $ = window.$

внутри componentDidMount. Посмотрите здесь .
Или вы можете импортировать поппер. js и Bootstrap js после jQuery и удалить теги <script> из index.html.


Полный (начальный) ответ:

Прежде всего, есть несколько проблем с тем, что у вас есть сейчас:

  • ваши попытки были сделаны с помощью $('.largeModal') но я не вижу className="largeModal" в вашем коде. Вы, вероятно, хотели использовать #largeModal.
  • , у вас есть несколько случаев class в вашей разметке, и React, похоже, не нравится их
  • вы используете Bootstrap v4.0.0. Независимо от основной версии, вы всегда должны go с последней стабильной версией этого основного (текущий 4 будет v4.4.1, а текущий 3 будет v3.4.1).
  • вы загружаете jQuery дважды. Один раз в index.html (из cdn) и один раз в вашем компоненте (из пакетов). Хотя загрузка jQuery возможна более одного раза (для того, чтобы разные модули могли использовать разные версии jQuery), есть специальная методика, и вы ее не используете (jQuery работает в режиме совместимости). Я не буду go вдаваться в детали, поскольку (по крайней мере, для текущего вопроса) он вам не понадобится.

Теперь у вас есть два варианта:

a) load jQuery, popper. js и bootstrap, как вы сделали, но затем вы должны также поместить свой скрипт внутрь index.html, после них (в теге <script> вместо *) 1044 *) и используйте что-то вроде:

$(document).on('show.bs.modal', '#largeModal', function() {
  $('#myCarousel').carousel(0);
})

или ...
b) load jQuery, popper. js и bootstrap s js правильно (с import, из соответствующих пакетов npm) внутри компонента.

Основная проблема заключается в том, что если вы импортируете только jQuery в свой компонент (помимо загрузки jquery дважды, что само по себе является проблемой), у него не будет расширенных методов на bootstrap. js. И вам, кажется, очень нужен один из них $().carousel().

Теперь я понимаю "b)" - не идеальное практическое решение, так как вам не нужно импортировать jQuery, popper и bootstrap в каждый из ваших компонентов в отдельности, решение для этого состоит в том, чтобы назначить внешнюю ссылку на ваш компонент, используя const $ = window.$ внутри componentDidMount, как указано в tl, dr; .

. Вы можете видеть, как это работает (с import) здесь .
Он также работает извне React (опция "a)" ). Просто убедитесь, что вы загружаете jQuery, popper.js и bootstrap s js, используя только один метод, а не оба. Лично я не рекомендую вариант "a)" (см. Примечание).

Приветствия!


Примечание: React и jQuery - две разные веб-парадигмы и их совместное использование сделает вашу жизнь намного сложнее (как программисту). Вы, вероятно, будете счастливее (и опытнее), выбрав один и придерживаясь его (большинство разработчиков посоветуют вам отказаться от jQuery и использовать React Bootstrap, но выбор остается за вами).

0 голосов
/ 20 января 2020

Хранить свойства изображения в массиве объектов, как. и сопоставьте их для рендеринга.

let arr = [
{
className:'img-size',
src:'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80',
alt:'Third slide'
 },
and more like this.
]

//Then map the images in carousel ann it would always show first image first, because it would always render images at runtime.

arr.map(img => {
return(
           <img
               className={img.className}
               src={img.src}
               alt={img.alt}
          />
);
})

...