Bootstrap 5 中的 offcanvas 在动态添加放置时缺少初始过渡

offcanvas in bootstrap 5 missing initial transition when placement is added dynamically

提问人:pmishev 提问时间:10/11/2023 最后编辑:traynorpmishev 更新时间:10/13/2023 访问量:126

问:

我正在尝试使用 JS 触发 Offcanvas 并使放置可配置。 问题是,如果我尝试将类动态设置为 offcanvas 元素,则第一次触发它时,不会发生转换。第二次没事。有什么方法可以欺骗它工作吗?offcanvas-end

var myOffcanvas = document.getElementById('myOffcanvas')

var btnClicked = function (event) {
    myOffcanvas.className += ' offcanvas-end'
    var bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
    bsOffcanvas.show()
}

document.getElementById('myBtn').addEventListener('click', btnClicked)
    
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>

<div class="offcanvas" tabindex="-1" id="myOffcanvas">My offcanvas</div>

<button type="button" id="myBtn">Open</button>

更新:


也许下面的片段通过目的更好地传达了为什么我需要在 JS 中而不是在 HTML 中设置 position 类 - 我想根据触发元素在不同的位置动态打开 offcanvas。

var myOffcanvas = document.getElementById('myOffcanvas')
var bsOffcanvas = null

var openLeftBtnClicked = function(event) {
  myOffcanvas.className = 'offcanvas offcanvas-start'
  if (bsOffcanvas) {
    bsOffcanvas.dispose()
  }
  bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
  bsOffcanvas.show()
}

var openRightBtnClicked = function(event) {
  myOffcanvas.className = 'offcanvas offcanvas-end'
  if (bsOffcanvas) {
    bsOffcanvas.dispose()
  }
  bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
  bsOffcanvas.show()
}

document.getElementById('openLeftBtn').addEventListener('click', openLeftBtnClicked)
document.getElementById('openRightBtn').addEventListener('click', openRightBtnClicked)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div tabindex="-1" id="myOffcanvas"></div>

<button type="button" id="openLeftBtn">Open left</button>
<button type="button" id="openRightBtn">Open right</button>

javascript css css-animations bootstrap-5

评论


答:

0赞 traynor 10/12/2023 #1

将类添加到元素本身,而不是通过 JavaScript,这将启用动画。 实际上是类显示它,而不是 .offcanvas-end.showoffcanvas-end

因此,您不需要在代码中添加类,可以使用 .toggle 方法而不是 来修改它,而且您也不需要在每次单击时创建实例,而是在单击之前执行此操作,然后在单击时切换:.show

试试这个:

const myOffcanvas = new bootstrap.Offcanvas('#myOffcanvas');

var btnClicked = function (event) {

    myOffcanvas.toggle();
}

document.getElementById('myBtn').addEventListener('click', btnClicked);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>

<div class="offcanvas offcanvas-end" tabindex="-1" id="myOffcanvas">My offcanvas</div>

<button type="button" id="myBtn">Open</button>

编辑

由于可能存在某些竞争条件,动态添加类似乎不起作用。

解决方法可能是完全动态地创建元素:

var myOffcanvasContainer = document.getElementById('myOffcanvas')
var myOffcanvas = document.createElement('div');

myOffcanvas.textContent = 'My offcanvas';

var bsOffcanvas = null

var openLeftBtnClicked = function(event) {
  myOffcanvas.className = 'offcanvas offcanvas-start'
  if (bsOffcanvas) {
    bsOffcanvas.dispose()
  }
  
  myOffcanvasContainer.appendChild(myOffcanvas);
  
  bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
  bsOffcanvas.show()
}

var openRightBtnClicked = function(event) {
  myOffcanvas.className = 'offcanvas offcanvas-end'
  if (bsOffcanvas) {
    bsOffcanvas.dispose()
  }
  
  myOffcanvasContainer.appendChild(myOffcanvas);
  
  bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
  bsOffcanvas.show()
}

document.getElementById('openLeftBtn').addEventListener('click', openLeftBtnClicked)
document.getElementById('openRightBtn').addEventListener('click', openRightBtnClicked)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div tabindex="-1" id="myOffcanvas"></div>

<button type="button" id="openLeftBtn">Open left</button>
<button type="button" id="openRightBtn">Open right</button>

编辑2

用它本身替换元素似乎也有效:

myOffcanvas.replaceWith(myOffcanvas);

所以我想浏览器不会在元素已经在 DOM 中并且 JS 和 BS offcanvas 更改了类时不会重绘该元素......

var myOffcanvas = document.getElementById('myOffcanvas')
var bsOffcanvas = null

var openLeftBtnClicked = function(event) {
  myOffcanvas.className = 'offcanvas offcanvas-start'
  
  myOffcanvas.replaceWith(myOffcanvas);
  
  if (bsOffcanvas) {
    bsOffcanvas.dispose()
  }
  bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
  bsOffcanvas.show()
}

var openRightBtnClicked = function(event) {
  myOffcanvas.className = 'offcanvas offcanvas-end'
  
  myOffcanvas.replaceWith(myOffcanvas);
  
  if (bsOffcanvas) {
    bsOffcanvas.dispose()
  }
  bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
  bsOffcanvas.show()
}

document.getElementById('openLeftBtn').addEventListener('click', openLeftBtnClicked)
document.getElementById('openRightBtn').addEventListener('click', openRightBtnClicked)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div tabindex="-1" id="myOffcanvas"></div>

<button type="button" id="openLeftBtn">Open left</button>
<button type="button" id="openRightBtn">Open right</button>

评论

0赞 pmishev 10/12/2023
我在页面上有一个 offcanvas div,我用它来打开带有 ajax 的动态内容。我只希望它的位置取决于触发它显示的元素。这就是为什么我需要在 JS 中而不是在 HTML 中设置位置类。我用另一个代码片段编辑了我的帖子,以更好地表达我的意思。
0赞 traynor 10/12/2023
嗯,那是完全不同的.嗯,看起来过渡动画不起作用。.很可能是某种比赛条件,但无法真正分辨.使用前强制重新粉刷没有区别。不过,如果您动态创建 offcanvas 元素,它似乎有效,所以我会采用这种方式作为解决方法。.show
0赞 traynor 10/12/2023
我添加了解决方法,它似乎正在使用完全动态的元素。我翻遍了源代码,这可能是一些竞争条件,但无法真正分辨..: github.com/twbs/bootstrap/blob/main/js/src/offcanvas.js