Castie!

正态分布, 优劣伴生

北冥有鱼,其名为鲲(kūn)。鲲之大,不知其几千里也;化而为鸟,其名为鹏。鹏之背,不知其几千里也;怒而飞,其翼若垂天之云。是鸟也,海运则将徙于南冥。南冥者,天池也。


北海若曰:“井鼃不可以语于海者,拘于虚也;夏虫不可以语于冰者,笃于时也;曲士不可以语于道者,束于教也。今尔出于崖涘,观于大海,乃知尔丑,尔将可与语大理矣。

Web 使用fetch请求后端服务

上篇我们使用了ssm构建了我们简历的服务, 这篇我们从前端的视角进行网络请求, 对于react就要讲讲fetch这个库的使用, 对于vue就要讲讲axios这个库, 对于axios之前已经讲过, 这篇就来讲讲fetch的使用.

参考链接:

以下内容在上述文章基础上进行, 请事先查阅.

安装fetch

当然说到fetch, 其实就是对于ajax的一个封装, 类似于iOS的AFNetworking, 首先我们先从npm 加载这个库.

$ npm instaill fetch --save

在开始进行网络请求之前, 我们需要和后端定义好接口以及返回的数据, 当然如果是前后端一起开发的话, 就没有这个困扰了.

查阅fetch文档

文档链接

Usage synopsis (use the argument links to find out more):

fetch(url, options).then(function(response) {
  // handle HTTP response
}, function(error) {
  // handle network error
})
More comprehensive usage example:

fetch(url, {
  method: "POST",
  body: JSON.stringify(data),
  headers: {
    "Content-Type": "application/json"
  },
  credentials: "same-origin"
}).then(function(response) {
  response.status     //=> number 100–599
  response.statusText //=> String
  response.headers    //=> Headers
  response.url        //=> String

  return response.text()
}, function(error) {
  error.message //=> String
})

自行封装fetch

像我们在iOS中使用第三方库的时候回在其基础上封装一层, 以便日后维护方便, 对于前端, 设计思想也是一样的, 我们就来新建一个http.js来封装网络请求和接口.

const host = 'http://localhost:8080';

export function GET(url) {
    var fetchOptions = {
        method: 'GET'
    };
    return new Promise((resolve, reject) => {
        fetch(url, fetchOptions).then(response => response.json()).then(response => resolve(response.data)).catch((error) => {
            reject(error);
        })
    });
}

export const URL = {
    fetchProfile: `${host}/portal/fetch_profile.do`,
    fetchProjects: `${host}/portal/fetch_projects.do`,
    fetchGitHub: `${host}/portal/fetch_github.do`,
    fetchArticles: `${host}/portal/fetch_articles.do`,
    fetchExperience: `${host}/portal/fetch_experience.do`,
    fetchContact: `${host}/portal/fetch_contact.do`
}

非常简单的在fetch的基础上使用Promise进行封装, 并将所需要的接口整合到一起以便日后的维护.

查看接口

为例完成下图的展示, 我们已经通过ssm写好了这个接口.

