每个开发人员必须知道的顶级React库
#javascript #网络开发人员 #编程 #react

React正在接管网络开发的世界,这是有充分理由的。 React由Facebook创建并于2013年发行,是一个开源JavaScript库,用于构建已经彻底改变前端开发的用户界面。

在本针对初学者的综合指南中,我们将介绍您需要知道的所有核心概念,以便与React一起启动并运行。您将学习基本主题,例如:

  • React如何工作以及为什么有用
  • JSX语法
  • 组件,道具和状态
  • 处理事件
  • 虚拟DOM
  • les> les> les> les> live <
  • 使用表格
  • 获取数据
  • Routing

最后,您将对React基本面有一个可靠的掌握,并准备好构建应用程序。让我们开始!

React如何工作

在其核心上,反应都是关于组件的。一个React应用程序包含多个可重复使用的组件,每个组件负责渲染整体UI的一小部分。

例如,您可以拥有一个Navbar组件,侧边栏组件,表单组件等。

每个组件都会管理其内部状态并基于该状态渲染UI。当组件的状态更改时,React将有效地更新并重新渲染需要重新渲染的组件。这要归功于React对虚拟DOM的使用。

虚拟DOM是实际DOM的JavaScript表示。当组件的状态更改时,React将结果的虚拟DOM与以前的虚拟DOM进行比较。

然后,它算出了同步它们所需的最小实际DOM操作集。

这意味着您不必担心自己更改DOM - 反应会自动处理幕后。

这最终允许与传统的JavaScript应用程序手动操纵DOM。

React还利用单向数据流。状态通过道具从父零件传递到子女组件。

当需要更新状态时,它是通过回调函数完成的,而不是直接修改状态。

这种单向数据流使您的应用程序中的状态管理更加容易。它还有助于隔离组件,因为每个组件都与国家的本地副本一起工作,而不是依靠全球状态。

总而言之,这是React的一些关键优势:

  • 声明性 - React使用声明代码来基于状态而不是手动更新DOM的命令代码渲染UI。
  • 基于组件的 - 构建封装的组件来管理自己的状态。
  • 学习一次,在任何地方写下 - 可用于Web,Mobile,VR甚至本地桌面应用程序。
  • 高性能 - 虚拟DOM使反应非常快速有效。

JSX语法

React使用称为JSX的JavaScript的语法扩展来描述UI的外观。 JSX看起来像HTML和JavaScript的组合:

const element = <h1>Hello, world!</h1>;

此语法被处理到标准的JavaScript函数调用和对象中。 Babel通常在React Apps中用于将JSX代码转换为常规JavaScript,浏览器可以理解。

一个关键区别是JSX使用className而不是添加CSS类的类,因为类是JavaScript中的一个保留单词。

您可以通过用卷曲括号包裹JSX代码中的任何有效的JavaScript表达式:

const name = 'John';
const element = <h1>Hello, {name}</h1>;

JSX元素可以像HTML元素一样具有属性。但是,您不能使用类似类和类似的关键字,因为它们是在JavaScript中保留的。相反,react dom组件期望诸如htmlfor和className之类的属性:

const element = &lt;div className="container"&gt;
  &lt;label htmlFor="name"&gt;Enter name:&lt;/label&gt;
  &lt;input id="name" /&gt;
&lt;/div&gt;</code></pre>
You can also nest child elements inside a parent JSX element:
<pre><code class="language-javascript">const element = (
  &lt;div&gt;
    &lt;h1&gt;I am the title&lt;/h1&gt;
    &lt;p&gt;This is a paragraph&lt;/p&gt;
  &lt;/div&gt;
)

JSX允许我们编写看起来像HTML的标记,还可以让我们在该标记中使用JavaScript的全部功能。这就是使反应对UI开发如此有用的原因。

组件,道具和状态

组件是任何React应用程序的构件。组件是一个独立的UI件,可封装标记和逻辑。

这是一个简单按钮组件的示例:

function Button(props) {
  return &lt;button&gt;{props.text}&lt;/button&gt;;
}

此功能接受道具作为参数,访问道具上的文本属性,然后返回显示按钮元素的JSX。

组件可以是函数或类。功能组件更简单,因为它们只需要接收道具并返回JSX。

有一个组件后,您可以通过将JSX传递给ReactDOM.render()
将其渲染

const root = document.getElementById('root');
ReactDOM.render(
  &lt;Button text="Click me"/&gt;,
  root
);

组件可以嵌套在其他组件中以构建复杂的UI:

function App() {
  return (
    &lt;div&gt;
      &lt;Button text="Save" /&gt;
      &lt;Button text="Cancel" /&gt;
    &lt;/div&gt;
  )
}

道具是数据传递到组件的方式。它们是不变的,不应在组件内更改。

状态保存可以随时间变化的数据,从而触发UI更新。创建组件时应初始化状态:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 0};
  }
}

只能使用setState()修改状态:

this.setState({count: this.state.count + 1});

