第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁(yè) 慕課教程 Flask 框架教程 Flask 框架教程 Flask 項(xiàng)目實(shí)戰(zhàn) 3: 前端實(shí)現(xiàn)

Flask 項(xiàng)目實(shí)戰(zhàn) 3: 前端實(shí)現(xiàn)

待做清單程序的總體結(jié)構(gòu)分為前端和后端兩個(gè)部分,上一節(jié)介紹了后端的實(shí)現(xiàn),本節(jié)講解前端的實(shí)現(xiàn)。

1. 首頁(yè)模板 templates/index.html

templates/index.html 是網(wǎng)站首頁(yè)的模板,包括如下幾個(gè)部分:

1.1 引入相關(guān)的庫(kù)

<html>
<head>
  <meta charset='utf-8'>
  <script src="https://lib.baomitu.com/jquery/2.2.4/jquery.min.js"></script>
  <link href="https://lib.baomitu.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="{{url_for('static', filename='style.css')}}" rel="stylesheet">
  <script src="{{url_for('static', filename='script.js')}}"></script>
  <title>每日清單</title>
</head>

在第 4 行和第 5 行,引入 JQuery 和 font-awesome 庫(kù)。

在第 6 行,引入網(wǎng)站的樣式文件 static/style.css,函數(shù) url_for(‘static’, filename=‘style.css’) 表示 static 文件夾下的文件 style.css,它的輸出為 static/style.css。

在第 7 行,引入 JS 文件 static/script.js,函數(shù) url_for(‘static’, filename=‘script.js’) 表示 static 文件夾下的文件 static/script.js,它的輸出為 static/script.js。

1.2 顯示 “登錄/注冊(cè)” 按鈕

<body>
  <div class='header'>
    <i class="fa fa-calendar-plus-o"></i> 待做清單
      
    {% if hasLogin %}
    <span class='login'>
      <i class="fa fa-sign-out"></i> 
      <a href='/users/logout'>退出</a>
    </span>
    {% else %}
    <span class='login'>
      <i class="fa fa-sign-in"></i> 
      <a href='/users/login'>登錄</a>
       
      <i class="fa fa-user-plus"></i> 
      <a href='/users/register'>注冊(cè)</a>
    </span>
    {% endif %}
  </div>

如果用戶沒(méi)有登錄,網(wǎng)站首頁(yè)的顯示 “登錄/注冊(cè)” 按鈕;如果用戶已經(jīng)登錄,網(wǎng)站首頁(yè)的顯示 “退出” 按鈕。

在第 5 行,變量 hasLogin 標(biāo)記用戶是否登錄,根據(jù) hasLogin 是否為真顯示不同的界面。

1.3 輸入待做事項(xiàng)的文本框

  {% if hasLogin %}
  <div>
    <input type="text" class="row" placeholder="輸入待辦事項(xiàng)">
    <i class="fa fa-fw fa-plus-square" onclick='onAddTodo(this);'></i>
  </div>
  {% endif %}

如果 hasLogin 為真,用戶已經(jīng)登錄,顯示一個(gè)文本框,用于輸入待做事項(xiàng)。

在第 4 行,顯示了一個(gè) font awsome 圖標(biāo) plus-square,點(diǎn)擊該圖標(biāo),調(diào)用函數(shù) onAddTodo(this) 向后端請(qǐng)求新增一個(gè)待做事項(xiàng)。

1.4 待做清單和完成清單

  {% for todo in todos %}
  <div>
    <input type="text" class="row" value="{{todo.title}}">
    <i class="fa fa-fw fa-check" onclick='onUpdateTodo({{todo.todoId}});'></i>
  </div>
  {% endfor %}

  <div class='header'>
    <i class="fa fa-calendar-check-o"></i> 完成清單
  </div>

  {% for done in dones %}
  <div>
    <input type="text" class="row" value="{{done.title}}">
    <i class="fa fa-fw fa-trash" onclick='onDeleteTodo({{done.todoId}});'></i>
  </div>
  {% endfor %}
</body>
</html>

頁(yè)面模板中有 2 個(gè)變量:todos 和 dones,todos 是 status 等于 ‘todo’ 的待做事項(xiàng)列表,dones 是 status 等于 ‘done’ 的待做事項(xiàng)列表。

在第 1 行,遍歷 todos,展示所有的待做事項(xiàng);在第 4 行,顯示了一個(gè) font awsome 圖標(biāo) check,點(diǎn)擊該圖標(biāo)表示已經(jīng)完成該項(xiàng),將待做事項(xiàng)移入到完成清單中,調(diào)用函數(shù) onUpdateTodo(todo.todoId) 向后端請(qǐng)求更新待做事項(xiàng)的 status 為 ‘done’。

