翻译:疯狂的技术宅
原文标题:Creating a full-stack web application with Python, NPM, Webpack and React — Beauty and Functionality
原文连接:https://codeburst.io/creating...
本文首发微信公众号:充实的脑洞。转载需注明出处!javascript
若是你遵循前面的教程中的步骤,如今应该有了一个能够工做的全栈Web应用程序框架。css
点击直达前文 >> 【译】一个小时搭建一个全栈Web应用框架(上)html
若是没有,但仍是要继续学习本教程,能够到个人GitHub页面下载代码。前端
对于下一个魔术,咱们将把一个显示“Hello World!”的简单静态页面转换成一个漂亮的单页面WEB应用。 这个页面可以与后端通讯,而且在收到新信息时当即更新,而无需用户刷新页面。咱们即将建立的页面,在每次点击按钮时,会以随机的欧洲语言返回“Hello”。java
这是咱们的页面:python
为了可以实现这一点,咱们须要先弄清楚如下的问题:react
每次调用 /hello
端点时,如何返回一个随机的欧洲语言“Hello”。jquery
如何从服务器请求信息。webpack
如何将返回的信息无缝显示给用户,从而无需刷新页面。git
如何在页面上添加样式,能够在页面上建立一个大的居中的按钮并添加文本。
最后,咱们必须搞清楚应该如何添加一个背景图像。
每当咱们与服务器上的 /hello
端点进行通话时,为了可以请求一个随机的欧洲语言“Hello”,必须更改 server/server.py 文件中的功能。每次调用它时,都不会返回静态的“Hello World”,而是从“Hello”列表中选择一个随机语言的“Hello”。为了实现这个功能,须要进行如下更改:
import random def get_hello(): greeting_list = [‘Ciao’, ‘Hei’, ‘Salut’, ‘Hola’, ‘Hallo’, ‘Hej’] return random.choice(greeting_list)
这个函数定义了一个欧洲语言的“hello”列表, 而后咱们调用这个函数时,使用 random.choice()
从列表中随机选择一个项目。
修改 hello()
函数,以便在每次调用它时返回get_hello()
。
@app.route("/hello") def hello(): return get_hello()
修改 /hello
以返回咱们感兴趣的信息,咱们如今须要弄清楚如何从前端获得这些信息。
把问题分解被认为是良好的编程习惯。 只要有可能,你应该尽可能使本身的函数只作一件事情,而且作好。这点一样适用于类。你能够考虑将每一个函数或类都做为单独的组件。
React是为组件化而设计的。这意味着它是用多个较小的部分来构建你的网站的。就像玩乐高同样,能够轻松地将一个组件替换成另一个,也能够复用组件,这也能帮助其余开发人员了解你的代码。咱们应该努力的编写可理解的代码,由于这样可使咱们的程序更容易维护和扩展。
考虑到组件化,咱们建立一个 Hello
类来处理咱们网页上的问候语。该类将从服务器上的 /hello 端点点获取一个 “Hello” ,并将其显示给用户。 它也应该有一个“name”参数,这样就能够向某个具体的人进行问候。
经过更改 React App 类中的render函数,使其调用Hello
类,咱们就能够很快的完成功能,而不是使用旧的代码。传递名称“Rimini”做为参数。出于结构化的目的,咱们将把Hello
类放在一个 PageHeader
中。
前面咱们修改了 App
类使其可以调用 hello
类, 接下来须要建立 Hello
类。在 js/
目录下建立一个名为 hello.jsx
的文件, 在此文件中定义一个名为 hello
的类。
export default class Hello extends React.Component { constructor(props) { super(props); this.state = {greeting: 'Hello ' + this.props.name}; // This binding is necessary to make `this` work in the callback this.getPythonHello = this.getPythonHello.bind(this); } }
在这一点上,你可能对构造函数中发生了什么有不少疑问。
在 React 中有一种叫作组件和道具的东西。 Props是建立时传递给构造函数的不可变参数。 道具是公开的,修改他们将违反 React 的基本使用原则。状态是内部的,可变的。每次更新状态时,都会在UI中从新展示。若是但愿更深刻地了解其运做方式,我强烈建议你阅读React文档中有关生命周期和状态的部分。
咱们将在Hello
类中添加一个名为personaliseGreeting()
的函数。 当咱们点击按钮得到一个新的问候语时,它将会处理网页上的问候语的更新操做。 请注意,咱们使用this.setState()
与名为“greeting”的key。你必须使用这个语法才能让 React 自动刷新网页上的“greeting”状态。
personaliseGreeting(greeting) { this.setState({greeting: greeting + ' ' + this.props.name + '!'}); }
为了让问候语出如今页面上,必须在render
函数中调用“{this.state.greeting}”
。咱们还必须添加一个带有回调函数的按钮,这个函数叫作getPythonHello()
,咱们很快就会实现它。这个函数在调用使用Python编写的后端时,将会获得一个新的“Hello”。
render () { return ( <h1>{this.state.greeting}</h1> <hr/> <Button bsSize="large" bsStyle="danger" onClick={this.getPythonHello}> Say Hello! </Button> ) }
请注意,我已经将标题和按钮HTML内嵌到了个人代码中,因此能够很轻松地控制他们在页面上的最终位置。
由于JavaScript中的类方法没有作默认绑定,因此当咱们想在函数回调中使用“this”时,就必须在构造函数中建立一个绑定。不然“this”将会是 undefined 的。 这适用于在 JavaScript 中调用without()
的状况。一个典型的例子就是 render()
中的 “onClick = {this.getPythonHello}”
。
React 没有提供执行HTTP请求的内置方式。为了可以从服务器请求信息,咱们将不得不找一个能够作这件事的库。 一个最简单的方法就是引入 jQuery 库。jQuery 是一个 javascript 库,经过在$符号后面提供缩写函数来简化标准的 JavaScript 功能。
首先安装jQuery依赖关系:
$ npm i jquery --save-dev
将 jQuery 依赖添加到要使用的 React 文件中,也就是 Hello.jsx 中。应该将此依赖添加到 Hello
类的定义前面。
var $ = require(‘jquery’);
将查询依赖添加到React文件中意味着能够在本身的React代码中使用标准的 jQuery 函数,只要它们以咱们刚刚定义的“$”变量开始。下面让咱们用它来从服务器获取一个“Hello”。
咱们将使用 HTTP 协议的 GET 请求获取信息。GET 实质上是HTTP请求的“只读”模式。能够用来获取信息,可是不能要求服务器更改它。
在 hello.jsx 文件中的Hello
类中添加如下函数:
getPythonHello() { $.get(window.location.href + 'hello', (data) => { console.log(data); this.personaliseGreeting(data); }); }
此函数经过jQuery 的 GET请求,链接 /hello
端点。而后获得从服务器返回的一个欧洲语言的“hello”信息,再它打印到浏览器的开发控制台,最后将它传递给Hello
类中的另外一个函数,调用 personaliseGreeting()
。
当 rebuild 前端代码(npm run watch),并从新启动 python 服务器后。 应该能看到如下内容:
有一行问候语,一个按钮,点击按钮能够更改问候语。 这个页面看起来很不错,由于咱们在index.html中包含了Bootstrap样式。
咱们终于有了一个可以与用户交互的产品。若是咱们愿意,就能够到此为止了,并对本身说:我对这些成就感到满意。不过就我我的而言,我更喜欢在个人Web应用中添加一些设计元素,让他们变得更加漂亮。因此,咱们将用CSS使标题可以覆盖整个屏幕,而不是在页面的顶部。CSS是为HTML设计的一种样式语言,它的做用至关于在Word文档中更改字体大小,样式和位置。
为了可以在咱们的WEB应用中使用CSS,必须安装一些加载器和插件,并将它们添加到Webpack配置文件中。这是由于 Webpack 默认只能处理JavaScript。
安装下列插件:
css-loader
style-loader
extract-text-webpack-plugin
css-loader 和 style-loader 可以使 Webpack 处理 CSS。 经过添加这些加载器,Webpack 将可以将咱们须要的任何 CSS 绑定到 bundle.js 中。 不过在这里存在一个问题,JavaScript 和 CSS 将不会在你的页面上单独进行加载,这可能致使 UI 组件在 JavaScript 加载以前没法显示。这点不好劲,由于在糟糕的网络上,咱们辛辛苦苦设计出来的页面可能会加载的很是缓慢。
不过能够经过添加 extract-text-webpack-plugin 来解决这个问题。 这个插件可以将 CSS 分解成一个单独的包,咱们能够把它附加到 HTML 上。 这样就可使 CSS 再次独立于 JavaScript 进行加载。
在你的webpack.config.js
文件的 modules.rules
部分添加下面的CSS规则:
{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader', }) },
将ExtractTextPlugin插件添加到 webpack.config.js
(若是您感到困惑,请查看个人 webpack 文件)。注意,在建立时,须要将捆绑的CSS文件名传给此插件。咱们将调用文件'styles.css'。
plugins: [ new ExtractTextPlugin('styles.css') ]
最后,咱们须要将 styles.css 包添加到index.html
中,以确保样式被加载。将如下行添加到你的index.html
文件中的 head 部分(能够参考个人代码):
<link rel="stylesheet" href="dist/styles.css">
如今能够确保咱们的设置能够正确处理CSS了,咱们将在css文件夹中建立一个名为fullstack.css 的文件。我已经添加了几个不一样的规则,以确保文本和按钮出如今正确的位置,而且文本是大号的细体。
这是个人 fullstack.css 文件中的一个规则。 它使 “Hello Rimini” 文本变得愈来愈细:
.header-contents h1 { font-size: 120px; font-weight: 300; }
在建立 fullstack.css 文件以后,咱们须要将它添加到使用规则的 React 组件中,这样它们才能生效。因为标题在 App.jsx 中定义,因此须要添加如下代码:
require('../css/fullstack.css');
fullstack.css 文件中的标题样式如今将由 Webpack 拾取,并绑定到 styles.css 文件中。当咱们刷新页面时,应该以下图所示。注意,若是你用的浏览器不是 Chrome 的话,字体可能和图中不同:
被CSS装饰后的页面
Webpack 自己并不理解图像的概念。所以,咱们还须要添加一个能够在Web应用程序中使用它们的加载程序。咱们须要安装名为“file-loader”的loader。
安装 file-loader:
$ npm i file-loader --save-dev
将file-loader规则添加到 webpack.config.js 文件中的modules.rules部分:
{ test: /\.(png|svg|jpg|gif)$/, use: 'file-loader' }
将要使用的图像添加到images/ folder。将其命名为“header.jpg”。
为了可以使图像成为网页头部的背景,咱们须要将其做为背景图像添加到 fullstack.css 文件的页眉部分。
.page-header { background-image: url('../images/header.jpg'); background-repeat: no-repeat; background-position: center; background-size: cover; }
接下来要作的是把图像加载到使用它的 React 文件中。若是没有在 React 中显式加载图片,Webpack 将不会棒的它,也不会把它显示在页面上。这种行为不是很直观,在我第一次在本身的应用中添加一个背景图像时,曾经犯过这个错误。
在App.jsx中进行以下更改:
import HeaderBackgroundImage from '../images/header.jpg';
将此函数添加到你的App类:
addHeaderImg() { let headerBg = new Image(); headerBg.src = HeaderBackgroundImage; }
这个函数建立了一个新的Image对象,并将源设置为你的标题图片。
咱们须要作的最后一件事是,确保在渲染页面时加载图像。 这意味着咱们必须在render()
函数中调用 addHeaderImg()函数。
将下列代码添加到render()
函数中:
{this.addHeaderImg()}
刷新浏览器窗口时,应该看到如下内容:
恭喜你!你已成功建立了一个全栈 Web 应用程序!
关注微信公众号:充实的脑洞, 一个技术宅的保留地 | |
---|---|
![]() |