Slog100_使用React框架進行前端開發11

ArthurSlog

  • ArthurSlog

  • SLog-100

  • Year·1

  • Guangzhou·China

  • October 21th 2018

關注微信公衆號“ArthurSlog”

人生天地之間 若白駒過隙 忽然而已


開發環境MacOS(Mojave 10.14 (18A391))

信息源

開始編碼

  • 本次以‘商城首頁’的公告欄爲例

  • 讓頁面在加載的時候 向服務器發起請求

  • 客戶端請求‘公告欄的數據’

  • 服務端接受到客戶端的請求之後

  • 對請求進行路由 和 處理

  • 然後將結果傳遞給客戶端

  • 具體的邏輯代碼如下:

client/

import React, { Component } from 'react'

// 引入輪播組件
import Carouselarea from './carouselarea/carouselarea'
// 引入配置文件
import Config from '../../../../config.json'
// 引入樣式文件
import './BodyContainer.less'

class BodyContainer extends Component {
    constructor(props) {
        super(props)
        this.state = { bulletinBoard_Text: '' }

        this.recbulletinBoard_Text = this.recbulletinBoard_Text.bind(this)
    }

    render() {
        return <div className='mobile_StoreIndex_BodyContainer'>
            <Carouselarea />
            <div className='bulletinBoard'>
                <div className='bulletinBoardImg'>圖片</div>
                <div className='bulletinBoardBar'>{this.state.bulletinBoard_Text}</div>
            </div>
            <div className='navigationBar'>
                <div className='navigationBarItem'>
                    <div className='navigationBarIconItem'>圖片</div>
                    <div>所有商品</div>
                </div>
                <div className='navigationBarItem'>
                    <div className='navigationBarIconItem'>圖片</div>
                    <div>拼團</div>
                </div>
                <div className='navigationBarItem'>
                    <div className='navigationBarIconItem'>圖片</div>
                    <div>限時促銷</div>
                </div>
                <div className='navigationBarItem'>
                    <div className='navigationBarIconItem'>圖片</div>
                    <div>秒殺</div>
                </div>
            </div>
            <div className='recommendBar'>
                <div className='recommendBarImg'>圖片</div>
                <div>熱銷推薦</div>
            </div>
            <div className='theBestProduct'>
                <div className='theBestProduct_topBar'>
                    <div className='theBestProduct_topBar_title'>鎮店之寶</div>
                    <div className='theBestProduct_topBar_more'>更多</div>
                </div>
                <div className='theBestProductList'>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目1</div>
                    </div>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目2</div>
                    </div>
                </div>
            </div>
            <div className='theBestProduct'>
                <div className='theBestProduct_topBar'>
                    <div className='theBestProduct_topBar_title'>專業工具</div>
                    <div className='theBestProduct_topBar_more'>更多</div>
                </div>
                <div className='theBestProductList'>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目1</div>
                    </div>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目2</div>
                    </div>
                </div>
            </div>
            <div className='theBestProduct'>
                <div className='theBestProduct_topBar'>
                    <div className='theBestProduct_topBar_title'>新品上市</div>
                    <div className='theBestProduct_topBar_more'>更多</div>
                </div>
                <div className='theBestProductList'>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目1</div>
                    </div>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目2</div>
                    </div>
                </div>
            </div>
            <div className='theBestProduct'>
                <div className='theBestProduct_topBar'>
                    <div className='theBestProduct_topBar_title'>力薦專區</div>
                    <div className='theBestProduct_topBar_more'>更多</div>
                </div>
                <div className='theBestProductList'>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目1</div>
                    </div>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目2</div>
                    </div>
                </div>
            </div>
            <div className='theBestProduct'>
                <div className='theBestProduct_topBar'>
                    <div className='theBestProduct_topBar_title'>特惠專區</div>
                    <div className='theBestProduct_topBar_more'>更多</div>
                </div>
                <div className='theBestProductList'>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目1</div>
                    </div>
                    <div className='theBestProductListItem'>
                        <div className='theBestProductListItemImg'>圖片</div>
                        <div className='theBestProductListItemText'>類目2</div>
                    </div>
                </div>
            </div>
            <div className='aboutWe'>
                <div className='aboutWeImg'>圖片(關於我們)</div>
                <div className='shoppingProcess'>圖片(購物流程)</div>
                <div className='customerService'>
                    <div className='customerServiceTitle'>客服在線</div>
                    <div className='customerServiceText'>售前售後的任何問題,請及時聯繫客戶,我們一定妥善爲您解決。如果沒有得到及時的回覆,也不要慌張,我們上線後會第一時間回覆。</div>
                </div>
                <div className='OrderInfo'>
                    <div className='OrderInfoTitle'>訂單信息</div>
                    <div className='OrderInfoText'>我們會按世紀付款順序完成商品發貨、儘快將寶貝呈進您的生活。如遇節假日或特殊天氣,可能會延遲,請您耐心等待。關注公衆號,進入店鋪即可查詢所有訂單及訂單狀態</div>
                </div>
                <div className='tips'>
                    <div className='tipsTitle'>溫馨提示</div>
                    <div className='tipsText'>每款商品的信息、活動、發貨等會有所不用,下單前請務必查看清楚喲~</div>
                </div>
                <div className='others'>
                    <div className='othersList'>
                        <div className='othersListItem'>實物拍攝</div>
                        <div className='othersListItem'>品質保障</div>
                        <div className='othersListItem'>閃電發貨</div>
                    </div>
                    <div className='purchaseNotes'>
                        <div>購買須知</div>
                        <div className='purchaseNotesArrow'>></div>
                    </div>
                </div>
            </div>
            <div className='mobile_personalCenter_bodyContainer_footer'>
                <div className='mobile_personalCenter_bodyContainer_footer_nagivation'>
                    <div>店鋪主頁</div>
                    <div className='mobile_personalCenter_bodyContainer_footer_nagivation_line'></div>
                    <div>推廣中心</div>
                    <div className='mobile_personalCenter_bodyContainer_footer_nagivation_line'></div>
                    <div>關注我們</div>
                    <div className='mobile_personalCenter_bodyContainer_footer_nagivation_line'></div>
                    <div>店鋪信息</div>
                </div>
                <div className='mobile_personalCenter_bodyContainer_footer_companyLogo'>
                    <img src='' alt='公司Logo'></img>
                </div>
            </div>
            <div style={{ marginBottom: '128px' }}></div>
        </div>
    }