在第 12 行,遍歷 dones,展示所有的完成事項(xiàng);在第 15 行,顯示了一個(gè) font awsome 圖標(biāo) delete,點(diǎn)擊該圖標(biāo),調(diào)用函數(shù) onDeleteTodo(todo.todoId) 向后端請(qǐng)求刪除待做事項(xiàng)。

2 注冊(cè)頁(yè)面模板 templates/register.html

注冊(cè)頁(yè)面 templates/register.html 顯示一個(gè)注冊(cè)表單,由如下部分構(gòu)成:

2.1 引入相關(guān)文件

<html>
<head>
  <meta charset='UTF-8'>
  <link href="https://lib.baomitu.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="{{url_for('static', filename='style.css')}}" rel="stylesheet">
  <title>注冊(cè)</title>
</head>

在第 4 行和第 5 行,引入font-awesome 庫(kù)。

在第 5 行,引入網(wǎng)站的樣式文件 static/style.css,函數(shù) url_for(‘static’, filename=‘style.css’) 表示 static 文件夾下的文件 style.css,它的輸出為 static/style.css。

2.2 注冊(cè)表單

<body>
  <h3><i class='fa fa-user-plus'></i> 注冊(cè)</h3>
  <form action="/users/register" method="POST">
    <div class="row">
      {{ form.name.label }}
      {{ form.name() }}
      <b>{{ form.name.errors[0] }}</b>
    </div>

    <div class="row">
      {{ form.password.label }}
      {{ form.password() }}
      <b>{{ form.password.errors[0] }}</b>
    </div>

    <div class="row">
      {{ form.submit() }}
    </div>

    {{ form.hidden_tag() }}
  </form>
</body>
</html>

form 是注冊(cè)表單,包括 3 個(gè)字段:name、password、隱藏字段,根據(jù) form 中字段 email 和 password 的屬性,它被渲染為如下的 HTML 文件:

<html>
<head>
  <meta charset='UTF-8'>
  <link href="https://lib.baomitu.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="/static/style.css" rel="stylesheet">
  <title>登錄</title>
</head>

<body>
  <div class="header"><i class='fa fa-sign-in'></i> 登錄</div>
  <form action="/users/login" method="POST">
    <div class="row">
      <label for="name">姓名</label>
      <input id="name" name="name" required type="text" value="">
      <b></b>
    </div>

    <div class="row">
      <label for="password">密碼</label>
      <input id="password" name="password" required type="password" value="">
      <b></b>
    </div>

    <div class="row">
      <input id="submit" name="submit" type="submit" value="登錄">
    </div>

    <input id="csrf_token" name="csrf_token" type="hidden" value="ImRlYTZjZDEwZjU3YjNjNGY0MDVkMDc4ZDhiZTMwNWM1OTk2MjhiMzAi.X2LvVA.0x7iz2PGVHH-r8dWf7KQNMkuSAE">
  </form>
</body>
</html>

這里注意兩點(diǎn):

  • form.email.errors 和 form.password.errors 是一個(gè)錯(cuò)誤信息列表,errors[0] 表示第一條錯(cuò)誤信息;
  • form.hidden_tag() 用于防范 CSRF 攻擊,生成 <input id=“csrf_token”/> 標(biāo)簽,請(qǐng)參考相關(guān)詞條。

2.3 登錄頁(yè)面模板 templates/login.html

登錄頁(yè)面 templates/login.html 顯示一個(gè)登錄表單,代碼如下:

<html>
<head>
  <meta charset='UTF-8'>
  <link href="https://lib.baomitu.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="{{url_for('static', filename='style.css')}}" rel="stylesheet">
  <title>登錄</title>
</head>

<body>
  <div class="header"><i class='fa fa-sign-in'></i> 登錄</div>
  <form action="/users/login" method="POST">
    <div class="row">
      {{ form.name.label }}
      {{ form.name() }}
      <b>{{ form.name.errors[0] }}</b>
    </div>

    <div class="row">
      {{ form.password.label }}
      {{ form.password() }}
      <b>{{ form.password.errors[0] }}</b>
    </div>

    <div class="row">
      {{ form.submit() }}
    </div>

    {{ form.hidden_tag() }}
  </form>
</body>
</html>

登錄頁(yè)面 templates/login.html 與注冊(cè)頁(yè)面 templates/register.html 幾乎完全相同,除了 title 標(biāo)簽不一樣。請(qǐng)參考對(duì) templates/register.html 的解釋。

3. 調(diào)用后端服務(wù) static/script.js

文件 script.js 定義了調(diào)用后端服務(wù)的 Ajax 函數(shù),由如下部分構(gòu)成:

3.1 配置 Ajax

function ajaxError()
{
    alert('ajax error');
}

function ajaxSuccess(result)
{
    if (result.error) {
        alert('操作失敗');
        return;
    }
    location.reload();
}

