本文主要是介绍30天入坑React ---------------day10 Interactivity,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这篇文章是30天React系列的一部分 。
在本系列中,我们将从非常基础开始,逐步了解您需要了解的所有内容,以便开始使用React。如果您曾经想学习React,那么这里就是您的最佳选择!
下载免费的PDF
互动
在Github上编辑此页面
今天,我们将介绍如何为我们的应用程序添加交互性,使其具有吸引力和动态性。
通过这一点,我们构建了少数几个组件,而没有增加太多的用户交互。今天,我们要改变这一点。
用户互动
浏览器是一个事件驱动的应用程序。用户在浏览器中执行的所有操作都会触发事件,从单击按钮到甚至只是移动鼠标。在纯的JavaScript中,我们可以监听这些事件并附加的JavaScript函数来与它们进行交互。
例如,可以我们mousemove
使用JS 将函数附加到浏览器事件:
export const go = () => {const ele = document.getElementById('mousemove');ele.innerHTML = 'Move your mouse to see the demo';ele.addEventListener('mousemove', function(evt) {const { screenX, screenY } = evt;ele.innerHTML = '<div>Mouse is at: X: ' +screenX + ', Y: ' + screenY +'</div>';})
}
这导致以下功能:
移动鼠标以查看演示
在阵营中,我们不必在原始的JavaScript中与浏览器的事件循环交互,因为阵营为我们提供了一种处理事件的方法props
。
例如,mousemove
要从React上面的(相当不起眼的)演示中监听事件,我们将设置prop onMouseMove
(注意事件名称的camelcasing)。
<div onMouseMove={(evt) => console.log(evt)}>Move the mouse over this text
</div>
反应了提供很多最props
我们可以设置来监听不同的浏览器事件,例如点击,触摸,拖动,滚动,选择事件等等(参阅请事件文档以电子杂志所有这些事件的列表)。
要查看其中的一些实际操作,的英文以下props
我们可以传递给我们的元素的一些小_ECSHOP演示。列表中的每个文本元素都会设置它列出的道具。尝试使用列表并查看在元素中如何调用和处理事件(所有事件都在文本上设置,而不是列表项):
将我们在onClick
整个应用程序中使用支柱相当多,所以熟悉它是个好主意。在我们的活动列表标题中,我们有一个搜索图标,我们还没有连接到显示搜索框。
我们想要的交互的英文<input />
在用户点击搜索图标种植时显示搜索。回想一下,的我们Header
组件的英文这样实现的:
class Header extends React.Component {constructor(props) {super(props);this.state = {searchVisible: false}}// toggle visibility when run on the stateshowSearch() {this.setState({searchVisible: !this.state.searchVisible})}render() {// Classes to add to the <input /> elementlet searchInputClasses = ["searchInput"];// Update the class array if the state is visibleif (this.state.searchVisible) {searchInputClasses.push("active");}return (<div className="header"><div className="menuIcon"><div className="dashTop"></div><div className="dashBottom"></div><div className="circle"></div></div><span className="title">{this.props.title}</span><inputtype="text"className={searchInputClasses.join(' ')}placeholder="Search ..." />{/* Adding an onClick handler to call the showSearch button */}<divonClick={this.showSearch.bind(this)}className="fa fa-search searchIcon"></div></div>)}
}
用户当单击该<div className="fa fa-search searchIcon"></div>
元素时,我们将要运行一个函数来更新组件的状态,以便searchInputClasses
更新对象。使用onClick
处理程序,这非常简单。
让我们使这个组件有状态(它需要跟踪搜索字段是否应该显示)。我们可以使用constructor()
函数将我们的组件转换为有状态:
class Header extends React.Component {constructor(props) {super(props);this.state = {searchVisible: false}}// ...
}
的英文什么
constructor
功能?在JavaScript的中,该
constructor
函数的英文在创建³³对象时运行的函数。它返回对创建实例的对象函数的引用prototype
。简单来说,构造函数是在JavaScript的运行时创建新对象时运行的函数。我们将使用构造函数方法在对象上设置实例变量,因为它在创建对象时正确运行。
使用
ES6
类语法创建³³对象时,必须我们super()
在任何其他方法之前调用该方法。调用该super()
函数调用父类的constructor()
函数。我们将使用相同的参数调用它,我们因为调用constructor()
了类的函数。
当用户单击该按钮时,将我们要更新状态以表示该searchVisible
标志已更新。由于我们希望用户能够在<input />
第二次单击搜索图标种植后关闭/隐藏字段,因此将我们e月刊状态而不是将其设置为真。
让我们创建这个方法来绑定我们的单击事件:
class Header extends React.Component {// ...showSearch() {this.setState({searchVisible: !this.state.searchVisible})}// ...
}
最后,我们可以onClick
在icon元素上附加一个单击处理程序(使用prop)来调用我们的新showSearch()
方法。我们Header
组件的整个更新源代码如下所示:
class Header extends React.Component {constructor(props) {super(props);this.state = {searchVisible: false}}// toggle visibility when run on the stateshowSearch() {this.setState({searchVisible: !this.state.searchVisible})}render() {// Classes to add to the <input /> elementlet searchInputClasses = ["searchInput"];// Update the class array if the state is visibleif (this.state.searchVisible) {searchInputClasses.push("active");}return (<div className="header"><div className="fa fa-more"></div><span className="title">{this.props.title}</span><inputtype="text"className={searchInputClasses.join(' ')}placeholder="Search ..." />{/* Adding an onClick handler to call the showSearch button */}<divonClick={this.showSearch.bind(this)}className="fa fa-search searchIcon"></div></div>)}
}
尝试单击搜索图标并观察输入字段的显示和消失(动画效果由CSS动画处理)。
输入事件
每当我们在React中构建表单时,我们将使用React提供的输入事件。最值得注意的是,我们最常使用onSubmit()
和onChange()
道具。
让我们更新我们的搜索框演示,以便在更新时捕获搜索字段内的文本。每当一个<input />
字段具有onChange()
prop设置时,它将在每次字段改变时调用该函数。当我们点击它并开始输入时,将调用该函数。
使用此prop,我们可以捕获我们州的字段值。
我们不是更新我们的<Header />
组件,而是创建一个包含<form />
元素的新子组件。通过将表单处理职责移动到它自己的表单,我们可以简化<Header />
代码,当我们的用户提交表单时,我们可以调用标题的父级(这是通常的React模式)。
让我们创建一个我们称之为的新组件SearchForm
。这个新组件是一个有状态组件,因为我们需要保持搜索输入的值(跟踪它的变化):
class SearchForm extends React.Component {// ...constructor(props) {super(props);this.state = {searchText: ''}}// ...
}
现在,我们已经在<Header />
组件中编写了表单的HTML ,所以让我们从Header
组件中获取它并从我们的SearchForm.render()
函数返回它:
class SearchForm extends React.Component {// ...render() {const { searchVisible } = this.state;let searchClasses = ['searchInput']if (searchVisible) {searchClasses.push('active')}return (<form className='header'><inputtype="search"className={searchClasses.join(' ')}onChange={this.updateSearchInput.bind(this)}placeholder="Search ..." /><divonClick={this.showSearch.bind(this)}className="fa fa-search searchIcon"></div></form>);}
}
请注意,我们在我们的<input />
领域丢失了样式。由于我们searchVisible
的新组件中不再具有状态,因此我们不能再使用它来设置样式<input />
。但是,我们可以从我们的Header
组件传递一个prop,它告诉SearchForm
将输入呈现为可见。
让我们定义searchVisible
prop(PropTypes
当然使用)并更新render
函数以使用新的prop值来显示(或隐藏)搜索<input />
。我们还将字段可见性的默认值设置为false(因为我们的Header
显示/隐藏它很好):
class SearchForm extends React.Component {static propTypes = {onSubmit: PropTypes.func.isRequired,searchVisible: PropTypes.bool}// ...
}
现在我们将样式返回到<input />
元素上,让我们添加用户在搜索框中键入的功能,我们将要捕获搜索字段的值。我们可以通过将onChange
prop添加到<input />
元素并向其传递函数来实现此工作流程,以便每次<input />
更改元素时调用它。
class SearchForm extends React.Component {// ...updateSearchInput(e) {const val = e.target.value;this.setState({searchText: val});}// ...render() {const { searchVisible } = this.state;let searchClasses = ['searchInput']if (searchVisible) {searchClasses.push('active')}return (<form className='header'><inputtype="search"className={searchClasses.join(' ')}onChange={this.updateSearchInput.bind(this)}placeholder="Search ..." /><divonClick={this.showSearch.bind(this)}className="fa fa-search searchIcon"></div></form>);}
}
当我们输入字段时,updateSearchInput()
将调用该函数。我们将通过更新状态来跟踪表单的价值。在updateSearchInput()
函数中,我们可以直接调用this.setState()
以更新组件的状态。
该值保存在
event
对象的目标上event.target.value
。
class SearchForm extends React.Component {// ...updateSearchInput(e) {const val = e.target.value;this.setState({searchText: val});}// ...
}
受控制与不受控制
我们正在创建所谓的不受控制的组件,因为我们没有设置
<input />
元素的值。我们现在无法对输入文本值进行任何验证或后处理。如果我们想要验证字段或操纵
<input />
组件的值,我们必须创建所谓的受控组件,这实际上只意味着我们使用value
prop 传递一个值。受控组件版本的render()
功能如下所示:class SearchForm extends React.Component {render() {return (<inputtype="search"value={this.state.searchText}className={searchInputClasses}onChange={this.updateSearchInput.bind(this)}placeholder="Search ..." />);} }
截至目前,我们无法实际提交表单,因此我们的用户无法真正搜索。让我们改变这一点。我们要将<input />
组件包装在<form />
DOM元素中,以便我们的用户可以按回车键提交表单。我们可以通过使用元素onSubmit
上的prop 来捕获表单提交<form />
。
让我们更新render()
函数以反映这一变化。
class SearchForm extends React.Component {// ...submitForm(e) {e.preventDefault();const {searchText} = this.state;this.props.onSubmit(searchText);}// ...render() {const { searchVisible } = this.props;let searchClasses = ['searchInput']if (searchVisible) {searchClasses.push('active')}return (<form onSubmit={this.submitForm.bind(this)}><inputtype="search"className={searchClasses.join(' ')}onChange={this.updateSearchInput.bind(this)}placeholder="Search ..." /></form>);}
}
我们马上打电话
event.preventDefault()
给这个submitForm()
功能。这会阻止浏览器冒泡事件,这会导致整个页面的默认行为重新加载(浏览器提交表单时的默认功能)。
现在,当我们输入<input />
字段并按Enter键时,将submitForm()
使用事件对象调用该函数。
所以...很好,我们可以提交表格和内容,但我们什么时候才能进行搜索?出于演示的目的,现在,我们会通过搜索文本了亲子部分构成的链,因此Header
可以决定什么搜索。
该
SearchForm
组件当然不知道它在搜索什么,所以我们必须将责任传递给链。我们将使用这个回调策略。
为了将搜索功能传递给链,我们SearchForm
需要接受一个支柱函数来在提交表单时调用。让我们定义一个我们称之为onSubmit
可以传递给我们SearchForm
组件的道具。作为优秀的开发人员,还将我们为此功能添加默认prop
值和a 。由于我们要确保定义,我们将把道具设置为必需的道具:propType
onSubmit
onSubmit()
onSubmit
class SearchForm extends React.Component {static propTypes = {onSubmit: PropTypes.func.isRequired,searchVisible: PropTypes.bool}// ...static defaultProps = {onSubmit: () => {},searchVisible: false}// ...
}
提交表单时,我们可以直接从中调用此函数props
。由于我们在状态中跟踪搜索文本,可以我们使用searchText
状态中的值调用函数,因此onSubmit()
函数只获取值而不需要处理事件。
class SearchForm extends React.Component {// ...submitForm(event) {// prevent the form from reloading the entire pageevent.preventDefault();// call the callback with the search valuethis.props.onSubmit(this.state.searchText);}
}
现在,当用户按下回车键时,可以我们通过我们的组件调用此onSubmit()
函数。props
Header
可以我们SearchForm
在组件中使用这个组件,Header
并将它们传递给我们定义的两个道具(searchVisible
和onSubmit
):
import React from 'react';
import SearchForm from './SearchFormWithSubmit'class Header extends React.Component {constructor(props) {super(props);this.state = {searchVisible: false}}// toggle visibility when run on the stateshowSearch() {this.setState({searchVisible: !this.state.searchVisible})}render() {// Classes to add to the <input /> elementlet searchInputClasses = ["searchInput"];// Update the class array if the state is visibleif (this.state.searchVisible) {searchInputClasses.push("active");}return (<div className="header"><div className="menuIcon"><div className="dashTop"></div><div className="dashBottom"></div><div className="circle"></div></div><span className="title">{this.props.title}</span><SearchFormsearchVisible={this.state.searchVisible}onSubmit={this.props.onSubmit} />{/* Adding an onClick handler to call the showSearch button */}<divonClick={this.showSearch.bind(this)}className="fa fa-search searchIcon"></div></div>)}
}export default Header
现在我们有一个搜索表单组件,可以我们在我们的应用程序中使用状语从句:重用当然,我们实际上还没有搜索任何东西。让我们解决这个问题并实施搜索。
实施搜索
要在我们的组件中实现搜索,需要我们搜索将职责从我们的Header
组件再次传递给我们将调用的容器组件Panel
。
首先,我们让实现从子Panel
容器中的容器到Header
组件的回调到父组件的相同模式。
在Header
组件上,我们让更新propTypes
一个我们将定义为支柱的道具onSearch
:
class Header extends React.Component {// ...
}
Header.propTypes = {onSearch: PropTypes.func
}
在Header
组件的'submitForm()'函数内部,调用此onSearch()
丙我们将传递给它:
class Header extends React.Component {// ...submitForm(val) {this.props.onSearch(val);}// ...
}
Header.propTypes = {onSearch: PropTypes.func
}
请注意,我们的虚拟树看起来像这样:
<Panel><Header><SearchForm></SearchForm></Header> </Panel
当
<SearchForm />
更新时,它会传递它对搜索输入对其父级的更改的感知<Header />
,它将当向上网站传递给<Panel />
组件时,此方法在作出反应程序应用中非常常见,并为我们的组件提供了一组良好的功能隔离。
回到Panel
我们在第7构建天的组件中,将我们函数传递给Header
作为onSearch()
支柱的函数Header
。我们在这里说的是,当提交搜索表单时,我们希望搜索表单回调到标题组件,调用然后Panel
组件来处理搜索。
由于Header
组件不控制内容列表,Panel
组件确实如此,我们必须将责任再提高一级,正如我们在此定义的那样。
无论如何,的我们Panel
组件基本上的英文Content
我们之前处理过的组件的副本:
class Panel extends React.Component {constructor(props) {super(props);this.state = {loading: false, // <~ set loading to falseactivities: data,filtered: data,}}componentDidMount() {this.updateData();}componentWillReceiveProps(nextProps) {// Check to see if the requestRefresh prop has changedif (nextProps.requestRefresh !== this.props.requestRefresh) {this.setState({loading: true}, this.updateData);}}handleSearch = txt => {if (txt === '') {this.setState({filtered: this.state.activities})} else {const { activities } = this.stateconst filtered = activities.filter(a => a.actor && a.actor.login.match(txt))this.setState({filtered})}}// Call out to github and refresh directoryupdateData() {this.setState({loading: false,activities: data}, this.props.onComponentRefresh);}render() {const {loading, filtered} = this.state;return (<div><HeaderonSubmit={this.handleSearch}title="Github activity" /><div className="content"><div className="line"></div>{/* Show loading message if loading */}{loading && <div>Loading</div>}{/* Timeline item */}{filtered.map((activity) => (<ActivityItemkey={activity.id}activity={activity} />))}</div></div>)}
}
我们让我们更新的状态以所有游戏一个searchFilter
字符串,它只是搜索值:
class Panel extends React.Component {constructor(props) {super(props);this.state = {loading: false,searchFilter: '',activities: []}}
}
为了实际处理搜索,我们需要将一个onSearch()
函数传递给我们的Header
组件。让我们onSearch()
在Panel
组件中定义一个函数,并将其传递给函数中的Header
道具render()
:
class Panel extends React.Component {// ...// after the content has refreshed, we want to// reset the loading variableonComponentRefresh() {this.setState({loading: false});}handleSearch(val) {// handle search here}render() {const {loading} = this.state;return (<div><HeaderonSearch={this.handleSearch.bind(this)}title="Github activity" /><ContentrequestRefresh={loading}onComponentRefresh={this.onComponentRefresh.bind(this)}fetchData={this.updateData.bind(this)} /></div>)}
}
在我们这里所做的就是添加一个handleSearch()
函数并将其传递给标题。现在,当用户在搜索框中键入时,将handleSearch()
调用我们Panel
组件上的函数。
实际要实现搜索,需要我们跟踪此字符串并更新我们的updateData()
功能以考虑搜索过滤。首先,我们让设置searchFilter
状态。我们还可以Content
通过设置loading
为真来强制重新加载数据,因此我们可以一步完成:
class Panel extends React.Component {// ...handleSearch(val) {this.setState({searchFilter: val,loading: true});}// ...
}
最后,我们让我们更新的updateData()
功能以考虑搜索。
class SearchableContent extends React.Component {// ...this.setState({loading: true}, this.updateData);// ...
}
虽然这可能看起来很复杂,它但实际上几乎与我们现有的updateData()
函数完全相同,除了我们更新fetch()
查询查询结果以调用filter()
JSON集合上的方法。
所有collection.filter()
函数都运行为每个元素传入的函数,并过滤掉报道查看虚假值的值,保留返回真值的值。我们的搜索功能只是在Github的活动actor.login
(Github的用户)上查找匹配,以查看它是否与该searchFilter
值匹配。
随着updateData()
功能的更新,我们的搜索已经完成。
尝试搜索auser
。
现在我们有一个3层应用程序组件,用于处理嵌套子组件的搜索。我们用这篇文章从初学者跳到中级。拍拍自己的背部。这是一些沉重的材料。请确保您理解这一点,因为我们会经常使用我们今天介绍的这些概念。
在下一节中,我们将跳出来看看构建纯组件。
学习REACT正确的方法
React和朋友的最新,深入,完整的指南。
下载第一章
❮上一个
下一章:
纯组件
这篇关于30天入坑React ---------------day10 Interactivity的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!