【全栈React】第10天: 交互性
今天,我们将介绍如何添加交互性到我们的应用,使其具有吸引力和交互性。 通过这一点,我们构建了少数几个组件,而没有添加用户交互。 今天我们将要改变它。 用户交互浏览器是事件驱动的应用程序。 用户在浏览器中进行的一切都会触发一个事件,从点击按钮,甚至只是移动鼠标。 在简单的JavaScript中,我们可以监听这些事件并附加一个JavaScript函数与它们进行交互。 例如,我们可以使用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>';
})
}
这导致以下行为: 将鼠标移到该文本上 然而,在React中,我们不必在原始JavaScript中与浏览器的事件循环进行交互,因为React为我们使用 例如,要从React上面的(相当不起眼的)演示中收听 <div onMouseMove={(evt) => console.log(evt)}>
Move the mouse
</div>
React提供了很多 要看看其中的一些在行动中,以下是一些小的演示,一些 我们将在我们的应用中使用 我们_想要_的交互是在用户点击搜索图标时显示搜索。 回想一下,我们的 class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
searchVisible: false
}
}
// toggle visibility when run on the state
showSearch() {
this.setState({
searchVisible: !this.state.searchVisible
})
}
render() {
// Classes to add to the <input /> element
let searchInputClasses = ["searchInput"];
// Update the class array if the state is visible
if (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>
<input
type="text"
className={searchInputClasses.join(' ')}
placeholder="Search ..." />
{/* Adding an onClick handler to call the showSearch button */}
<div
onClick={this.showSearch.bind(this)}
className="fa fa-search searchIcon"></div>
</div>
)
}
}
当用户点击 我们让这个组件有状态(它需要跟踪搜索字段是否应该显示)。 我们可以使用 class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
searchVisible: false
}
}
// ...
}
当用户点击按钮时,我们将要更新状态来表示 我们创建这个方法来绑定我们的点击事件: class Header extends React.Component {
// ...
showSearch() {
this.setState({
searchVisible: !this.state.searchVisible
})
}
// ...
}
最后,我们可以在icon元素上附加一个点击处理程序(使用 class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
searchVisible: false
}
}
// toggle visibility when run on the state
showSearch() {
this.setState({
searchVisible: !this.state.searchVisible
})
}
render() {
// Classes to add to the <input /> element
let searchInputClasses = ["searchInput"];
// Update the class array if the state is visible
if (this.state.searchVisible) {
searchInputClasses.push("active");
}
return (
<div className="header">
<div className="fa fa-more"></div>
<span className="title">
{this.props.title}
</span>
<input
type="text"
className={searchInputClasses.join(' ')}
placeholder="Search ..." />
{/* Adding an onClick handler to call the showSearch button */}
<div
onClick={this.showSearch.bind(this)}
className="fa fa-search searchIcon"></div>
</div>
)
}
}
尝试点击搜索图标并观看输入字段出现并消失(动画效果由CSS动画处理)。 输入事件无论何时在React中构建表单,我们将使用React提供的输入事件。最值得注意的是,我们最常使用 我们更新我们的搜索框演示,以便在更新时捕获搜索字段内的文本。每当一个 使用这个属性,我们可以捕捉到我们这个字段的价值。 让我们创建一个新的子组件来包含一个 我们创建一个我们称之为 class SearchForm extends React.Component {
// ...
constructor(props) {
super(props);
this.state = {
searchText: ''
}
}
// ...
}
现在,我们已经在 class SearchForm extends React.Component {
// ...
render() {
const { searchVisible } = this.state;
let searchClasses = ['searchInput']
if (searchVisible) {
searchClasses.push('active')
}
return (
<form className='header'>
<input
type="search"
className={searchClasses.join(' ')}
onChange={this.updateSearchInput.bind(this)}
placeholder="Search ..." />
<div
onClick={this.showSearch.bind(this)}
className="fa fa-search searchIcon"></div>
</form>
);
}
}
请注意,我们在我们的 我们定义 class SearchForm extends React.Component {
static propTypes = {
onSubmit: React.PropTypes.func.isRequired,searchVisible: React.PropTypes.bool
}
// ...
}
现在我们在 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'>
<input
type="search"
className={searchClasses.join(' ')}
onChange={this.updateSearchInput.bind(this)}
placeholder="Search ..." />
<div
onClick={this.showSearch.bind(this)}
className="fa fa-search searchIcon"></div>
</form>
);
}
}
当我们键入字段时,将会调用
class SearchForm extends React.Component {
// ...
updateSearchInput(e) {
const val = e.target.value;
this.setState({
searchText: val
});
}
// ...
}
到目前为止,我们无法真正提交表单,所以我们的用户无法真正搜索。 我们来改变一下 我们需要将 我们来更新 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)}>
<input
type="search"
className={searchClasses.join(' ')}
onChange={this.updateSearchInput.bind(this)}
placeholder="Search ..." />
</form>
);
}
}
现在当我们键入 那么好的,我们可以提交表单和内容,但是什么时候我们实际上进行搜索?为了演示目的,我们将把搜索文本传递给父子组件链,以便
为了将搜索功能传递给链,我们的“SearchForm”将需要接受在提交表单时调用的函数。我们来定义一个我们称之为 class SearchForm extends React.Component {
static propTypes = {
onSubmit: React.PropTypes.func.isRequired,searchVisible: React.PropTypes.bool
}
// ...
static defaultProps = {
onSubmit: () => {},searchVisible: false
}
// ...
}
当表单提交时,我们可以直接从 class SearchForm extends React.Component {
// ...
submitForm(event) {
// prevent the form from reloading the entire page
event.preventDefault();
// call the callback with the search value
this.props.onSubmit(this.state.searchText);
}
}
现在,当用户按下enter时,我们可以通过我们的 我们可以在我们的 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 state
showSearch() {
this.setState({
searchVisible: !this.state.searchVisible
})
}
render() {
// Classes to add to the <input /> element
let searchInputClasses = ["searchInput"];
// Update the class array if the state is visible
if (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>
<SearchForm
searchVisible={this.state.searchVisible}
onSubmit={this.props.onSubmit} />
{/* Adding an onClick handler to call the showSearch button */}
<div
onClick={this.showSearch.bind(this)}
className="fa fa-search searchIcon"></div>
</div>
)
}
}
export default Header
现在我们有一个搜索表单组件,可以在我们的应用中使用和重用。 当然,我们还没有搜索任何东西。 我们来解决这个问题,实现搜索。 [](#implementing-search)实现搜索要在我们的组件中实现搜索,我们希望将搜索责任从我们的 首先,让我们实现一个从 在 class Header extends React.Component {
// ...
}
Header.propTypes = {
onSearch: React.PropTypes.func
}
在 class Header extends React.Component {
// ...
submitForm(val) {
this.props.onSearch(val);
}
// ...
}
Header.propTypes = {
onSearch: React.PropTypes.func
}
回到我们在第7天构建的 由于 无论如何,我们的 class Panel extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,// <~ set loading to false
activities: data,filtered: data,}
}
componentDidMount() {this.updateData();}
componentWillReceiveProps(nextProps) {
// Check to see if the requestRefresh prop has changed
if (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.state
const filtered = activities.filter(a => a.actor && a.actor.login.match(txt))
this.setState({
filtered
})
}
}
// Call out to github and refresh directory
updateData() {
this.setState({
loading: false,activities: data
},this.props.onComponentRefresh);
}
render() {
const {loading,filtered} = this.state;
return (
<div>
<Header
onSubmit={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) => (
<ActivityItem
key={activity.id}
activity={activity} />
))}
</div>
</div>
)
}
}
我们更新我们的状态以包括一个 class Panel extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,searchFilter: '',activities: []
}
}
}
为了实际处理搜索,我们需要将 class Panel extends React.Component {
// ...
// after the content has refreshed,we want to
// reset the loading variable
onComponentRefresh() {this.setState({loading: false});}
handleSearch(val) {
// handle search here
}
render() {
const {loading} = this.state;
return (
<div>
<Header
onSearch={this.handleSearch.bind(this)}
title="Github activity" />
<Content
requestRefresh={loading}
onComponentRefresh={this.onComponentRefresh.bind(this)}
fetchData={this.updateData.bind(this)} />
</div>
)
}
}
我们在这里所做的就是添加一个 为了_实现_搜索,我们需要跟踪这个字符串,并更新我们的 class Panel extends React.Component {
// ...
handleSearch(val) {
this.setState({
searchFilter: val,loading: true
});
}
// ...
}
最后,我们更新我们的 class SearchableContent extends React.Component {
// ...
this.setState({loading: true},this.updateData);
// ...
}
虽然这可能看起来很复杂,但它实际上几乎与我们现有的 所有的 随着 尝试搜索 现在我们有一个3层应用组件来处理嵌套子组件的搜索。我们通过这个post从初级阶段跳到了中级阶段。靠着自己。这是一些重大的材料。确保你明白这一点,因为我们会经常使用我们今天介绍的这些概念。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
