JUl*_*der 5 ruby-on-rails hotwire-rails turbo-frames ruby-on-rails-7
问题:Turbo 只是将服务器的响应附加到当前页面的末尾。没有像预期那样替换页面。
最近从 Rails 6 升级到 7。我还从 importmap 切换到 esbuild。
我有一个正在向创建方法发布帖子的表单。控制器响应
if @stamp.save
redirect_to stamps_path, notice: "Input saved"
else
Run Code Online (Sandbox Code Playgroud)
发生的奇怪的事情是响应从顶部附加到源代码的底部。因此,在原始源代码的末尾附加了响应中的新头部部分,如下所示
<...> The whole initial html <...>
</body>
<title>Page title</title> <-- The server response gets appended after </body>
<meta .... the whole page gets repeated again
Run Code Online (Sandbox Code Playgroud)
不太确定要在这里向您展示什么,一直在研究所有设置等。我从未见过 Turbo 有这样的响应行为。
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.1.2"
gem "rails", "~> 7.0.2", ">= 7.0.2.4"
gem "sprockets-rails"
gem "puma", "~> 5.6"
gem "haml-rails", "~> 2.0"
gem "sqlite3", "~> 1.4"
gem 'devise', '~> 4.8'
gem 'devise-i18n', '~> 1.10'
gem "turbo-rails"
gem "jsbundling-rails", "~> 1.0"
gem 'sass-rails'
gem "stimulus-rails"
gem 'rubyXL', '~> 3.3'
gem "jbuilder"
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
gem 'kaminari', '~> 1' # pagination gem
gem "bootsnap", require: false
group :development, :test do
gem "debug", platforms: %i[ mri mingw x64_mingw ]
end
group :development do
gem "web-console"
end
group :test do
gem "capybara"
gem "selenium-webdriver"
gem "webdrivers"
end
Run Code Online (Sandbox Code Playgroud)
{
"private": true,
"license": "ISC",
"name": "name",
"version": "0.1.0",
"scripts": {
"release": "npm run build && npm run publish",
"test": "echo \"Error: no test specified\" && exit 1",
"build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.1.2",
"@fortawesome/free-brands-svg-icons": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.1.2",
"@hotwired/stimulus": "^3.1.0",
"@hotwired/turbo-rails": "^7.2.5",
"@popperjs/core": "^2.11.5",
"@rails/activestorage": "^6.0.0",
"bootstrap": "^5.2.0",
"esbuild": "^0.17.7"
}
}
Run Code Online (Sandbox Code Playgroud)
我一直在尝试复制另一个使用 Turbo 的 Rails 应用程序。一直在研究所有设置等。其他页面可以采用redirect_to并按预期替换内容。我正在使用 haml,所以 HTML 结构应该没问题。
Ale*_*lex 10
我只能想到一种可能发生这种情况的方法:你有show.erb模板。只需将其重命名为show.html.erb(或.haml、.slim,没关系)。
默认情况下,表单以TURBO_STREAM形式提交,这是Rails在日志中显示的内容,但这并不是全部。表单提交请求设置 Accept标头:
Accept: text/vnd.turbo-stream.html, text/html, application/xhtml+xml
# ^
# here is where `TURBO_STREAM` comes from
Run Code Online (Sandbox Code Playgroud)
这些是Turbo期望收到的Content-Type响应。当您在控制器操作中使用块时,标头决定了要调用哪个块:respond_toAcceptformat
respond_to do |format|
if @model.save(model_params)
# if you have turbo_stream, it will run first
# format.turbo_stream { render turbo_stream: turbo_stream.replace(model) }
# if you don't have turbo_stream, next format in `Accept` header is html
format.html { redirect_to model_url(@model) }
format.json { render :show, status: :ok, location: @model }
# if nothing matches, you get `ActionController::UnknownFormat` error.
# the one you get when trying to render `format.js`, but Turbo
# doesn't handle js format, so it doesn't send `Accept: text/javascript`
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @model.errors, status: :unprocessable_entity }
end
end
Run Code Online (Sandbox Code Playgroud)
当你使用respond_toblock时,rails会自动设置一些渲染选项,其中之一就是:content_type依次设置Content-Type响应头。因此,如果format.html块运行,它会设置Content-Type: text/html哪个Turbo知道如何通过重定向或替换页面内容来处理。
重要的是我们从Turbo_stream格式转变为html。不用说,html需要渲染 html 响应,并且turbo_stream必须是一个<turbo-stream>标签。
当你不使用respond_toblock 时会发生什么?Rails将尝试渲染与格式匹配的模板。例如,turbo_stream请求将查找show.turbo_stream.erbthen show.html.erbthen show.erb,如下所示:
render :show, formats: [:turbo_stream, :html]
Run Code Online (Sandbox Code Playgroud)
假设它找到show.html.erb,因为存在html扩展,rails会将响应Content-Type设置为text/html,并且一切按预期工作。
但是,如果找到show.erb,则没有任何信息告诉rails它是html格式,我们没有使用respond_to块,因此未显式设置响应Content-Type,剩下的唯一选择是回退到第一个Accept类型,即涡轮流。现在您正在渲染html模板,但响应类型为Turbo_stream,并且没有<turbo-stream>标签。
当turbo看到turbo_stream响应时,它会将其附加到文档中,这就是您所看到的。由于没有<turbo-stream>指令,因此它保持不变。
长话短说,一路上需要设置正确的内容类型。
要么使用respond_to块来设置必要的渲染选项。或者自己设置渲染选项:content_type: "text/html". 或者通过使用和扩展让Rails了解内容类型。html.erbturbo_stream.erb
请注意,当您重定向时,turbo_stream内容类型将保留,因为Turbo在前端处理重定向。如果显示操作中没有html.erb扩展名和块,则会出现内容类型不匹配的情况。respond_to
| 归档时间: |
|
| 查看次数: |
1519 次 |
| 最近记录: |