上节课我介绍了在案例中用axios发送请求,这节课我们来介绍一下List组件的数据展示。

回顾

在开始这节课的内容之前我们来先对上节课的要点做一个简单回顾

  • 解构赋值重命名变量
  • 复习一下ref
  • 回顾一下代理的配置

以上便是上节课的主要要点,接下来我们开始这节课的内容。

数据结构分析

我们在拿到数据做页面展示的时候,第一步我是不是要先看到数据长什么样子啊?我们只有知道数据什么样才能分析怎么去展示用户信息啊。

当然了,在公司的开发过程中,我们的数据结构基本都是前后端在一起协商好了的。但是我们目前是不是根本不知道GitHub会给我们返回什么样的数据?那么我们先来请求看一下数据长什么样子:

image-20220112090151964

首先我们来看,这给我们的是一个对象,里面有 3 个属性,先看第一个incomplete_results属性,这个属性是什么意思呢?这个属性代表了这次结果GitHub给我返回的是不是一个完整的结果,我们看我们获取到的数据中这个属性是false,这就代表我们拿到的不是完整结果,那么为什么呢?因为我们搜索的这个关键词在GitHub上的结果实在太多了,不可能一次性全都给你返回,但是总共有多少,而又返回多少呢?

我们看到了有一个total_count是代表总量有多少个,这里是 18 个,items属性也告诉我们这次返回的数量是 18 个。可能有人要问了,这不是完整的吗?为啥incomplete_results却是false呢?其实这个其实在GitHub的接口中并没有对这个属性做处理,默认就是false

那我们在展开看items里面的每个用户对象:

image-20220112091105420

这里的属性是不是太多了啊,我们不可能说每个属性都说一遍,我们挑我们页面上需要用的东西,首先我们页面上是不是要展示头像?是不是还要有用户名?而且我们还要让头像可以点击跳转到这个用户的主页,那么我们来看应该用什么属性?是不是这三个?

  • avatar_url
  • login
  • html_url

数据存放位置分析

那么好,我们现在第一已经能够拿到数据了,第二我们已经分析出数据中我们需要什么数据了,那么好我们来分析一下数据存放到哪呢?

第一,我们的数据是谁发送请求获取的?是不是Search组件?第二,我们获取到数据之后要交给谁去展示?是不是List组件?Search组件和List组件是什么关系?是不是平级的?那么我们能不能直接通过Seatch组件直接把数据给List?以我们目前的知识面来看是不是不行?那么是不是要通过父组件来中转?父组件是谁?是不是App组件?那么好,我们是不是要把数据存放在App组件中?

既然在App组件中存数据,而数据是App组件的子组件给的,是不是要App组件提供一个入口函数给子组件?话分两头,App组件中哪里可以存数据呢?是不是stateprops以及自身属性啊?我们说过props是只读的,我们只能通过组件标签传入,不能在组件内部以任何形式修改,那么props是不是我们就不考虑了?因为我们是从子组件拿数据的啊,子组件不可能给父组件的组件标签传props的啊。那么自身属性行不行呢?我们是不是要把数据展示到页面上啊?所以说当我们搜索之后是不是要触发页面更新的啊?自身属性能驱动页面更新吗?不能啊,那我们就只能选state了啊。

数据交互

我们上面已经分析过了,我们要把数据存放在App组件的state中,而且还要提供一个入口函数给Search组件,用于Search组件来更新App组件的state。那么好,我们来看一下:

export default class App extends Component {
  state = { users: [] };

  saveUsers = users => this.setState({ users });

  render() {
    return (
      <div className="container">
        <Search saveUsers={this.saveUsers} />
        <List />
      </div>
    )
  }
}

我们的App组件既然要用state来存放数据,那么是不是就要初始化state?给定一个属性是users而且是个空数组。

然后我们要定义一个入口函数啊,还记不记得TodoList案例中的结论?state在哪,修改state的方法就在哪,所以我们定义入口函数也一定是在App组件中的。那么好,我们看我们定义了一个saveUsers方法,这个方法接收users参数,这个参数就是一个数组,然后我们来修改state,而我们接收的参数和state中的属性重名,所以可以简写。

最后我们在渲染子组件的时候,通过Search组件标签属性将入口函数传给了Search组件。

那么我们初始化了state而且也提供了入口函数并传给了Search组件,那么在Search组件中我们就要来调用这个方法啊:

export default class Search extends Component {
  render() {...}
  search = () => {
    const { value: keyword } = this.user;
    axios.get(`http://localhost:3000/api1/search/users?q=${keyword}`).then(
      response => { this.props.saveUsers(response.data.items); },
      error => { console.log(error); }
    )
  };
}

这就简单了,其他的都不用边,我们之前请求成功是把我们的数据打印到控制台上,现在我们不需要打印了,那么我们就调用props中收到的saveUsers函数来把数据存到App组件的state中去啊,但是我们state中的users属性是不是一个数组啊?而数据中的items属性刚好就是一个数组,那么我们直接把这个items属性传给saveUsers函数就可以了,那么我们来看一下效果吧:

image-20220112094607561

我们在搜索之前,我们的stateusers属性是一个空数组,那么我们来搜索一下再看:

image-20220112094730068

这一次数据是不是来了?那么好,数据我们是拿到了,但是还没有展示到页面上啊。我们接下来是不是就要把state中的users传给List组件啊?那么好,AppList是什么关系?是不是父子关系?App是父组件,List是子组件,父组件给子组件传数据怎么传?是不是直接通过props就行了?那么我们来处理一下:

// App 组件
export default class App extends Component {
  state = { users: [] };

  saveUsers = users => this.setState({ users });

  render() {
    const { users } = this.state;
    return (
      <div className="container">
        <Search saveUsers={this.saveUsers} />
        <List users={users}/>
      </div>
    );
  }
}
// List 组件
export default class List extends Component {
  render() {
    const { users } = this.props;
    return (
      <div className="row">
        {
          users.map(userObj => (
            <div className="card">
              <a href={userObj.html_url} target="_blank" rel="noreferrer">
                <img alt="head-pic" src={userObj.avatar_url} 
                  style={{ width: "100px" }} />
              </a>
              <p className="card-text">{userObj.login}</p>
            </div>
          ))
        }
      </div>
    );
  }
}

我们来看一下代码,首先App组件中没有什么可说的,就是把users传给了List组件,那么List组件中呢,我们先是解构赋值拿到了users,然后遍历数组来生成我们的固定结构。那么我们来看一下效果吧:

image-20220112100042927

最初始肯定是什么都没有,因为我们初始化的state是个空数组,那么我们来搜索一下看看:

image-20220112100151034

数据也都出来了,展示也没有问题,来看一下控制台:

image-20220112100313551

页面展示倒是没有任何问题。但是控制台里面是不是有一个错误警告啊?告诉我们没有设置唯一的key,那么我们设一个呗?那么我们用什么来做key?我们回想一下我们的数据:

image-20220112091105420

这个数据中是不是有一个id属性啊?那我们用id来做key不就行了嘛

image-20220112100626937

这次再来看,就没有刚才的警告了。

以上便是我们List组件展示的内容

总结

  • 平级组件共用的数据存放在公共父组件的state
  • 遍历一定要加上唯一性key

Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.

Link of this article:https://work.lynchow.com/article/github_search_show_data/