调用setState()触发器会反应以新状态值重新渲染组件。这是React如何使UI与数据同步。

处理事件

用反应元素处理事件类似于用DOM元素处理事件。有一些关键语法差异:

  • 用骆驼而不是小写(OnClick变为onClick)命名的React事件
  • 您将功能作为事件处理程序而不是字符串传递

例如,要处理单击事件:

function Button(props) {
  function handleClick() {
    console.log('Clicked!');
  }
  return &lt;button onClick={handleClick}&gt;Click Me&lt;/button&gt;
}

请注意,HandleClick是一种普通的JS函数,包含您要在单击元素时要运行的任何代码。

您还可以绑定构造函数中的事件处理程序:

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {

    // event handler logic

  }
  render() {
    return &lt;button onClick={this.handleClick}&gt;Click Me&lt;/button&gt;
  }
}

绑定呼叫创建了一个新函数,该函数范围为组件实例。这使您可以访问道具并在处理程序内正确陈述道具。

您也可以将自定义参数传递给事件处理程序:

<button onClick={() => this.handleClick(id)} />

这对于传递元素或其他数据的ID很有用。

虚拟dom

使React如此性能的核心功能之一是使用虚拟DOM。

让我们考虑UI更新如何在没有虚拟DOM的情况下工作。当状态发生变化时,React必须操纵实际的DOM才能直接更改渲染内容。对于具有较大DOMS和频繁更新的应用程序,这可能很慢。

相反,React在内存中保持UI的轻量级虚拟表示。该虚拟DOM是React组件和实际DOM之间的抽象层。

当状态在组件中发生变化时,React通过组合应用程序的组件树来创建一个新的虚拟DOM树。

然后将新的虚拟DOM与先前的虚拟DOM进行比较。此过程称为“分散”。

反应准确地算出了哪些虚拟DOM节点通过此扩散过程发生了变化。最后,React仅更新实际DOM中的那些更改的DOM节点。

由于虚拟DOM可以快速更新而无需触摸真实的DOM,因此性能得到显着提高。

React必须只对真实DOM进行有针对性的更新,而不是从头开始重新渲染所有内容。这使得重新渲染过程更快,更有效。

开发人员根本不必考虑虚拟DOM。这是完全由React处理的实现细节。但是,了解其在引擎盖下的工作方式可以帮助解释React的性能优势。

在React 16.8中引入了钩子以使用状态,而功能组件中的其他React特征则引入。

在挂钩之前,功能组件只能根据其道具渲染UI - 它们缺乏像只有类组件的状态这样的能力。

挂钩允许功能组件做所有类都可以做的事情,除了上下文和生命周期方法之类的功能。一些常用的内置钩子包括:

usestate:将状态添加到功能组件:

import { useState } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  return (
    &lt;div&gt;
      &lt;p&gt;You clicked {count} times&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
        Click me
      &lt;/button&gt;
    &lt;/div&gt;
  );
}

使用效果:添加了从功能组件中执行副作用的能力:

import { useState, useEffect } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  useEffect(() =&gt; {
    document.title = You clicked ${count} times;
  });
  return ( 
    //...
  )
}

usecontext:从函数组件中消耗上下文:

const ThemeContext = React.createContext('light');
function Button() {
  const theme = useContext(ThemeContext);
  return (
    &lt;button className={theme}&gt;OK&lt;/button&gt;
  );
}

与内置的钩子一起,您可以创建自定义钩以共享可重复使用的逻辑。

使用表格

反应中的形式处理涉及:

  • 将状态添加到跟踪表单输入值
  • 聆听输入上的变更事件以更新该状态
  • 渲染以设置输入值时从状态访问值

例如:

class Form extends React.Component {
  state = {name: ''};
  handleChange = (e) =&gt; {
    this.setState({name: e.target.value})
  }
  render() {
    return (
      &lt;&gt;
        &lt;input 
          value={this.state.name}
          onChange={this.handleChange} 
        /&gt;
        &lt;p&gt;{this.state.name}&lt;/p&gt;
      &lt;/&gt;
    )
  }
}

受控的与不受控制的组件

React表格可以使用受控或不受控制的组件:

  • 控制:由React状态处理的值
  • 不受控制的:DOM本身处理的值

使用不受控制的组件,您使用refs来访问dom输入值,而不是直接访问状态。

处理多个输入

您可以分别跟踪每个输入的状态:

state = {
  name: '',
  email: '' 
};
handleNameChange = (e) =&gt; {
  this.setState({name: e.target.value});
}
handleEmailChange = (e) =&gt; {
  this.setState({email: e.target.value});  

}


render() {
  return (
    &lt;&gt;
      &lt;input 
        value={this.state.name}
        onChange={this.handleNameChange}
      /&gt; 
      &lt;input
        value={this.state.email}
        onChange={this.handleEmailChange}
      /&gt;
    &lt;/&gt;
  )
}

或将状态作为一个对象管理:

state = {

  formData: {

    name: '',

    email: ''

  }

};