我们就以第一个接口举例fetchProfile: ${host}/portal/fetch_profile.do`,如果你对es6模板字符串的语法不熟悉的话, 可以自行搜索下, 我们先来看看这个接口的返回.

/* http://localhost:8080/portal/fetch_profile.do */
{
    "status": 0,
    "data": {
        "profileImage": "http://upload-images.jianshu.io/upload_images/1229762-23e162b9bd6b9c39.JPG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
        "profileName": "Shuangquan Zhu",
        "profileCareer": "Designer / Developer",
        "profileLocation": "Shanghai",
        "profileSocialList": [
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-877e3e5c2260bcf1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "https://github.com/coderzsq"
            },
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-f6525252f3e8387b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "http://www.jianshu.com/u/9d7fad1a4693"
            },
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-a69614a97de93f36.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "http://upload-images.jianshu.io/upload_images/1229762-453920a3f4eedcd8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"
            },
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-91b0949aec719aab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "http://coderzsq.github.io/"
            }
        ],
        "profileSummaryTitle": "Summary",
        "profileSummaryDescription": "Shuangquan Zhu is a professional developer who focuses on iOS now. He has strong knowledge of Objective-C, Swift and Javascript. With these skills, he created quite a few quickly developer tools. He also leads the J1 iOS team to promote the project process.\\nHe crazy loves playing basketball with friends in spare time, He also loves traveling, writing and listening music. He is always willing to try new things, and keeping to learn from them.",
        "profileInterestTitle": "Interest",
        "profileInterestList": [
            {
                "interest": "Learn about high tech"
            },
            {
                "interest": "Play basketball"
            },
            {
                "interest": "Listen to music"
            },
            {
                "interest": "Apple products"
            }
        ],
        "profileEducationTitle": "Education",
        "profileEducationList": [
            {
                "major": "Business Management",
                "school": "East China University of Science and Technology",
                "year": "2016"
            },
            {
                "major": "Customs and International Freight",
                "school": "Shanghai Maritime Academy",
                "year": "2013"
            }
        ]
    }
}

这个返回的数据结构已经可以完美匹配上图的数据展示需求了.

如何请求

就以第一个模块举例, 我们打开pc_home.js为例:

构造函数
    constructor() {
        super();
        this.state = {
            data: {
                profileImage: '',
                profileName: '',
                profileCareer: '',
                profileLocation: '',
                profileSocialList: [],
                profileSummaryTitle: '',
                profileSummaryDescription: '',
                profileInterestTitle: '',
                profileInterestList: [],
                profileEducationTitle: '',
                profileEducationList: []
            }
        }
    }

首先我们需要添加构造函数, 字段对应返回的数据结构.

生命周期函数
    componentWillMount() {
        GET(URL.fetchProfile).then((data) => {
            this.setState({data: data})
        })
    }

生命周期函数, 用于页面的请求, 我们可以看到对刚才fetch封装类的调用.

渲染函数
render() {
        const {data} = this.state;
        let profileLocation = data.profileLocation.length ? `Location: ${data.profileLocation}` : ''
        let profileSummaryDescription = data.profileSummaryDescription.split('\\n').map((description, index) => (
            <p key={index}>{description}</p>
        ))
        let profileSocialList = data.profileSocialList.map((socialVo, index) => (
            <div key={index}>
                <a href={socialVo.href}><img src={socialVo.src} alt=""/></a>
            </div>
        ))
        let profileInterestList = data.profileInterestList.map((interestVo, index) => (
            <li key={index}># {interestVo.interest}</li>
        ))
        let profileEducationList = data.profileEducationList.map((educationVo, index) => (
            <dl key={index}>
                <dd>{educationVo.major} - {educationVo.year}</dd>
                <dt>{educationVo.school}</dt>
            </dl>
        ))
        return (
            <div>
                <div styleName="user">
                    <div styleName="user-block">
                        <div styleName="icon">
                            <img src={data.profileImage} alt=""/>
                        </div>
                        <div styleName="row name">
                            {data.profileName}
                        </div>
                        <div styleName="row career">
                            {data.profileCareer}
                        </div>
                        <div styleName="row location">
                            {profileLocation}
                        </div>
                        <div styleName="row social">
                            <div styleName="indent"></div>
                            {profileSocialList}
                        </div>
                    </div>
                </div>
                <div styleName="introduction">
                    <div styleName="main">
                        <div styleName="main-block">
                            <h1>{data.profileSummaryTitle}</h1>
                            {profileSummaryDescription}
                        </div>
                    </div>
                    <div styleName="left">
                        <div styleName="left-block">
                            <h2>{data.profileInterestTitle}</h2>
                            <ul>{profileInterestList}</ul>
                        </div>
                    </div>
                    <div styleName="right">
                        <div styleName="right-block">
                            <h2>{data.profileEducationTitle}</h2>
                            {profileEducationList}
                        </div>
                    </div>
                </div>
            </div>
        )
  }

进行渲染, 我们可以将一些逻辑写在render函数中, 就写法而言react这种用起来是比vue的模板v-for这种更适合有经验的开发者.

这里有一个知识点需要掌握就是当react的jsx需要循环渲染的时候需要在最外面的节点添加key={index}属性.

完整代码

import React, {Component} from 'react';
import CSSModules from 'react-css-modules';
import styles from './pc_home.css';
import {GET, URL} from '../javascripts/http';

@CSSModules(styles, {allowMultiple: true})
export default class PCHome extends Component {

    constructor() {
        super();
        this.state = {
            data: {
                profileImage: '',
                profileName: '',
                profileCareer: '',
                profileLocation: '',
                profileSocialList: [],
                profileSummaryTitle: '',
                profileSummaryDescription: '',
                profileInterestTitle: '',
                profileInterestList: [],
                profileEducationTitle: '',
                profileEducationList: []
            }
        }
    }

    componentWillMount() {
        GET(URL.fetchProfile).then((data) => {
            this.setState({data: data})
        })
    }

    render() {
        const {data} = this.state;
        let profileLocation = data.profileLocation.length ? `Location: ${data.profileLocation}` : ''
        let profileSummaryDescription = data.profileSummaryDescription.split('\\n').map((description, index) => (
            <p key={index}>{description}</p>
        ))
        let profileSocialList = data.profileSocialList.map((socialVo, index) => (
            <div key={index}>
                <a href={socialVo.href}><img src={socialVo.src} alt=""/></a>
            </div>
        ))
        let profileInterestList = data.profileInterestList.map((interestVo, index) => (
            <li key={index}># {interestVo.interest}</li>
        ))
        let profileEducationList = data.profileEducationList.map((educationVo, index) => (
            <dl key={index}>
                <dd>{educationVo.major} - {educationVo.year}</dd>
                <dt>{educationVo.school}</dt>
            </dl>
        ))
        return (
            <div>
                <div styleName="user">
                    <div styleName="user-block">
                        <div styleName="icon">
                            <img src={data.profileImage} alt=""/>
                        </div>
                        <div styleName="row name">
                            {data.profileName}
                        </div>
                        <div styleName="row career">
                            {data.profileCareer}
                        </div>
                        <div styleName="row location">
                            {profileLocation}
                        </div>
                        <div styleName="row social">
                            <div styleName="indent"></div>
                            {profileSocialList}
                        </div>
                    </div>
                </div>
                <div styleName="introduction">
                    <div styleName="main">
                        <div styleName="main-block">
                            <h1>{data.profileSummaryTitle}</h1>
                            {profileSummaryDescription}
                        </div>
                    </div>
                    <div styleName="left">
                        <div styleName="left-block">
                            <h2>{data.profileInterestTitle}</h2>
                            <ul>{profileInterestList}</ul>
                        </div>
                    </div>
                    <div styleName="right">
                        <div styleName="right-block">
                            <h2>{data.profileEducationTitle}</h2>
                            {profileEducationList}
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

学会一个接口请求, 对于其他的就是复制黏贴的重复劳动了, 这样这个简历项目的完整性又有了进一步的提升, 接下来的发展方向是制作一个后台服务, 敬请期待.

About:

点击下方链接跳转!!

🌟 项目源码 请点这里🌟 »> 喜欢的朋友请点喜欢 »> 下载源码的同学请送下小星星 »> 有闲钱的壕们可以进行打赏 »> 小弟会尽快推出更好的文章和大家分享 »> 你的激励就是我的动力!!

最近的文章

iOS 移动端架构初探心得

本文作为这一系列的收尾总结, 详细叙述了这个架构工具的设计思路以及一步步的优化, 在此也分享与你, 完整keynote可查阅github参考链接: Hybird 搭建零耦合架构从MVC开始 Hybird 搭建后端Koa.js并过度到MVVM Hybird 搭建前端Vue.js并升级至MVP Hybird 搭建路由Router实现组件化 Hybird 搭建客户端实时降级架构 iOS 执行.py脚本生成解耦架构 iOS 执行.py脚本生成UI层结构 iOS 移动端面向文档开...…

移动开发继续阅读
更早的文章

Server 使用Spring来构建服务

刚才一篇我们提到了如何入门后端, 我也知道一篇文章是不可能完成后端的方方面面的, 期望达到的是知道如何进行学习, 有一条清晰的学习路径, 少绕弯路. 这篇我们就来进行简历的接口开发了.参考链接: Server 入门后端你要学什么以下内容在上述文章基础上进行, 请事先查阅.jdbc 代码生成首先我们要做的就是使用mybatis插件进行读取数据库数据并生成jdbc代码.generatorConfig.xml<?xml version="1.0" encoding="UTF-8"?&...…

后端开发继续阅读