使用javascript_pack_tag时,页面导航后DOMContentLoaded事件不触发,但在页面重新加载时会触发。

5
我正在使用React和Webpacker的Rails 6 rc1项目。
我目前正在使用`javascript_pack_tag`在我的Rails应用中渲染React组件。为了保持事情简单,我试图不使用像`react-rails`这样的gem。
今天我发现一个奇怪的行为,我的React组件在从链接导航到页面后不会渲染。但是,在重新加载页面后,我的组件被渲染。
`Gemfile`文件:
gem 'rails', '~> 6.0.0.rc1'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
gem 'sass-rails', '~> 5'
gem 'webpacker', '~> 4.0'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
gem 'bootsnap', '>= 1.4.2', require: false
gem 'devise', '~>4.6'

group :development, :test do
  gem 'pry-byebug'
  gem 'rspec-rails', '~> 3.8'
end

group :development do
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

app/views/layouts/application.html.erb:

<html>
  <head>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
....

app/javascript/packs/application.js:

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

import "bootstrap"
import "../stylesheets/application"

app/views/posts/new.html.erb:

<%= content_tag :div,
  id: 'post_data',
  data: @post do %>
<% end %>
<div id="render_here"></div>
<%= javascript_pack_tag 'new_post' %>

app/javascript/packs/new_post.jsx:(尽管该文件中的React代码与问题无关)

import React from 'react';
import ReactDOM from 'react-dom';
import PostForm from '../components/PostForm';

document.addEventListener('DOMContentLoaded', () => {
  const node = document.getElementById('post_data');
  const data = JSON.parse(node.getAttribute('data'));
  const dom = document.querySelector('#render_here');

  ReactDOM.render(
    <PostForm post={data} />,
    dom);
});

使用这种设置后,点击导航到页面的链接后,该组件不会被渲染。在页面重新加载时,该组件将被渲染。
我尝试了许多方法。
在new_post.jsx中,注释掉所有内容,只留下console.log(document.readyState),控制台显示两次complete。页面加载时,它显示loading。
然后我尝试在new_post.jsx中使用jQuery的document.ready:
$(document).ready(function() {
  if (pageInitialized) {
    return;
  }
  pageInitialized = true;

  console.log('render');
...

页面导航后,render再次显示两次。刷新页面后,render只显示一次。

发生了什么?


更新:我发现罪魁祸首是application.js中的require("turbolinks").start()。删除该行代码后,我的组件可以正确加载。 - jules
1个回答

4
我知道你已通过一个解决方法解决了这个问题,但我在寻找相同问题的答案时发现了这个问题,因此为了今后遇到相同问题的人,我想给出一个解释。如此处所述,更好的方法是监听turbolinks事件。
document.addEventListener("turbolinks:load", ()=> {
   alert("loaded");
}

或者如果您需要使用jQuery

$( document ).on("turbolinks:load", ()=> {
    alert("loaded");
}

CoffeeScript变体:

document.addEventListener "turbolinks:load",  ->
    alert "loaded"

1
谢谢,这真的帮了很多忙。@jules提到的解决方法对我也有用,但更好的是理解发生了什么,而不需要禁用turbolinks。 - Nicholas Barry
1
非常感谢!这真的对我很有帮助。我在我的 RoR 应用程序中使用第三方表格构建器,但是表格只在刷新时而不是在导航时被构建。将 window.addEventListener('DOMContentLoaded', event => { 替换为 window.addEventListener("turbolinks:load", event => { 就解决了这个问题。感谢您的贡献! - CWarrington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接