81022fa8b671fbf27d095361df0e4906.png

引言

React 可以说是近些年最热门的前端框架啦, 并且非常非常的好用 ~

很多的国外公司比如 Netflix、Feedly、Airbnb 都是用它来实现的网站主页。

那么 React 到底是个什么呢?它其实是一个为数据提供渲染为HTML视图的开源JavaScript 库。传说最早起源于Facebook 的内部项目,由于太好用了,就开源给大家使用了。

现在国内的很多公司都在招聘会 React 的前端工程师。说明如果会这项技术还是会很吃香哒。

那么我们应该怎么学习它呢?

它的官方文档当然是一个选择 ~

里面有官方人员给出的最严谨的定义和最全的方法解释,一步一步跟着学的话应该也能学会。

不过,稍显有那么点点枯燥啦。

想要更好玩的学习方法,不妨找个小项目来上手吧。

因为根据认知心理学的理论,学习的最好方法之一就是应用 ~

在“做中学” 会比单纯的 “看概念” 更记忆深刻哦 ~

我之前在初步学习 react 的时候,有小试牛刀,

做了一个机器人 ️网站,网址在这里:https://rocky-hamlet-79784.herokuapp.com/ 。

教程在此:https://zhuanlan.zhihu.com/p/296727460

今天想教大家一个升级版!!!一个可以有用户的人脸识别网站~

效果展示

https://wenjia-smartbrain.herokuapp.com/ (后端部分还没完全搭建好)

由于教程篇幅过长,将会分成四个部分:前端篇、后端篇、数据库篇 和 部署篇。

跟着我一起动手,不仅能掌握 react 框架的基本使用,还能拥有一个可以被访问的网站哦~~

前端篇

思路梳理

前端的页面想设计成这样:

378b390ec57d9893b8f5d7a43e8f289d.png

首页可以拆分成3个元素, 分别是登录、注册、导航栏。

那就每个元素为一个组件。

登录后的页面:

aaa7094ee92d0585c761f93811da8ad2.png

可以拆分成5 个组件。除去导航栏,还有logo、搜索框、排名区、面部识别功能区。

每个组块存储在一个文件夹 内, 而所有的模块都放在模块文件夹下, 像这样

b600f39109563288d2a116e7f851bca3.png

创造好的 component,可以在app.js中以 以下的形式被引用 。

Tips:app.js中的多个 components 要放在 <div></div> 里面哦。

​
function App() {
  return (
    <div>
       <Navigation />
       <Logo /> 
        <ImageLinkForm/>
        <FaceRecognition />
        ... 省略了其他组件们...
​
    </div>
​
  );
}
​

功能实现

讲完了思路,那我们就来动手写吧 ~

注册, 登录功能

css

因为要花好多时间调试好看的样式,而样式会根据项目的不同而进行很大的调整。

所以这里具体样式就直接给大家了,就不用花太多时间纠结样式了。

感兴趣的可以去找我的源码康康。

目前只要安装一个好用的插件 tachyons 就可咯。

npm install tachyons
npm tachyons
​

Index.js 导入

import "tachyons";

页面

App.js

功能: 没登入之前是注册页面, 登录之后是搜索图片页面。

实现: constructor()

Tips: jsx语法: html 里加了{ } 就可以写 js 了。

constructor(){
    super()
    this.state = {
      input: "",
      route: "signin"
    }
  }
​
​
render() {
    return (
      <div className="App">
         <Navigation />
         { this.state.route === "signin"
          ?  <div>< Signin /></div>
          :  <div> 
            <Logo /> 
            <Rank />
            <ImageLinkForm onInputChange={this.onInputChange} onButtonSubmit={this.onButtonSubmit}/>
            <FaceRecognition />
            <Particles className="particles"
                  params={particleOptions}
                /></div>
         }   
      </div>
  
    );
    }
  }
   
​

同理,新建 register 页面。

// 新增代码
 <div className="mt3">
                <label className="db fw6 lh-copy f6" htmlFor="name">Name</label>
                <input
                  className="pa2 input-reset ba bg-transparent hover-bg-black hover-white w-100"
                  type="text"
                  name="name"
                  id="name"
                  onChange={this.onNameChange}
                />
              </div>

页面跳转

设置

constructor(){
    super()
    this.state = {
      input: "",
      route: route
      // route: "signin"
    }
  }
  
  
  onRouteChange = (route) => {
    this.setState({route: route});
  }
​
render() {
    return (
      <div className="App">
         <Navigation onRouteChange = {this.onRouteChange}/>
         { this.state.route === "signin"
          ?  <div>
              <Signin />
              <Particles className="particles"
                    params={particleOptions} />
              </div>
          :  <div> 
              <Logo /> 
              <Rank />
              <ImageLinkForm onInputChange={this.onInputChange} onButtonSubmit={this.onButtonSubmit}/>
              <FaceRecognition />
              <Particles className="particles"
                    params={particleOptions}
                /></div>
         }   
      </div>
  
    );
    }

添加思路: 需要跳转到什么页面, onRouteChange(param)}, param就写什么参数。

Tips: 千万别忘了在函数头传参 {onRouteChange} !!!!!

Navigation.js (signout button)

onClick={({onRouteChange}) => onRouteChange("signin")}

Signin.js

// 千万别忘了传参 {onRouteChange} !!!!!
// 箭头函数:render的时候不调用这个函数,只有当onClick的时候才调用
//            onClick = {() => onRouteChange("rankpage")}
            
     <div class="">
            <input 
            // 箭头函数:render的时候不调用这个函数,只有当onClick的时候才调用
            onClick = {() => onRouteChange("rankpage")}
            className="b ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib" 
            type="submit" 
            value="Sign in" />
            </div>
            <div class="lh-copy mt3">
            <a onClick = {() => onRouteChange("register")} href="#0" className="f6 link dim black db">Register</a>
                        </div>       
            

Register

<input 
  // 箭头函数:render的时候不调用这个函数,只有当onClick的时候才调用
  onClick = {() => onRouteChange("signin")}
  className="b ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib" 
  type="submit" 
  value="Register" />
  </div>

上传照片并识别

Step 1. 输入框,按钮框对于输入的识别

App.js 设置 state,并渲染

constructor(){
    super()
    this.state = {
      input: ""
    }
  }
​
  onInputChange = (event) => {
    console.log(event.target.value);
  }
​
  onButtonSubmit = () => {
    console.log("click");
  }
  
render() {
    return (
      <div className="App">
  
          <ImageLinkForm onInputChange={this.onInputChange} onButtonSubmit={this.onButtonSubmit}/>
         
      </div>
  
    );
    }  

ImageLinkForm.js

传参,用参

 <input className="f4 pa2 w-70 center" type="text" onChange={onInputChange}/>
  <button className="w-30 grow f4 link ph3 pv2 dib white bg-light-purple" 
                    onClick = {onButtonSubmit}>Detect</button>
            

step 2. 能上传图片

调用人家已经做好的api

clarifai (https://www.clarifai.com/)

注册一个账户就能免费用了

(未完待续...)

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