    componentDidMount() {
        this.recbulletinBoard_Text()
    }

    recbulletinBoard_Text() {
        const myObj = { func: 1, object: "test" }
        fetch(Config.baseUrl + 'api/client', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(myObj),
        })
            .then(response => {
                console.log('Add data to message successfuly')
                // 這裏獲取到了服務端返回的‘公告欄’的數據 resmsg
                const resmsg = response.json()
                console.log('Response1: ', resmsg)
                console.log('Response2: ', response)
                return resmsg
            })
            .then(resmsg => {
                // 然後 傳值給‘公告欄’
                // 接着 重新渲染(局部渲染)頁面
                // 語法 查一下setState裏怎麼使用對象
                this.setState({
                    bulletinBoard_Text: resmsg
                })
            })
            .catch(err => {
                alert("Error in sending data to server: " + err.message)
            })
    }
}

export default BodyContainer
  • 本次把 樣式獨立出去 代碼看起來清爽一些了

  • 可以看到其中的關鍵部分在於

...
constructor(props) {
    super(props)
    this.state = { bulletinBoard_Text: '' }

    this.recbulletinBoard_Text = this.recbulletinBoard_Text.bind(this)
}
...

...
<div className='bulletinBoard'>
    <div className='bulletinBoardImg'>圖片</div>
    <div className='bulletinBoardBar'>{this.state.bulletinBoard_Text}</div>
</div>
...

...
componentDidMount() {
    this.recbulletinBoard_Text()
}

recbulletinBoard_Text() {
    const myObj = { func: 1, object: "test" }
    fetch(Config.baseUrl + 'api/client', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(myObj),
    })
        .then(response => {
            console.log('Add data to message successfuly')
            // 這裏獲取到了服務端返回的‘公告欄’的數據 resmsg
            const resmsg = response.json()
            console.log('Response1: ', resmsg)
            console.log('Response2: ', response)
            return resmsg
        })
        .then(resmsg => {
            // 然後 傳值給‘公告欄’
            // 接着 重新渲染(局部渲染)頁面
            // 語法 查一下setState裏怎麼使用對象
            this.setState({
                bulletinBoard_Text: resmsg
            })
        })
        .catch(err => {
            alert("Error in sending data to server: " + err.message)
        })
}
...
  • 這裏 func的值等於1 代表了我們發起的是請求‘公告欄’數據的 請求

  • 服務端接收到之後 發現func等於1

  • 就會路由到‘公告欄’處理函數中去

  • 接着把處理好的數據反饋給客戶端

  • 客戶端接到反饋的信息之後

  • 替換state.bulletinBoard_Text的值 然後重新渲染頁面

  • 這樣 我們就得到了最新反饋到的數據 並顯示了出來

  • 下面是後端的代碼

