zoukankan      html  css  js  c++  java
  • react 项目实战(二)创建 用户添加 页面 及 fetch请求 json-server db.json -w -p 8000

    1.安装 路由

    npm install -S react-router@3.x

    2.新增页面

    我们现在的应用只有一个Hello React的页面,现在需要添加一个用于添加用户的页面。

    首先在/src目录下新增一个pages目录,用于存放渲染页面的组件。

    然后在/src/pages中新增一个UserAdd.js文件。

    在这个文件中写入一个基本的React组件:

    import React from 'react';
    
    // 添加用户组件
    class UserAdd extends React.Component {
      // 渲染
      render() {
        return (
          <div>User add page.</div>
        );
      }
    }
    
    // 向外暴露
    export default UserAdd;

    3.配置路由

    我们需要使用react-router提供的路由组件来控制当前路由下页面应该渲染的组件。

    修改/src/index.js为:

    // 配置路由
    import React from 'react';
    import ReactDOM from 'react-dom';
    // 引入react-router
    import { Router, Route, hashHistory } from 'react-router';
    import UserAddPage from './pages/UserAdd'
    
    // 渲染
    ReactDOM.render((
      <Router history={hashHistory}>
      	<Route path="/user/add" component={UserAddPage} />
      </Router>
    ), document.getElementById('root'));
    

    打开浏览器的http://localhost:3000发现页面一片空白,在控制台中可以看到一个错误信息: 

    这是因为我们只配了一个/user/add的路由,我们来访问一下http://localhost:3000/#/user/add看看 

    新页面出来了。现在需要把上面的那个错误干掉:新建一个主页,并在主页中添加一个链接链到添加用户的页面。

    还是在/src/pages/中新建一个Home.js,写入代码:

    import React from 'react';
    import { Link } from 'react-router';
    
    class Home extends React.Component {
      render () {
        return (
          <div>
            <header>
              <h1>Welcome</h1>
            </header>
    
            <main>
              <Link to="/user/add">添加用户</Link>
            </main>
          </div>
        );
      }
    }
    
    export default Home;

    然后在/src/index.js中添加一个指向Home的Route:

    // 配置路由
    import React from 'react';
    import ReactDOM from 'react-dom';
    // 引入react-router
    import { Router, Route, hashHistory } from 'react-router';
    import HomePage from './pages/Home';
    import UserAddPage from './pages/UserAdd';
    
    // 渲染
    ReactDOM.render((
      <Router history={hashHistory}>
      	<Route path="/" component={HomePage} />
      	<Route path="/user/add" component={UserAddPage} />
      </Router>
    ), document.getElementById('root'));
    

    首页已经可以正常访问了,并且点击添加用户也正确地跳转到了添加用户页面。

    Q: 为什么我看到的url里有一个’#’? 
    A: 这是由于我们给Router组件传入了hashHistory,url中’#’及’#’以后的部分属于hash,hash的变化并不会引起页面的重新刷新,而hashHistory会监听hash的变化使得Router组件能够根据url渲染出正确的组件。除了hash History之外还有browserHistory和memoryHistory。使用browserHistory可以让url变得像标准的url一样(没有#),但是需要在后端做一些特殊处理;memoryHistory是用于做服务端渲染时使用的。

    Q: 为什么Home.js里要用Link组件而不是一个标准的a标签? 
    A: 上面说了,我们使用了hashHistory,正确的页面url中应该都是有一个’#’的,如果直接使用a标签,你需要这么写:<a href=”/#/user/add”>添加用户</a>。但是如果我们想要换成browserHistory,就需要把所有标签中的’#’去掉。使用react-router提供的Link组件可以让我们无视history之间的差异性,直接写标准的路由”/user/add”就可以了。此外,由于我们写的是单页面应用(SPA),Link组件会阻止页面的跳转(仅仅只是改变了url,然后改变了渲染的组件)。

    4.编写页面

    我们定义了User的结构为:

    {
      "id": 10000,
      "name": "一韬",
      "age": 25,
      "gender": "male"
    }
    

    在新建的时候,我们需要使用post方式将新用户的name、age、gender发送给接口http://localhost:3000/user,因此这个添加用户的页面需要提供一个包含上述3个字段控件的表单:

    src / pages / UserAdd.js

    import React from 'react';
    
    // 添加用户组件
    class UserAdd extends React.Component {
      // 构造器
      constructor(props) {
        super(props);
        // 定义初始化状态
        this.state = {};
      }
      
      render() {
        return (
          <div>
            <header>
              <div>添加用户</div>
            </header>
    
            <main>
              <form>
                <label>用户名:</label>
                <input type="text" />
                <br />
                <label>年龄:</label>
                <input type="number" />
                <br />
                <label>性别:</label>
                <select>
                  <option value="">请选择</option>
                  <option value="male">男</option>
                  <option value="female">女</option>
                </select>
                <br />
                <br />
                <input type="submit" value="提交" />
              </form>
            </main>
          </div>
        );
      }
    }
    
    export default UserAdd;
    

    现在我们的页面是这个样子: 

    获取表单的值

    现在我们可以在表单中填写数据了,但是还不能获取到我们输入的值。

    在React中处理表单有些不一样,由于React提倡“单向数据流”,React中的表单并不提供双向数据绑定的功能,我们需要给表单绑定它的value,然后提供一个onChange的处理方法来更新value的值。

    这里我们使用组件的state来维护表单的值,在onChange的时候使用setState来更新值,最后,在表单提交事件被触发的时候,我们输出state来观察最终获得的表单值:

    src / pages / UserAdd.js

    import React from 'react';
    
    // 添加用户组件
    class UserAdd extends React.Component {
      // 构造器
      constructor(props) {
        super(props);
        // 定义初始化状态
        this.state = {
          name: '',
          age: 0,
          gender: ''
        };
      }
      // 输入框改变事件
      handleValueChange(field, value, type='string') {
        // 由于表单的值都是字符串,我们可以根据传入type为number来手动转换value的类型为number类型
        if(type === 'number'){
          value = + value;
        }
        // 设置状态值
        this.setState({
          [field]: value
        });
      }
      // 按钮提交事件
      handleSubmit(e){
        // 阻止表单submit事件自动跳转页面的动作
        e.preventDefault();
        alert(JSON.stringify(this.state));
      }
      
      render() {
        // 定义常量
        const {name, age, gender} = this.state;
        return (
          <div>
            <header>
              <div>添加用户</div>
            </header>
    
            <main>
              <form onSubmit={(e) => this.handleSubmit(e)}>
                <label>用户名:</label>
                <input
                  type="text"
                  value={name}
                  onChange={(e) => this.handleValueChange('name', e.target.value)} />
                <br />
                <label>年龄:</label>
                <input
                  type="number"
                  value={age || ''}
                  onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} />
                <br />
                <label>性别:</label>
                <select
                  value={gender}
                  onChange={(e) => this.handleValueChange('gender', e.target.value)}>
                  <option value="">请选择</option>
                  <option value="male">男</option>
                  <option value="female">女</option>
                </select>
                <br />
                <br />
                <input type="submit" value="提交" />
              </form>
            </main>
          </div>
        );
      }
    }
    
    export default UserAdd;
    

    在页面中填写表单,点提交后可以看到如下界面:

    调用接口创建用户

    拿到了表单数据,我们离目标已经很近了,就差最后一步:把表单的值通过接口提交

    调用接口可以有很多方法:Ajax、表单提交、fetch。

    由于直接使用表单提交会引起页面的跳转,这不符合我们单页应用的原则。这里我们使用比Ajax更先进易用的fetch。

    修改/pages/UserAdd.js中的handleSubmit方法:

    handleSubmit (e) {
      e.preventDefault();
    
      const {name, age, gender} = this.state;
      fetch('http://localhost:3000/user', {
        method: 'post',
        // 使用fetch提交的json数据需要使用JSON.stringify转换为字符串
        body: JSON.stringify({
          name,
          age,
          gender
        }),
        headers: {
          'Content-Type': 'application/json'
        }
      })
        .then((res) => res.json())
        .then((res) => {
          // 当添加成功时,返回的json对象中应包含一个有效的id字段
          // 所以可以使用res.id来判断添加是否成功
          if (res.id) {
            alert('添加用户成功');
            this.setState({
              name: '',
              age: 0,
              gender: ''
            });
          } else {
            alert('添加失败');
          }
        })
        .catch((err) => console.error(err));
    }
    

    填写表单然后点击提交后,可以看到弹出一个添加成功的提示框:

    /server目录执行json-server db.json -w -p 8000

    打开http://localhost:8000/user查看所有用户列表,发现用户已经被添加进去了:

    至此就完成了基本的添加用户功能~

    注:完成的代码 src / pages / UserAdd.js

    import React from 'react';
    
    // 添加用户组件
    class UserAdd extends React.Component {
      // 构造器
      constructor(props) {
        super(props);
        // 定义初始化状态
        this.state = {
          name: '',
          age: 0,
          gender: ''
        };
      }
      // 输入框改变事件
      handleValueChange(field, value, type='string') {
        // 由于表单的值都是字符串,我们可以根据传入type为number来手动转换value的类型为number类型
        if(type === 'number'){
          value = + value;
        }
        // 设置状态值
        this.setState({
          [field]: value
        });
      }
      // 按钮提交事件
      handleSubmit(e){
        // 阻止表单submit事件自动跳转页面的动作
        e.preventDefault();
        // 定义常量
        const { name, age, gender } = this.state;
        // 发送请求
        fetch('http://localhost:8000/user', {
          method: 'post',
          // 使用fetch提交的json数据需要使用JSON.stringify转换为字符串
          body: JSON.stringify({
            name,
            age,
            gender
          }),
          headers: {
            'Content-Type': 'application/json'
          }
        })
        // 强制回调的数据格式为json
        .then((res) => res.json())
        // 成功的回调
        .then((res) => {
          // 当添加成功时,返回的json对象中应包含一个有效的id字段
          // 所以可以使用res.id来判断添加是否成功
          if(res.id){
            alert('添加用户成功!');
            // 初始化
            this.setState({
              name: '',
              age: 0,
              gender: ''
            });
          }else{
            alert('添加用户失败!');
          }
        })
        // 失败的回调
        .catch((err) => console.error(err));
      }
      
      render() {
        // 定义常量
        const {name, age, gender} = this.state;
        return (
          <div>
            <header>
              <div>添加用户</div>
            </header>
    
            <main>
              <form onSubmit={(e) => this.handleSubmit(e)}>
                <label>用户名:</label>
                <input
                  type="text"
                  value={name}
                  onChange={(e) => this.handleValueChange('name', e.target.value)} />
                <br />
                <label>年龄:</label>
                <input
                  type="number"
                  value={age || ''}
                  onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} />
                <br />
                <label>性别:</label>
                <select
                  value={gender}
                  onChange={(e) => this.handleValueChange('gender', e.target.value)}>
                  <option value="">请选择</option>
                  <option value="male">男</option>
                  <option value="female">女</option>
                </select>
                <br />
                <br />
                <input type="submit" value="提交" />
              </form>
            </main>
          </div>
        );
      }
    }
    
    export default UserAdd;

    .

  • 相关阅读:
    JSON序列化选项
    JOSN的stringify()和parse()方法
    html5增强元素--续
    html5页面增强元素
    js继承模式
    js常用设计模式
    js跨浏览器事件处理
    前端兴趣浓厚,后端提不起来兴趣
    padding的讲究
    margin的讲究
  • 原文地址:https://www.cnblogs.com/crazycode2/p/8462237.html
Copyright © 2011-2022 走看看