Rails 6:使用fetch()和params渲染.js.erb时HTML未替换问题
解决Rails中fetch()调用.js.erb模板不更新页面的问题
问题背景
升级旧Rails应用时,将原jQuery的$.ajax()替换为fetch()调用后,服务器能正常处理请求并返回渲染好的.js.erb代码,浏览器控制台也能接收到内容,但页面中#workbar_switch的内容始终未被指定局部视图替换。
现有代码
控制器代码
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@}) %>");
fetch调用代码
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(() => { }) }
解决建议
手动执行返回的JS代码
fetch()API不会自动执行返回的JavaScript内容,必须手动处理。可以在获取到responseText后执行以下操作:.then(responseText => { console.log("received js", responseText); // 方式1:直接执行(注意安全风险) eval(responseText); // 方式2:创建script标签插入页面(更安全) const script = document.createElement('script'); script.textContent = responseText; document.body.appendChild(script); document.body.removeChild(script); })注意:使用
eval()时要确保返回的JS代码来自可信源,避免XSS攻击。修复js.erb中的语法错误
现有switch_state.js.erb里存在笔误:exercise: @exercise@多了一个@符号,会导致生成的JS代码无效。修正后代码:$('#workbar_switch').html("<%= j render(partial: @partial, locals: {exercise: @exercise}) %>");确认jQuery是否正常加载
返回的JS代码依赖$(jQuery),如果页面已移除jQuery,这段代码会执行失败。可以在浏览器控制台输入$验证是否存在:- 若jQuery仍在页面中,确保加载顺序正确;
- 若已移除jQuery,将JS代码改为原生DOM操作:
document.getElementById('workbar_switch').innerHTML = "<%= j render(partial: @partial, locals: {exercise: @exercise}) %>";
内容的提问来源于stack exchange,提问作者Daniela
相关产品推荐
相关产品推荐

