Flask-Vue-Crud - 01. 项目介绍及搭建

主要依赖

  • Vue v2.5.2
  • Vue CLI v2.9.3
  • Node v10.3.0
  • npm v6.1.0
  • Flask v1.0.2
  • Python v3.6.5

教学目标

课程结束后,你应该可以:

  1. 解释什么是 Flask
  2. 解释什么是 Vue,并且清楚 Vue 同其他前端框架 ,如 Angular、React 的区别
  3. 通过脚手架(Vue CLI)来快速创建前端项目
  4. 通过 Vue 组件创建单页面应用
  5. 通过异步请求将 Vue 前端应用和 Flask 后端应用连通
  6. 通过 Flask 开发 RESTful API
  7. 通过 Bootstrap 来美化 Vue 组件
  8. 通过 Vue 路由来创建路由并渲染组件

什么是 Flask?

Flask 是一个简单却很强大的 web 微框架,可以非常完美的来构建 RESTFul API。就像 Ruby 的 Sinatra 和 Node 的 Express,它非常小和灵活,根据需要,你可以从一个很小的应用开始,逐步添加功能到一个复杂的应用。

初次接触 Flask,可以从下面两个教程开始:

  1. Flaskr TDD
  2. Flask for Node Developers

什么是 Vue?

Vue 是一个开源的 Javascript 框架,用来编写用户界面。它借鉴了 React 和 Angular 的一些优秀概念。

以下两篇文章,比较了 Vue 跟 Angular 和 React 的一些比较:

  1. Vue: Comparison with Other Frameworks
  2. Angular vs. React vs. Vue: A 2017 comparison

Flask Setup

执行如下命令,创建项目目录,并启用虚拟环境
upload successful

安装 Flask 和 Flask-CORS 扩展
upload successful

在项目根目录下,创建 app.py文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask, jsonify
from flask_cors import CORS

app = Flask(__name__)

CORS(app)

@app.route('/ping', methods=['GET'])
def ping_pong():
return jsonify('Pong!')

if __name__ == '__main__':
app.run()

执行如下命令,运行 app:
upload successful

打开浏览器,键入http://localhost:5000/ping,会看到如下内容:

1
"Pong!"

为什么需要 Flask-CORS?

如果使用不同的协议,或者请求来自于其他的 IP 地址或域名或端口,就需要用到 Cross Origin Resource Sharing (CORS),这正是 Flask-CORS 扩展帮我们做到的。当然,实际产品环境中,我们应该配置只允许来自前端应用所在的域来请求。

Vue Setup

全局安装 Vue CLI :
upload successful

接着,执行如下命令,通过 webpack来初始化一个新的 Vue 项目 client
upload successful

我们主要要写的代码都在 src目录里,目录结构如下所示:
upload successful

解释如下:

名字 作用
main.js app 的入口,它会加载和初始化 Vue 和根组件
App.vue 根组件 - 其他组件的入口
assets 静态文件如图片和字体等都放在这里
components UI 组件放在这里
router URL 同组件的映射关系在这里定义

client/src/components/HelloWord.vue是自动生成的单文件组件,有三部分组成:

  1. template: 组件的 HTML 内容
  2. script: 组件的逻辑代码(Javascript)
  3. style: 组件的样式(CSS)

执行如下命令,运行前端程序:
upload successful

访问 http://localhost:8080 能看到前端页面

添加新组件

创建client/src/components/Ping.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<p>{{ msg }}</p>
</div>
</template>

<script>
export default {
name: 'Ping',
data() {
return {
msg: 'Hello!',
};
},
};
</script>

更新client/src/router/index.js,映射/pingPing组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
import Ping from '@/components/Ping';

Vue.use(Router);

export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld,
},
{
path: '/ping',
name: 'Ping',
component: Ping,
},
],
mode: 'history',
});

上面的mode: 'history'是为了让 URL 变成http://localhost:8080/ping的形式。如果,不加该设置,默认的 URL 为http://localhost:8080/#/ping的形式。

最后,修改client/src/App.vue,移除模板里自带的图片:

1
2
3
4
5
<template>
<div id="app">
<router-view/>
</div>
</template>

现在,访问http://localhost:8080/ping,能看到Hello!

连接前后端

通过使用axios库发送 AJAX 请求,axios安装如下:
upload successful

更新Ping.vue组件中script部分,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
script>
import axios from 'axios';

export default {
name: 'Ping',
data() {
return {
msg: '',
};
},
methods: {
getMessage() {
const path = 'http://localhost:5000/ping';
axios.get(path)
.then((res) => {
this.msg = res.data;
})
.catch((error) => {
// eslint-disable-next-line
console.error(error);
});
},
},
created() {
this.getMessage();
},
};
</script>

启动后端 Flask 应用,访问http://localhost:8080/ping,会看到页面会呈现后端返回的数据。

Bootstrap Setup

为了给页面增加样式,可以引入 CSS 框架 bootstrap,通过如下命令安装bootstrap
upload successful

在 app 的入口文件client/src/main.js中导入 bootstrap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import 'bootstrap/dist/css/bootstrap.css';
import Vue from 'vue';
import App from './App';
import router from './router';

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
});

去掉根组件client/src/App.vue中多余的样式:

1
2
3
4
5
<style>
#app {
margin-top: 60px;
}
</style>

Ping.vue组件中增加样式:

1
2
3
4
5
<template>
<div class="container">
<button type="button" class="btn btn-primary">{{ msg }}</button>
</div>
</template>

再次访问http://localhost:8080/ping查看效果如下:
upload successful