在React中构建一个可扩展的随机报价应用程序

发布于:2021-02-05 11:55:20

0

113

0

react javascript freecocodecamp 初学者

辅助项目和实际应用对于程序员来说是非常令人着迷的术语,但是构建辅助项目并不是小菜一碟,我们必须先构建一些项目才能获得一定的专业知识,然后再开始自己的项目。Freecodecamp在这方面非常有帮助。因此,今天我们将使用React解决freecodecamp的Random Quote Machine挑战。

让我们先计划一下应用程序

我们将这个小应用程序分为两个步骤。

在第一步中,我们将在单个组件中设计整个应用程序。一旦它将实现的目的,我们将进入第二步,并将应用程序分为小的独立组件,这将是有益的,如果应用程序在未来变得更大。

组件设置

在编写任何逻辑之前,我们将设置组件,并用quote和author值初始化state对象。值暂时将是空字符串。

import React, { Component } from 'react' class RandomQuote extends Component {    constructor(props) {       super(props)       this.state = {          quote: '', //for quote          author: '' //for author       }    }    render() {       return (          <div id='wrapper'>             <h1 className='title'>Random Quote App</h1>          </div>       )    } } export default RandomQuote

API请求包

我们将使用axios进行API请求。它基于承诺,使Api请求更简单、更简短、更简洁。

我们将在componentDidMount生命周期方法中调用我们的API

你可能会想为什么?

所以在这里我们首先要明确一个概念,有些新手可能没有意识到这一点。

概念

在我们基于类的组件中,我们有一些预定义的方法,每个方法都有特定的特性和执行时间。


import React, { Component } from 'react'; class App extends Component {   constructor(props) {     super(props)     console.log('constructor runs')   }   componentDidMount() {     console.log('componentDidMount runs')   }   render() {     console.log('render method runs')     return (       <div>         <h1>Hello</h1>       </div>     );   } } export default App;

在componentDidMount中调用API

所以我们看到componentDidMount在默认呈现方法之后运行。所以它是API调用的最佳场所。

componentDidMount() {       this.getQuote()    }    getQuote() {       let url = 'https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json'       axios.get(url)          .then(res => console.log(res))    }

如果我们检查,我们可以看到控制台中的API数据。这意味着我们成功地调用了API。

现在我们将用setState属性更改state对象,并使quote和author值等于我们从api获得的一些数据。

是时候写点逻辑了。

逻辑1:从API中随机选择一个报价

如果我们能找出如何从数组中得到一个随机元素,我们就可以为此编写逻辑。我们有一个引号数组,它作为一个元素进一步包含引号和作者键。

我们知道,为了在Javascript中获得随机数,我们使用内置的Math.random()函数,并且为了从特定长度获得数据,我们将像这样扩展它

Math.floor(Math.random() * data.length)

Math.floor()只是将数字向下舍入到最接近的整数。

这将给我们从0到数组长度的随机数,我们将它存储在变量quoteNum中。

如果把quoteNum当作一个索引怎么办?我们将从引号数组中获得一个随机元素。

import React, { Component } from 'react' import axios from 'axios' class RandomQuote extends Component {    constructor(props) {       super(props)       this.state = {          quote: '',          author: ''       }    }    componentDidMount() {       this.getQuote()    }    getQuote() {       let url = 'https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json'       axios.get(url)          .then(res => {             let data = res.data.quotes             let quoteNum = Math.floor(Math.random() * data.length) //quote number             let randomQuote = data[quoteNum] //actual quote             this.setState({                quote: randomQuote['quote'],                author: randomQuote['author']             })          })    }    getNewQuote = () => {       this.getQuote()    }    render() {       const { quote, author } = this.state       return (          <div id='wrapper'>             <h1 className='title'>Random Quote App</h1>             <div id='quote-box'>                <div id='text'><p>{quote}</p></div>                <div id='author'><h5>{author}</h5></div>             </div>          </div>       )    } } export default RandomQuote

你会发现,应用程序运行后,你会在几毫秒内看不到数据,因为从api获取数据需要时间。

一旦请求成功,它将使用setStatestate中存储新值,我们的DOM将用新数据更新。

造型

我们需要做三件事

  1. 设计背景

  2. 设计报价框

  3. 设计按钮

这篇文章不是关于造型的。如果你什么都不懂,你可以在评论区问。

我已经添加了媒体查询,以便在小屏幕时做出响应。

@import url('https://fonts.googleapis.com/css?family=Josefin+Sans|K2D'); body {   background: linear-gradient(90deg, lightgreen, lightblue);   font-family: 'K2D', sans-serif;   display: flex;   justify-content: center;   align-items: center;   height: calc(100vh - 100px);   overflow-y: hidden; } .title {   text-align: center;   font-weight: 500; } #quote-box {   width: 400px;   margin: 0 auto;   padding: 1px 15px;   font-weight: 550;   font-size: 22px;   background: linear-gradient(35deg, #CCFFFF, #FFCCCC);   text-align: center;   border-radius: 20px;   box-shadow: 0px 0px 2px 1px gray; } #text p {   margin-block-start: 0.5em;   margin-block-end: 0.5em; } #author h5 {   margin-block-start: 1em;   margin-block-end: 1em; } #buttons {   display: flex;   justify-content: space-between; } .twitter-icon {   color: #1DA1F2 } .button {   font-family: 'K2D', sans-serif;   font-weight: 500;   font-size: 1rem;   padding: 5px;   border-radius: 50em;   box-shadow: 0px 0px 3px .5px rgb(82, 81, 81);   border: 0;   margin-bottom: 10px; } .button:focus {   outline: none;   border: none; } @media only screen and (max-width: 450px) {   .title {     font-size: 22px;   }   #quote-box {     width: 270px;   } }

我们完成了第一步。

让我们来谈谈扩展应用程序

记住,我们总是以一种更易于增长、阅读和维护的方式来构建我们的项目。

可重复使用的报价框

假设我们希望以后向应用程序添加更多屏幕/路由,并且我们希望使用相同的报价框,但使用不同的文本/数据。因此,我们将为此制作一个单独的组件报价箱。我们将使用新的报价和共享按钮执行类似的操作。

// Quote Box component const QuoteBox = ({ quote, author }) => { //destructuring    return (       <React.Fragment>          <div id='text'><p>{quote}</p></div>          <div id='author'><h5>{author}</h5></div>       </React.Fragment>    ) }

在这里,我们通过以下方式从RandomQuote组件获取作者和报价值props.

可重复使用按钮

假设这是一个客户项目,他改变了主意,要求你不要有一个新的报价按钮,他想有两个按钮,一个用于下一个报价,一个用于上一个报价。

因此,最好是制作一个可重复使用的按钮,我们将在任何需要相同按钮的地方使用按钮组件。

//Button component const Button = ({ onClick, title }) => {    return (       <button className='button' id='new-quote' onClick={onClick}>{title}</button>    ) }

可重复使用的共享按钮

如果我们以后想添加Facebook、Instagram和whatsapp共享怎么办。他们将共享相同的样式,但不同的props。因此最好将其写入一个单独的文件中,这样便于维护。

// Social Share component const TwitterShare = ({ quote, author }) => {    return (       <React.Fragment>          <a href={`https://twitter.com/intent/tweet?text= ${quote} ${author}`} target="_blank" title="Post this quote on twitter!" id='tweet-quote'>             <i className="fab fa-twitter twitter-icon" />          </a>       </React.Fragment>    ) }

这就是我们的随机报价类的样子,现在不是更干净了吗?

class RandomQuote extends Component {    constructor(props) {       super(props)       this.state = {          quote: '',          author: ''       }    }    componentDidMount() {       this.getQuote()    }    getQuote() {       let url = 'https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json'       axios.get(url)          .then(res => {             let data = res.data.quotes             let quoteNum = Math.floor(Math.random() * data.length)             let randomQuote = data[quoteNum]             this.setState({                quote: randomQuote['quote'],                author: randomQuote['author']             })          })    }    getNewQuote = () => { //will be called on clicking the New Quote button       this.getQuote()    }    render() {       const { quote, author } = this.state       return (          <div id='wrapper'>             <h1 className='title'>Random Quote App</h1>             <div id='quote-box'>                <QuoteBox quote={quote} author={author} /> //passing data via props to QuoteBox component                <div id='buttons'>                   <TwitterShare quote={quote} author={author} />                   <Button id='new-quote' title='New Quote' onClick={this.getNewQuote} />                </div>             </div>          </div>       )    } }

这篇文章有点长,希望你能跟着学点新东西。