【譯】一個小時搭建一個全棧Web應用框架(下)——美化與功能

翻譯:瘋狂的技術宅
原文標題: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

clipboard.png

爲了可以實現這一點,咱們須要先弄清楚如下的問題:react

  1. 每次調用 /hello 端點時,如何返回一個隨機的歐洲語言「Hello」。jquery

  2. 如何從服務器請求信息。webpack

  3. 如何將返回的信息無縫顯示給用戶,從而無需刷新頁面。git

  4. 如何在頁面上添加樣式,能夠在頁面上建立一個大的居中的按鈕並添加文本。

  5. 最後,咱們必須搞清楚應該如何添加一個背景圖像。

從服務器返回隨機語言的「Hello」

每當咱們與服務器上的 /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類

把問題分解被認爲是良好的編程習慣。 只要有可能,你應該儘可能使本身的函數只作一件事情,而且作好。這點一樣適用於類。你能夠考慮將每一個函數或類都做爲單獨的組件。

React是爲組件化而設計的。這意味着它是用多個較小的部分來構建你的網站的。就像玩樂高同樣,能夠輕鬆地將一個組件替換成另一個,也能夠複用組件,這也能幫助其餘開發人員瞭解你的代碼。咱們應該努力的編寫可理解的代碼,由於這樣可使咱們的程序更容易維護和擴展。

考慮到組件化,咱們建立一個 Hello 類來處理咱們網頁上的問候語。該類將從服務器上的 /hello 端點點獲取一個 「Hello」 ,並將其顯示給用戶。 它也應該有一個「name」參數,這樣就能夠向某個具體的人進行問候。

經過更改 React App 類中的render函數,使其調用Hello類,咱們就能夠很快的完成功能,而不是使用舊的代碼。傳遞名稱「Rimini」做爲參數。出於結構化的目的,咱們將把Hello類放在一個 PageHeader 中。

建立Hello類

前面咱們修改了 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內嵌到了個人代碼中,因此能夠很輕鬆地控制他們在頁面上的最終位置。

綁定「this」

由於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 服務器後。 應該能看到如下內容:

clipboard.png

有一行問候語,一個按鈕,點擊按鈕能夠更改問候語。 這個頁面看起來很不錯,由於咱們在index.html中包含了Bootstrap樣式。

使用CSS樣式美化頁面

咱們終於有了一個可以與用戶交互的產品。若是咱們願意,就能夠到此爲止了,並對本身說:我對這些成就感到滿意。不過就我我的而言,我更喜歡在個人Web應用中添加一些設計元素,讓他們變得更加漂亮。因此,咱們將用CSS使標題可以覆蓋整個屏幕,而不是在頁面的頂部。CSS是爲HTML設計的一種樣式語言,它的做用至關於在Word文檔中更改字體大小,樣式和位置。

使 Webpack 可以處理 CSS

爲了可以在咱們的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了,咱們將在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 的話,字體可能和圖中不同:

clipboard.png

被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()}

刷新瀏覽器窗口時,應該看到如下內容:

clipboard.png

恭喜你!你已成功建立了一個全棧 Web 應用程序!

關注微信公衆號:充實的腦洞, 一個技術宅的保留地
相關文章
相關標籤/搜索