AJAX、jQuery、CORS
需求
自己做了个问答系统,客户端用户在前端页面提出问题,问题需要提交到后台(不同域的服务端,不同域:域名,端口等有一个不同就是跨域问题),后台给出问题答案后返回前端进行异步刷新(ajax)。
遇到的问题
-
如何实现局部刷新(异步刷新
- ajax 可以实现异步传输数据、局部刷新
-
在上个问题基础上遇到了,ajax跨域问题
- 跨域常见的方法有jsonp,CORS技术
- jsonp只能发送GET请求,CORS可以发送GET或者POST等
- CORS主要是在服务端配置允许请求的域信息(我的服务端采用的flask,底层是WSGI服务协议)
-
前端 form提交时数据没有提交成功
- 注意看浏览器控制台是否报错,最开始报错‘$.ajax func is not found’,是因为我引入的jQuery是slim版本,其中的ajax被移除了,故需要重新引入包含ajax的jquery.js文件
- 包问题解决后发现form表单数据还是提交不成功,经过各种摸索,试验,最后发现普通的 按钮,默认的type=‘submit’,会自动提交数据,导致页面刷新(相当于自己编写的ajax函数没有得到请求结果就被刷新覆盖了),而在form外部是可以提交成功的,但是这样我们就无法获得表单的提交信息了。解决:input 、button 想要在form内部顺利提交表单(能够执行ajax并返回结果,不被强制刷新页面),都需显示指定type=‘button’
-
浏览器缓存问题
以link、script 文件方式引入的文件修改后要清楚浏览器缓存才能看到效果。否则会出现代码都对了,但是达不到效果,也不知到问题出在哪里的现象,这个问题很容易被忽视。 -
局部更改 带有!import 的css属性问题
- js有个 ‘cssText’ 属性,存储了当前元素的所有css值,我们可以通过在这个cssText基础上增加、覆盖值来更改
javascript">$("#card-header").text("查询成功").css("cssText","background-color:#28a745 !important;color:#fff;");
前端
method one:
javascript"><script>
$(document).on("click","#btn",get_answer); //绑定按钮
function get_answer(){
var start_time = get_time();
var question = $("#question").get(0).value;
if (question == ''){
return false;
}
$.ajax({
type:'post',
data:{"question":question},
url:'http://127.0.0.1:5000/',
async:true,
dataType:"json",
// xhrFields: {withCredentials: true}, //加这个报错,暂时不知道为啥???
success:function (data,status) {
console.log("status : " + status);
console.log("answer : " + data['answer']);
console.log("valid answer : " + data['valid_answer'])
$("#answer").text(data['answer']);
var time_consume = get_time() - start_time;
var valid_answer = data['valid_answer'];
if (valid_answer == "true"){
console.log("valid answer true comes")
$("#card-header").text("查询成功").css("cssText","background-color:#28a745 !important;color:#fff;");
}
else {
console.log("valid answer false comes");
$("#card-header").text("查询失败").css("cssText","background-color:#dc3545 !important;color:#fff;");
}
$("#time_consume").text("用时: " + time_format(time_consume) + "s");
console.log("花费时间 : " + time_consume.toString());
},
error:function(){
console.log("Request error.")
var err_msg = "请求服务器出错,请稍后尝试。"
$("#answer").text(err_msg);
}
})
}
function get_time() {
return new Date().getTime();
}
function time_format(time) {
var seconds = time / 1000;
return seconds.toFixed(2); // 保留2位小数
}
</script>
<form action="" class="flex justify-content-center align-items-center">
<div class="input-group">
<input type="text" class="form-control" placeholder="请输入问题" id="question">
<button type="button" id="btn" class="btn btn-secondary" onclick="get_answer()">
<span class="fa fa-search"></span>
</button>
</div>
</form>
method two:
javascript">// get_answer 函数 同上,可以把onclick直接写在input里面。实现绑定
<form action="" class="flex justify-content-center align-items-center">
<div class="input-group">
<input type="text" class="form-control" placeholder="请输入问题" id="question">
<input type="button" class="btn btn-secondary" onclick="get_answer()">
<span class="fa fa-search"></span>
</input>
</div>
</form>
后端(基于Flask)
from flask import Flask,request,make_response,jsonify
from flask_cors import * # 解决ajax 跨域问题请求
app = Flask(__name__)
# r'/*' 是通配符,让本服务器所有的URL 都允许跨域请求
# CORS(app, resources=r'/*',supports_credentials=True) # supports_credentials=True 多加会报错,暂时不知道原因
CORS(app, resources=r'/*')
@app.route("/",methods=('GET', 'POST'))
def index():
global handler
if request.method == 'POST':
print("get post request")
question = request.form['question']
answer = handler.question_answer_main(question)
if answer == "非常抱歉,这个问题超出小医的能力范围!":
valid_answer = "false"
else:
valid_answer = "true"
result_text = {"statusCode": 200, "answer": answer,"valid_answer":valid_answer}
response = make_response(jsonify(result_text)) # jsonify 返回json格式数据
response.headers['Access-Control-Allow-Origin'] = '*'
# response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'OPTIONS,HEAD,GET,POST'
response.headers['Access-Control-Allow-Headers'] = 'x-requested-with'
return response
else:
question = request.args.get('question')
answer = handler.question_answer_main(question)
return answer