【React.js模仿大众点评webapp】实战教程(9)开发搜索结果页
源代码地址
购买实战课程后,在播放视频页面右侧可查看到章节源代码。
- part1 主要介绍一些正式进入页面开发前的准备工作,但是也都非常重要(否则不会单独拿出来)
- part2 正式开发搜索页面,详解页面每一部分的开发过程
从首页进入搜索结果页的场景有以下两种:
- 通过输入框输入关键字搜索
- 通过轮播图的类型搜索
输入框进入搜索页面的的实现方式,我们最后再介绍,到时候会引入约束性和非约束性组件
的概念,内容比较多。
轮播图进入搜索页面的方式比较简单,就是通过<Link>
组件设置一个路由就好了
<Link to="/search/jingdian"><li className="float-left jingdian">景点</li></Link>
<Link to="/search/ktv"><li className="float-left ktv">KTV</li></Link>
演示过程中需要注意的是,这两种方式跳转到搜索结果页时路由是怎样的。
路由配置找到配置路由的文件./app/router/routeMap.jsx
,找到搜索结果页的代码
<Router history={this.props.history}>
<Route path='/' component={App}>
......
<Route path='/search/:category(/:keyword)' component={Search}/>
......
</Route>
</Router>
路由定位的页面在./app/containers/Search
中,再次强调,它也有一个App
的父组件。
注意看路由的配置规则/search/:category(/:keyword)
,在之前讲react-router
基础知识的时候,都已经介绍过了。这里再重申一遍,其中/search
是路径,/:category
是必填参数,(/:keyword)
是选填参数。
上文让大家注意两种跳转到搜索结果页的方式的路由,可以和这里的规则对应一下。
代码中如何得到这些参数呢?可以通过以下的方式得到:
componentDidMount() {
const params = this.props.params
console.log('category param: ' + params.category)
console.log('key param:' + params.keyword)
}
约束性和非约束性组件
非约束性
针对<input>
输入框这种类型,你可以通过这种方式来实现(其中defaultValue
就是原生DOM中的value
属性)
<input type="text" defaultValue="a" ref="input"/>
获取输入框的值的时候,需要这样做——即通过查询DOM,获取DOM属性的方式来做。
var input = this.refs.input
console.log(input.value)
这样做,跟之前jquery的做法一样,都是围绕着DOM来做的。缺点有两个:
- 依赖DOM操作,不符合组件化的设计,也不易扩展
- 查询DOM消耗更多性能
约束性
比较推荐的方式是这一种。即监控<input>
的变化,将值实时保存到state
中,直接从state
中获取值。
<input type="text" value={this.state.name} onChange={this.handleChange} />
//...省略部分代码
handleChange: function(e) {
this.setState({name: e.target.value});
}
React或者Vue都是一种基于数据驱动视图的设计方式,定好数据和视图的规则之后,只更改数据,不直接操作DOM。操作DOM的事情,交给React或者Vue这个框架的代码来搞定。
最后看一下实际代码中如何修改Home
页面的输入框。
源码地址 https://github.com/wangfupeng1988/react-simple-o2o-demo/tree/stage3-search-page-2
页面效果 抽离 SearchInput 组件根据最终实现的效果可以看到,搜索结果页的头部有一个输入框,而首页的头部也有一个输入框,两者的作用都是一样的。因此要把这个输入框抽离成一个组件,两个地方公用。
由于搜索结果页还没有开始创建,因此处理的这个组件先给首页的头部用,即用于HomeHeader
组件中。
创建./app/components/SearchInput
组件,并引用到HomeHeader
中。
<SearchInput value="" enterHandle={this.enterHandle.bind(this)}/>
引用时需要传递两个参数,value
即引用时要显示的默认值,enterHandle
即在其中输入内容并回车时,要触发的事件。具体的实现,看实际代码即可。
在SearchInput
组件中,首先要满足约束性组件的条件,第二要用上传入的enterHandle
的方法。
搜索结果页的头部,也是一个红色背景的Header,但是这个Header的样子,和之前做的其他页面的都不一样,因此又要重新做一个Header组件。
创建./app/components/SearchHeader
组件,并引用到Search
页面中。
<SearchHeader keyword={params.keyword}/>
注意,这里要传入一个keyword
属性,即把搜索结果页拿到的keyword
参数传递进去 —— 因为要在头部的 input 中显示搜索的关键字。(这个params.keyword
在 part1 的时候已经解说过了)
在SearchHeader
组件的代码实现中,左侧有一个返回按钮,然后就是输入框。这里的输入框当然要引用刚刚抽离出来的SearchInput
组件。
<SearchInput value={this.props.keyword || ''} enterHandle={this.enterHandle.bind(this)}/>
两个必要的参数是必须传的。其中传递给value
参数的,正好是接收到的keyword
属性值
这里的结果列表和首页中的“猜你喜欢”基本差不多,也是需要在subpage
目录下创建一个子页面,然后在子页面中获取数据,并传递给./app/components/List
,加载更多的实现方式,也是一个样子的。
唯一不同的是,如果在搜索结果页头部的输入框中再次输入内容重新进行搜索时,就需要多一步处理。
// 处理重新搜索
componentDidUpdate(prevProps, prevState) {
const keyword = this.props.keyword
const category = this.props.category
// 搜索条件完全相等时,忽略。重要!!!
if (keyword === prevProps.keyword && category === prevProps.category) {
return
}
// 重置 state
this.setState(initialState)
// 重新加载数据
this.loadFirstPageData()
}
这里需要理解componentDidMount
和componentDidUpdate
两个生命周期的不同。
- 页面初次渲染,会走
componentDidMount
- 页面再次渲染,就不会走
componentDidMount
,而只走componentDidUpdate
共同学习,写下你的评论
评论加载中...
作者其他优质文章