客戶端使用 ajax 技術(shù)請(qǐng)求服務(wù)端的服務(wù)。當(dāng) ajax 請(qǐng)求失敗時(shí),調(diào)用 ajaxError,提示用戶 ajax 請(qǐng)求服務(wù)失??;當(dāng) ajax 請(qǐng)求成功時(shí),調(diào)用 ajaxSuccess,提示用戶 ajax 請(qǐng)求服務(wù)成功。

3.2 新增待做事項(xiàng)

function onAddTodo(button)
{
    var children = $(button).parent().children();
    var title = children.eq(0).val();
    var data = JSON.stringify({'title': title});
    
    $.ajax({
        'url': '/todos/add',
        'type': 'POST',
        'contentType': 'application/json',
        'data': data,
        'dataType': 'json',
        'error': ajaxError,
        'success': ajaxSuccess
    });
}

點(diǎn)擊 “新增” 按鈕后,執(zhí)行函數(shù) onAddTodo(button),button 指向的是 “新增” 按鈕。在 templates/index.html 中,按鈕、待做事項(xiàng)位于相同的 DIV 中,如下所示:

  <div>
    <input type="text" class="row" placeholder="輸入待辦事項(xiàng)">
    <i class="fa fa-fw fa-plus-square" onclick='onAddTodo(this);'></i>
  </div>

在第 3 行到第 4 行,表達(dá)式的含義如下所示:

表達(dá)式 含義
$(button).parent() 指向按鈕的父節(jié)點(diǎn)
$(button).parent().children() 表示 div 的 2 個(gè)子節(jié)點(diǎn)
children.eq(0) 指向待做事項(xiàng)的文本框
children.eq(0).val() 待做事項(xiàng)的文本框的值

在第 7 行,通過(guò) JQuery 的 ajax 函數(shù)調(diào)用后端服務(wù),設(shè)置 url 為 ‘/todos/add’、type 為 ‘POST’ ,表示新增一條待做事項(xiàng)。

3.3 更新待做事項(xiàng)

function onUpdateTodo(todoId) 
{
    var data = JSON.stringify({'todoId': todoId});
    
    $.ajax({
        'url': '/todos/update',
        'type': 'POST',
        'contentType': 'application/json',
        'data': data,
        'dataType': 'json',
        'error': ajaxError,
        'success': ajaxSuccess
    });
}

當(dāng)用戶完成一個(gè)待做事項(xiàng)后,將待做事項(xiàng)的 status 從 ‘todo’ 更改為 ‘done’。

在第 5 行,通過(guò) JQuery 的 ajax 函數(shù)調(diào)用后端服務(wù),設(shè)置 url 為 ‘/todos/update’、type 為 ‘POST’ ,更新待做事項(xiàng)的 status。

3.4 刪除待做事項(xiàng)

function onDeleteTodo(todoId)
{
    var data = JSON.stringify({'todoId': todoId});
    
    $.ajax({
        'url': '/todos/delete',
        'type': 'POST',
        'contentType': 'application/json',
        'data': data,
        'dataType': 'json',
        'error': ajaxError,
        'success': ajaxSuccess
    });
}

在第 5 行,通過(guò) JQuery 的 ajax 函數(shù)調(diào)用后端服務(wù),設(shè)置 url 為 ‘/todos/delete’、type 為 ‘POST’ ,刪除待做事項(xiàng)。

4. 樣式文件 static/style.css

style.css 是網(wǎng)站的樣式文件,設(shè)置尺寸、字體大小等信息。

body {
    width: 400px;
    margin: auto;
}

a {
    text-decoration: none;
}

.fa {
    cursor: pointer;
}

.login {
    font-size: 80%;
    font-weight: normal;
}

.header {
    padding-top: 8px;
    padding-bottom: 8px;
    font-size: 120%;
    font-weight: bold;
}

.row {
    width: 360px;
    padding-top: 3px;
    padding-bottom: 3px;
    margin-top: 2px;
    margin-bottom: 2px;
}

對(duì)標(biāo)簽 body 設(shè)置,margin: auto 表示將內(nèi)容居中顯示,兩側(cè)的 margin 相等,根據(jù)內(nèi)容的寬度和屏幕的寬度自動(dòng)計(jì)算 margin 的大小。

對(duì)標(biāo)簽 a 設(shè)置,不顯示下劃線。

對(duì) class 等于 fa 的元素設(shè)置,顯示光標(biāo)的形狀為手形。

登錄、注冊(cè)、退出的按鈕的 class 等于 login,顯示的 font-size 為 80%,略小于正常的尺寸。

待做事項(xiàng)和完成事項(xiàng)的 class 等于 row,設(shè)置上下的 padding 和 margin,讓它們互相之間存在一個(gè)間隔。

5. 小結(jié)

本節(jié)講解了前端的實(shí)現(xiàn),使用思維導(dǎo)圖概括如下:

圖片描述