应用程序的html视图包含一个默认设置为20的变量。然后,当在浏览器中运行应用程序时,使用向上/向下按钮增加或减少此温度。但是,如果浏览器或页面被刷新(或重定向),则温度不会保留,而是始终重置为20。
以下是观点:
<!DOCTYPE html> <link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'> <html> <head>
<link rel="stylesheet" type="text/css" href="style.css"> </head> <body>
<section class="display">
<h1>Thermostat</h1>
<input id='city' type='text' placeholder="city name">
<button id='submit'>Submit</button>
<p id='weather'></p>
<h1 id="temperature"></h1>
<h4 id="psm"></h4>
<form action='/temperature' method='post'>
<button class="icon icon-up" id="up" name='temp'></button>
<button class="icon icon-down"id="down" name='temp'></button>
<button id="reset" name='temp'>reset</button>
<button id="switchpowersaving">PSM</button>
</form>
</section>
<script src="jquery.js"></script>
<script src="thermostat.js"></script>
<script src="interface.js"></script>
<script src="weatherAPI.js"></script> </body> </html>
当我们访问该页面时,我们将被定向到索引。然后我们在这里增加/减少温度。每次温度变化时,都会发布一个&#39; POST&#39;方法被发送到我们的/温度页面。然后,这将使用JSON,会话和参数创建哈希。这在interface.js文件中有一个ajax GET函数,它将这个新温度存储为data.temp。然后,每次重新加载页面时,应将thermostat.temperature设置为存储的data.temp。但是它会不断重置为20。
这是控制器:
require 'sinatra'
require 'json'
enable :sessions
get '/' do
send_file 'views/index.html'
end
post '/temperature' do
p params[:temp]
session[:temp] = params[:temp].to_i
redirect '/temperature'
end
get '/temperature' do
p session[:temp]
if session[:temp]
JSON.generate({temp: session[:temp]})
else
JSON.generate({temp: 20})
end
redirect '/'
end
这是interface.js文件:
$(document).ready(function() {
var thermostat = new Thermostat();
var temp = thermostat.temperature;
$.ajax({
type: 'GET',
url: 'http://localhost:4567/temperature',
success: function(data){
temp = data.temp;
},
error: function(){
alert('Error loading temp');
}
});
updateTemperature();
$('#up').click(function() {
thermostat.increaseTemperature();
updateTemperature();
});
$('#down').click(function() {
thermostat.decreaseTemperature();
updateTemperature();
});
$('#reset').click(function() {
thermostat.tempReset();
updateTemperature();
});
$('#switchpowersaving').click(function() {
thermostat.switchModePowerSaving();
updateTemperature();
});
function updateTemperature() {
$('#temperature').text(thermostat.currentTemperature() + "\xB0C");
$('#up').attr('value', thermostat.currentTemperature());
$('#down').attr('value', thermostat.currentTemperature());
$('#reset').attr('value', thermostat.currentTemperature());
$('.display').css('background-color', thermostat.displayColor());
$('#psm').text(thermostat.displayPowerSaveMode());
}
});
这是thermostat.js:
function Thermostat(){
this.temperature = 20;
this.MINTEMP = 10;
this.isPowerSaving = true;
this.thermostatDisplay = 'yellow';
}
Thermostat.prototype.currentTemperature = function(){
return this.temperature;
};
Thermostat.prototype.increaseTemperature = function(){
if ( this.currentTemperature() >= this.maxTemp()) {
throw 'Max. temp reached';
}
this.temperature ++;
};
Thermostat.prototype.decreaseTemperature = function(){
if ( this.currentTemperature() <= this.MINTEMP ) {
throw 'Min. temp reached';
}
this.temperature --;
};
Thermostat.prototype.maxTemp = function(){
if(this.isPowerSaving === true) {return 25;}
else
{return 32;}
};
Thermostat.prototype.switchModePowerSaving = function() {
if (this.isPowerSaving === true)
{this.isPowerSaving=false;}
else
{this.isPowerSaving=true;}
};
Thermostat.prototype.tempReset = function() {
this.temperature = 20;
};
Thermostat.prototype.displayColor = function() {
if(this.temperature <= 18) {return 'green';}
if(this.temperature <= 25) {return 'yellow';}
if(this.temperature > 25) {return 'red';}
};
Thermostat.prototype.displayPowerSaveMode = function(){
if(this.isPowerSaving === true) {return 'Power Save Mode: ON';}
else {return 'Power Save Mode: OFF';}
};
increaseTemperature / decreaseTemperature函数只是将thermostat.temperature增加和减少+ 1 / -1。
当直接访问&#39; /温度&#39;时,可以访问按下按钮时的新温度。但是在浏览器中重定向到&#39; /&#39;新的thermostat.temperature未设置为新温度,并始终重置为默认温度(20)。
如何在不使用数据库的情况下将其存储在状态中。 (存储新的温度,以便刷新页面时新的温度保持不变,而不是重置为20。
答案 0 :(得分:0)
这里有几个问题:
send_file
不是使用Sinatra加载HTML文件的首选方式。替代方法是将index.html
重命名为index.erb
,然后使用以下作为路由描述符:
get '/' do
erb :index
end
ERB是HTML的超集,并添加了ruby插值标记,可用于从Sinatra传递变量或只是在视图中运行ruby命令。如果您熟悉这些标记,则这些标记类似于JSP的<%%>
或PHP的<?php ?>
。在ERB中,<%%>
将运行ruby命令,<%= %>
可用于将ruby命令的结果打印到视图上。
在设计路线时,预先确定请求/响应的数据类型非常重要。例如,当interface.js
加载时,它会通过jQuery向GET
端点发出'/temperature
请求。由于您尚未指定数据类型,因此响应将为字符串,data.temp
将为null
。因此,在ajax调用中,您需要添加dataType: 'json'
设置:
$.ajax({
type: 'GET',
url: 'http://localhost:4567/temperature',
dataType: 'json',
success: function(data){
// same as earlier
});
另一个好处是不要在sinatra中混合和匹配AJAX调用和redirect
调用。这是一个问题,尤其是在这种情况下,因为当您重定向到索引页面时,虽然会话数据存在,但它不会被加载/显示在任何地方。理想情况下,在Sinatra中,您必须将值分配给实例变量并在视图中将其打印出来:
# app.rb
get '/' do
@temp = session[:temp] || 20
erb :index
end
# views/index.erb
# truncating common code
<h1 id="temperature"><%= @temp %></h1>
这样,当get '/'
路线加载时,显示初始温度。 $.ajax
GET
请求可以完全删除。
单击按钮时,默认情况下会发生表单提交,这将完全重新加载。这可能会搞乱你正在做的任何基于JS的渲染(我现在无法完全理解这部分)。因此,不是进行整页重定向,而是将AJAX帖子(如评论中指出的)改为“/ temperature”路径。请注意,您必须禁用按钮单击的默认操作。所以:
$('#up').click(function() {
thermostat.increaseTemperature();
updateTemperature();
});
和其他点击处理程序应更改为:
$('#up').click(function(event) {
event.preventDefault();
event.stopPropagation();
thermostat.increaseTemperature();
updateTemperature();
});
这将确保在您单击按钮时不会发生默认的HTML表单提交。 updateTemperature()
将进行ajax POST调用。我在这里提出了一个示例:https://gist.github.com/kgrz/9320d1682e682a9930c30e34c979a306