如何让 React.js 和 Bootstrap 4 模态轮播始终在打开时显示第一张图片
How to get React.js and Bootstrap 4 modal carousel to always display the first image on open
我将 React.js 与 Bootstrap 4 modal/carousel 一起使用,我希望当模式为 opened/reopened 时始终显示第一张图片。现在,第一个图像是在第一次打开模态时显示的,但是如果用户滚动到另一个图像然后关闭并重新打开模态,它会显示用户查看的最后一个图像,而不是第一个。我尝试在我的 componentDidMount 中使用 jquery 来强制轮播索引,但它不起作用。
这是我的预期行为的示例场景...
1. 打开模式(显示第一张图片)
2.轮播到第二项
3.关闭模态
4. 打开模式(显示第一张图片)
这是一个Demo
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.scss
.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>
package.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"
}
}
将图像属性存储在对象数组中。
并将它们映射到渲染。
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}
/>
);
})
tl,博士;
您应用中导入的 jQuery 与 window 对象中的不同。因此,您正在使用的 Bootstrap 和 .carousel()
方法未扩展。您可以使用
访问 window 对象中的对象
const $ = window.$
在 componentDidMount
函数中。看看吧here.
或者您可以在 jQuery 之后导入 popper.js 和 Bootstrap 的 js,并从 index.html
.
中删除 <script>
标签
完整(初始)答案:
首先,您现在拥有的东西存在一些问题:
- 你的尝试是用
$('.largeModal')
完成的,但我在你的代码中没有看到任何 className="largeModal"
。您可能想使用 #largeModal
.
- 您的标记中有一些
class
的情况,而 React 似乎不喜欢它们
- 您正在使用 Bootstrap
v4.0.0
。无论主要版本如何,您都应该始终使用该主要版本的最新稳定版本(当前 4 为 v4.4.1
,当前 3 为 v3.4.1
)。
- 您正在加载 jQuery 两次。一次进入
index.html
(来自 cdn),一次进入您的组件(来自包)。虽然可以多次加载 jQuery(以允许不同的模块使用不同版本的 jQuery),但它有一种特殊的技术并且您没有使用它(运行 jQuery 在兼容模式下)。我不会详细说明(至少对于当前的问题)你不应该需要它。
现在,您有两个选择:
a) 加载 jQuery、popper.js 和 bootstrap,但您还必须将脚本放在 index.html
,在它们之后(在 <script>
标签中,而不是在 componentDidMount
中),然后使用类似:
$(document).on('show.bs.modal', '#largeModal', function() {
$('#myCarousel').carousel(0);
})
或...
b) 正确加载 jQuery、popper.js 和 bootstrap 的 js(使用 import
,从它们各自的 npm 包中)组件。
主要问题是,如果你在你的组件中只导入jQuery(除了加载jquery两次,这本身就是一个问题),它不会有扩展的方法通过 bootstrap.js。而你似乎非常需要其中之一 $().carousel()
。
现在,我明白 "b)" 不是理想的实用解决方案,因为您不必导入 jQuery、popper 和 bootstrap 在您的每个组件中,解决方案是通过在 componentDidMount
中使用 const $ = window.$
将外部引用分配给您的组件,如 tl,dr;[=83 中所述=].
您可以看到它正在运行(使用导入)here。
它也适用于 React 外部(选项 "a)")。只需确保只使用一种方法加载 jQuery
、popper.js
和 bootstrap
s js,而不是两种方法。我个人不推荐选项"a)"(阅读说明)。
干杯!
注意:React 和 jQuery 是两种不同的 Web 范式,一起使用它们会使您的生活更加艰难(作为程序员)。选择一个并坚持使用它可能会更快乐(并且更熟练)(大多数开发人员会建议您放弃 jQuery 并使用 React Bootstrap,但选择权完全在您手中)。
我将 React.js 与 Bootstrap 4 modal/carousel 一起使用,我希望当模式为 opened/reopened 时始终显示第一张图片。现在,第一个图像是在第一次打开模态时显示的,但是如果用户滚动到另一个图像然后关闭并重新打开模态,它会显示用户查看的最后一个图像,而不是第一个。我尝试在我的 componentDidMount 中使用 jquery 来强制轮播索引,但它不起作用。
这是我的预期行为的示例场景...
1. 打开模式(显示第一张图片)
2.轮播到第二项
3.关闭模态
4. 打开模式(显示第一张图片)
这是一个Demo
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.scss
.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>
package.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"
}
}
将图像属性存储在对象数组中。 并将它们映射到渲染。
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}
/>
);
})
tl,博士;
您应用中导入的 jQuery 与 window 对象中的不同。因此,您正在使用的 Bootstrap 和 .carousel()
方法未扩展。您可以使用
const $ = window.$
在 componentDidMount
函数中。看看吧here.
或者您可以在 jQuery 之后导入 popper.js 和 Bootstrap 的 js,并从 index.html
.
<script>
标签
完整(初始)答案:
首先,您现在拥有的东西存在一些问题:
- 你的尝试是用
$('.largeModal')
完成的,但我在你的代码中没有看到任何className="largeModal"
。您可能想使用#largeModal
. - 您的标记中有一些
class
的情况,而 React 似乎不喜欢它们 - 您正在使用 Bootstrap
v4.0.0
。无论主要版本如何,您都应该始终使用该主要版本的最新稳定版本(当前 4 为v4.4.1
,当前 3 为v3.4.1
)。 - 您正在加载 jQuery 两次。一次进入
index.html
(来自 cdn),一次进入您的组件(来自包)。虽然可以多次加载 jQuery(以允许不同的模块使用不同版本的 jQuery),但它有一种特殊的技术并且您没有使用它(运行 jQuery 在兼容模式下)。我不会详细说明(至少对于当前的问题)你不应该需要它。
现在,您有两个选择:
a) 加载 jQuery、popper.js 和 bootstrap,但您还必须将脚本放在 index.html
,在它们之后(在 <script>
标签中,而不是在 componentDidMount
中),然后使用类似:
$(document).on('show.bs.modal', '#largeModal', function() {
$('#myCarousel').carousel(0);
})
或...
b) 正确加载 jQuery、popper.js 和 bootstrap 的 js(使用 import
,从它们各自的 npm 包中)组件。
主要问题是,如果你在你的组件中只导入jQuery(除了加载jquery两次,这本身就是一个问题),它不会有扩展的方法通过 bootstrap.js。而你似乎非常需要其中之一 $().carousel()
。
现在,我明白 "b)" 不是理想的实用解决方案,因为您不必导入 jQuery、popper 和 bootstrap 在您的每个组件中,解决方案是通过在 componentDidMount
中使用 const $ = window.$
将外部引用分配给您的组件,如 tl,dr;[=83 中所述=].
您可以看到它正在运行(使用导入)here。
它也适用于 React 外部(选项 "a)")。只需确保只使用一种方法加载 jQuery
、popper.js
和 bootstrap
s js,而不是两种方法。我个人不推荐选项"a)"(阅读说明)。
干杯!
注意:React 和 jQuery 是两种不同的 Web 范式,一起使用它们会使您的生活更加艰难(作为程序员)。选择一个并坚持使用它可能会更快乐(并且更熟练)(大多数开发人员会建议您放弃 jQuery 并使用 React Bootstrap,但选择权完全在您手中)。