我正在更新使用 jquery 和 $ajax() 的旧 Rails 应用程序,更新后它仍然有效。我想将 ajax 调用更改为带有 .js.erb 和 params 的 fetch(),一切似乎都很好,但 html 不会被 workbar_work 部分替换。有什么建议吗?
在控制器中:
def switch_state
permitted_params = params.permit(:partial)
@partial = permitted_params[:partial].to_s
@exercise = current_exercise # defined somewhere else
respond_to do |format|
format.js
end
end
在 switch_state.js.erb 中
$('#workbar_switch').html("<%= j render(partial: @partial, :locals => {exercise: @exercise@}) %>");
获取调用
function switchState(partial, exercise){
const params = new URLSearchParams();
params.append('partial', partial);
fetch("/work/switch_state", {
method: 'POST',
headers: {
'Accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript',
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.text()
})
.then(responseText => {
console.log("received js", responseText)
})
.catch(error => {
console.log('Update failed', error)
console.log('error', error.message)
})
.finally(() => {
})
}
rails 服务器日志-看起来不错:
Started POST "/work/switch_state" for ::1 at 2024-12-07 11:19:49 +0100
Processing by WorkController#switch_state as JS
Parameters: {"partial"=>"workbar_work"}
Exercise Load (0.3ms) SELECT "exercises".* FROM "exercises" WHERE "exercises"."unit" = $1 LIMIT $2 [["unit", "ct100_1_ma3"], ["LIMIT", 1]]
↳ app/models/exercise.rb:81:in `find_exercise'
CACHE Exercise Load (0.0ms) SELECT "exercises".* FROM "exercises" WHERE "exercises"."unit" = $1 LIMIT $2 [["unit", "ct100_1_ma3"], ["LIMIT", 1]]
↳ app/models/exercise.rb:81:in `find_exercise'
Rendering work/switch_state.js.erb
Rendered work/_workbar_work.html.erb (Duration: 0.6ms | Allocations: 351)
CACHE Exercise Load (0.0ms) SELECT "exercises".* FROM "exercises" WHERE "exercises"."unit" = $1 LIMIT $2 [["unit", "ct100_1_ma3"], ["LIMIT", 1]]
↳ app/models/exercise.rb:81:in `find_exercise'
Rendered work/switch_state.js.erb (Duration: 3.4ms | Allocations: 2535)
Completed 200 OK in 17ms (Views: 5.4ms | ActiveRecord: 2.1ms | Allocations: 9998)
浏览器控制台:
[Log] response – Response {type: "basic", url: "http://localhost:3000/work/switch_state", redirected: false, …} (ctrl-dc34a42ad73de8380cf755f815535ed1b8bfc04007d2b4f4fad4a1f130e93d45.js, line 183)
[Log] received js – "$('#workbar_switch').html(\"<ul>\\n\t\\n\t<a title=\\\"Klicke hier für eine leichte Übung\\\" id=\\\"bug_click\\\" href=\\\"\\\">\\n\t<l…" (ctrl-dc34a42ad73de8380cf755f815535ed1b8bfc04007d2b4f4fad4a1f130e93d45.js, line 190)
"$('#workbar_switch').html(\"<ul>\\n \\n <a title=\\\"Klicke hier für eine leichte Übung\\\" id=\\\"bug_click\\\" href=\\\"\\\">\\n <li id=\\\"workbar_bug\\\">\\n <i class=\\\"fa fa-bug\\\"><\\/i>\\n <span id=\\\"bug_text\\\"><\\/span>\\n <\\/li>\\n<\\/a> <a title=\\\"andere Stufe\\\" id=\\\"back_to_base_click\\\" href=\\\"\\\">\\n <li id=\\\"change_level\\\">\\n <i class=\\\"fa fa-signal\\\"><\\/i>\\n <span>andere Stufe<\\/span>\\n <\\/li>\\n<\\/a> \\n<\\/ul>\\n\\n<form id=\\\"answerForm\\\"\\n name=\\\"answerForm\\\"\\n action=\\\"#dummy\\\">\\n\\n <div id= \\\"answer_field\\\"\\n title= \\\"Tippe Deine Antwort hier\\\">\\n <input type = \\\"text\\\"\\n id = \\\"txtanswer\\\"\\n name = \\\"txtanswer\\\"\\n size = \\\"3\\\"\\n maxlength = \\\"3\\\" />\\n <\\/div>\\n \\n <button type=\\\"submit\\\" \\n id=\\\"submit_answer\\\">\\n <i class=\\\"fa fa-level-down fa-rotate-90\\\"><\\/i>\\n <span>OK<\\/span>\\n <\\/button>\\n\\n<\\/form>\\n\\n\");"
AJAX 调用返回的 JavaScript 不会自动执行。这对于安全性来说非常糟糕。
当Rails UJS 处理 AJAX 响应时,它会创建一个脚本标签并将其附加到评估脚本的文档中:
这基本上只是 JSONP 技术的演变,该技术用于在黑暗时代对 JSON 进行跨域请求,并被纳入(非常)穷人的 AJAX 框架。
如果您想在模板的奇妙之塔上进行构建,
js.erb
那么只需使用 JS 创建表单或将其隐藏在页面上并触发提交以让 Rails UJS 为您处理它,而不是使用编写 AJAX 处理程序,这会更容易fetch
。或者你可以像一个理智的人一样不将 HTML 块包装在 JavaScript 中。
这就是 Turbo 所做的。
我明白了
@partial = "workbar_work"
。render (partial: workbar_work, ...)
找不到时,_workbar_work.html.erb
文件。因为它在工作文件夹中或者
您可以设置
@partial = "work/#{permitted_params[:partial].to_s}"