// 這個函數 接收客戶端傳過來的數據 
// 判斷數據裏面是否含有 bootomTabBar的值
// 根據四個bootomTabBar的值 來返回每個基礎界面的數據
// 上面表述的不好理解 下面舉個栗子
// 比如 這個函數 接收到一個數據data data裏面包含有數據‘count’ 和 ‘tabBar’
// 並且‘count’等於1 ‘tabBar’也等於1
// 這代表了 客戶端想要得到的 bootomTabBar數量是一個 想要得到的bootomTabBar是第一個(商城首頁)
// 所以 通過這個函數
// 可以客戶端可以請求到 第一個界面的數據、第二個界面的數據、第三個界面的數據、第四個界面的數據
// {
//     count: int, // 這個就是代表了本次要修改的bootomTabBar的數量
//     tabBar: []  // 這個就是代表了本次要修改的bootomTabBar
// }
//
// 這裏其實還有另一種方式 就是全部的方法統一一個函數
// 具體是這麼做的 例如 app.all('/api/POST', ...
// 那麼 怎麼判斷客戶端請求的是哪個功能呢?
// 是這樣子的 是通過判斷客戶端傳過來的數據data裏面的特定的字段來判斷的
// 可以這麼看 就是根據客戶端傳過來的data裏的‘func’的值 進行路由的
// 路由什麼呢? 路由到指定的功能函數
// 例如 客戶端傳過來的數據data裏的‘func’==01
// 那麼就路由到函數 func1 這個func1函數返回第一個界面的數據
// 如果 ‘func’==02
// 那麼就路由到函數 func2 這個func2函數返回第二個界面的數據
// 以此類推
// 那麼 想要這麼做呢 就需要在後端進行嚴格的檢查判斷 需要一套工業級的機制
// 這麼看來 有點像在寫底層協議了 哈哈
// 包頭+包體 的模式
//
// 客戶端傳過來的數據結構
// {
//     func: int, // 這個就相當於包頭
//     object: [] // 這個就相當於包體
// }
app.all('/api/client', (req, res) => {
    console.log(req.body)
    
    // 首先接收到來自客戶端的數據 並保存在 recDatas對象裏
    const recDatas = req.body
    // 接着 我們約定好的數據結構 就是 包頭+包體
    // 也就是 func + object 這樣的數據結構
    // 所以 首先判斷func的值 然後根據不同的值 執行不同的函數
    switch (recDatas.func) {
        // 這個是前後端接口的測試功能
        case 0:
            console.log('接收到了func等於0的數據')
            res.header("Access-Control-Allow-Origin", "*")
            //res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type")
            //res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
            //res.header("X-Powered-By", ' 3.2.1')
            //res.header("Content-Type", "application/json;charset=utf-8")
            // 這裏 我們把object傳給函數進行處理 同時還需要把res也傳給函數 可以對客戶端做出反饋
            //const results = Func1.func1(recDatas.object)
            //res.json(results)
            //console.log(results)
            break;
        // 這個來寫第一個正式功能
        // 這個寫個什麼功能好?給前端推點界面的數據好了
        // 這個就推給‘商城首頁’裏面‘公告欄’組件的數據好了
        // 首先 把功能寫出來 單獨一個js文件
        case 1:
            console.log('客戶端請求公告欄的數據')
            res.header("Access-Control-Allow-Origin", "*")
            res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type")
            res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
            //res.header("Content-Type", "application/json;charset=utf-8")
            let result = BulletinBoard.ReturnBBInfo(recDatas.object)
            res.json(result)
            break;
        case 2:
            Func1(recDatas.object, res);
            break;
        case 3:
            Func1(recDatas.object, res);
            break;
        case 4:
            Func1(recDatas.object, res);
            break;
        case 5:
            Func1(recDatas.object, res);
            break;
        case 6:
            Func1(recDatas.object, res);
        default:
            res.header("Access-Control-Allow-Origin", "*")
            res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type")
            res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
            //res.header("Content-Type", "application/json;charset=utf-8")
            res.json('error');
    }
})
  • switch裏的寫法有一些語法的問題 不影響結果就不理了

  • 關鍵可以看一下注釋的內容

  • 註釋的內容 解釋了一個業務上的邏輯設計

  • 這次增加了新的判定狀況 用於路由‘公告欄’處理函數

'use strict'

// 來自客戶端的object
// 或者這麼說 來自父級的 object
// 這裏是客戶端向服務端請求‘公告欄’的數據
// So object是空的

function func(object) {

    if (object == null) {
        return `客戶端傳來的值是空的`
    }
    else if (object != null) {
        // 這裏 需要定義‘公告欄’的數據
        return '[歡迎來到ArthurSlogStore]' + '當前時間是: ' + '[' + new Date() + ']'
    }
    else {
        console.log('未知錯誤')
    }
}

module.exports = {
    ReturnBBInfo: func
}

  • 歡迎關注我的微信公衆號 ArthurSlog

關注微信公衆號“ArthurSlog”

  • 如果你喜歡我的文章 歡迎點贊 留言

  • 謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章