VUE+FLASK前后端分离(回答面试题之“你来说说restful前后端代码怎么写”)
动机
前段时间出去面试,遇到了好几次对方面试官问这样的问题,”restful风格的代码,前后端怎么写?”,“从浏览器前端到后台经过了哪些?说的越详细越好。”这样的问题,我听到的第一时刻是懵逼的,啥情况?我要从vue的双向数据绑定开始说吗?axios的用法要说吗?falsk的restful是如何用‘’/api/‘’对应前台的url的吗?还是去说spring框架的mvc? 产生这样的疑惑,主要原因是,我不明白面试官为什么要问这样的问题?实现起来很简单,但是说起来又太宽泛,不知道说的是不是面试官想要的答案,容易偏题。 在我回头仔细想想了之后,决定以后再遇到这样的问题,就使用vue+falsk做例子来讲解这个。
回答策略
按照下面的几步,顺序回答
- 以vue+flask 前后端分离为基础,以用户登录,输入用户名密码为场景。
- vue前端框架通过v-model获得输入框输入的用户名以及密码。通过引入axios向后台发起http请求,axios是一个http库,可以在nodejs中使用,使用方式有一点类似ajax。通过axios.post(“/api”,{param:”param”})的方式向后台发起http请求。
- 后台的flask运行起来之后,通过装饰圈route.配置路由@app.route(‘/api’,methods=[“GET”,”POST”]) 来对应前台http请求的url,如果没有对应的url会返回404。如果找到对应的路由,则会进入相应的方法,进行运算,完成运算之后,可以用json.dumps把数据作为json返回。
- axios前台的response收到后,通过response.data获得返回的json,然后可以把相应的值进行变更
代码实现
- 前端vue关键代码之 index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vueapp01</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<style>
.class1{
background: #444;
color: #eee;
}
</style>
<body>
<div id="app3"></div>
</body>
</html>
- 前端vue关键代码之main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import Lzw from './components/Lzw'
import router from './router'
import axios from 'axios'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(BootstrapVue)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app3',
router,
axios,
components: { Lzw },
template: '<Lzw/>'
})
- 前端vue关键代码之Lzw.vue
使用axios需要先安装axios库和HTTP2库
npm install –save axios
npm install –save http2
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<div id="example-3">
<input type="checkbox" id="jack" value="白金会员" v-model="checkedNames">
<label for="jack">白金会员</label>
<input type="checkbox" id="john" value="黄金会员" v-model="checkedNames">
<label for="john">黄金会员</label>
<input type="checkbox" id="mike" value="王者会员" v-model="checkedNames">
<label for="mike">王者会员</label>
<br>
<strong>选择会员种类: {{ checkedNames }}</strong>
</div>
<div id="app2">
<input v-model="username" placeholder="用户名">
<p>用户名是: {{ username }}</p>
<input type="password" v-model="password" placeholder="密码">
<p>密码是: {{ password }}</p>
<button class="btn btn-large btn-primary" v-on:click="login">向后台发送post请求,传递用户名和密码,变更用户ID</button>
<p>用户ID是: {{ id }}</p>
<button class="btn btn-large btn-primary" v-on:click="getmsg">向后台发送get请求,把用户ID变成0</button>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "hello",
data() {
return {
msg: "欢迎来到测试开发笔记!",
checkedNames: [],
username: "",
password: "",
id: "密码反转+用户名反转"
};
},
methods: {
login() {
var that = this;
// 对应 Python 提供的接口,这里的地址填写下面服务器运行的地址,本地则为127.0.0.1,外网则为 your_ip_address
const path = "http://127.0.0.1:5000/getMsg";
axios
.post(path, { username: this.username, password: this.password })
.then(response => {
this.id = response.data.userid;
});
},
getmsg() {
var that = this;
// 对应 Python 提供的接口,这里的地址填写下面服务器运行的地址,本地则为127.0.0.1,外网则为 your_ip_address
const path = "http://127.0.0.1:5000/getMsg";
// 务必使用箭头函数的方法,这样this.id能直接对上,不然会报错提示id没找到
axios
.get(path, { username: this.username, password: this.password })
.then(response => {
this.id = response.data.userid;
});
}
}
};
</script>
- 后端flask关键代码main.py
flask要避免跨域问题。需要安装Flask库和Falsk-Cors库
from flask import Flask, url_for,request
from flask_cors import *
import json
app = Flask(__name__)
# 这句话解决跨域问题
CORS(app, supports_credentials=True)
@app.route('/getMsg',methods=["GET","POST"])
def getMsg():
if request.method == 'POST':
username = request.json['username']
password= request.json['password']
# 假定用户id是密码反转+用户名反转得出来的
datat = {
"userid": username[::-1]+password[::-1],
}
return json.dumps(datat)
elif request.method == 'GET':
datat = {
"userid": 0,
}
return json.dumps(datat)
if __name__ == '__main__':
app.debug = True
app.run()