handleChange = (e) =&gt; {

  this.setState({

    formData: {

      ...this.state.formData,

      [e.target.name]: e.target.value

    } 

  });

}


render() {

  return (

    &lt;&gt;

     &lt;input 

       name="name"

       value={this.state.formData.name}

       onChange={this.handleChange}

     /&gt;

     // ...

    &lt;/&gt;

  )

}

这使用计算的属性名称仅更新formdata中的一个密钥。

处理提交

使用一个防止默认提交的提交处理程序,然后调用函数来处理表单值:

handleSubmit = (e) =&gt; {
  e.preventDefault();
  this.processForm();
}
processForm() {

  // send data to server  

}
render() {
  return (
    &lt;form onSubmit={this.handleSubmit}&gt;
      // inputs 
      &lt;button&gt;Submit&lt;/button&gt;
    &lt;/form&gt;
  )
}

验证

有诸如Formik之类的库可以帮助验证。您也可以在提交时进行验证:

handleSubmit = (e) =&gt; {

  e.preventDefault();

  // validate form 

  if(valid) { 

    this.processForm();

  }

}

通过以状态跟踪用户向用户显示验证错误。

获取数据

使用效果挂钩可用于在安装和状态更改上获取数据:

function MyComponent() {
  const [data, setData] = useState(null);
  useEffect(() =&gt; {
    fetch('/some-api')
      .then(res =&gt; res.json())
      .then(setData);
  }, []); // empty deps = only on mount
  //...
}

空阵列意味着此效果只能在安装座上,而不是在重新租户上运行。

您也可以在状态更改中获取:

useEffect(() =&gt; {
  // refetch data
}, [someStateVar]);

现在,如果有变化,它将重新运行。

  • 处理加载状态

获取时,数据将为null。您可以跟踪状态:

const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() =&gt; {
  setLoading(true);
  fetchData().then(data =&gt; {
    setData(data);
    setLoading(false);
  })
}, [])

然后在显示数据之前检查加载:

return (
  {loading &amp;&amp; &lt;p&gt;Loading...&lt;/p&gt;}
  {data &amp;&amp; &lt;DisplayData data={data} /&gt;}
)
  • 错误处理

通过添加捕获量来处理错误:

useEffect(() =&gt; {
  setLoading(true);
  fetchData()
    .then(setData)
    .catch(error =&gt; {
      // handle error  
    })
    .finally(() =&gt; setLoading(false))
}, [])

或使用尝试/捕获:

useEffect(() =&gt; {
  const fetchData = async () =&gt; {
    try {
      setLoading(true);
      const data = await fetchData();
      setData(data);
    } catch (error) {
      // handle error
    } finally {
      setLoading(false); 
    }
  }
  fetchData();
}, [])

跟踪错误状态要显示给用户。

路由

用于在React中进行路由,通常使用React路由器库。

首先,用组件包装组件。

然后使用<链接>创建链接而不是锚标记:

<Link to="/about">About</Link>

并使用<路由>定义路由:

<Route exact path="/" component={Home} />
<Route path="/about" component={About} />

完全匹配路径完全是“ /".

路由组件接收历史,位置和匹配道具。

匹配路由的组件将渲染。

路由器可以使用推动和替换进行导航:

history.push('/about')

路由参数:

&lt;Route path="/user/:id" component={User} /&gt;

// User component

const { id } = this.props.match.params;</code></pre>
Query strings:
<pre><code class="language-javascript">&lt;Link to="/posts?sortBy=newest" /&gt;

// Get search string

const { search } = this.props.location;

// ?sortBy=newest


// Parse with query-string pkg 

import queryString from 'query-string';

const { sortBy } = queryString.parse(search); 

// newest

嵌套路线:

&lt;Route path="/users" component={Users}&gt;
  &lt;Route path=":id" component={User} /&gt;
&lt;/Route&gt;

重定向:

<Redirect from="/old-path" to="/new-path" />

有条件:

&lt;Route 
  path="/dashboard"
  render={() =&gt; (
    loggedIn ? (
      &lt;Dashboard /&gt;  
    ) : (
      &lt;Redirect to="/login" /&gt;
    )
  )}
/&gt;

处理404:

&lt;Switch&gt;
  &lt;Route exact path="/" /&gt;
  &lt;Route component={NotFound} /&gt; 
&lt;/Switch&gt;

编程导航:

const history = useHistory();
history.push('/login');

结论

涵盖了React的核心基础知识!有了这个基础,您应该准备开始构建应用程序。

关键要点包括:

  • React全部关于模块化,可重复使用的组件
  • JSX混合HTML和JavaScript宣布UI
  • Props将数据传递到组件中,State拥有随时间变化的数据
  • 虚拟DOM通过最小化DOM更新来提高性能

希望您喜欢阅读本指南,并有动力开始您的Python编程旅程。

如果您发现这篇文章令人兴奋,请在Learnhub Blog上找到更多令人兴奋的帖子;我们编写从Cloud computingFrontend DevCybersecurityAIBlockchain的所有技术。

资源