涉及知识点总结
热门搜索换页功能知识点:
- 想从state中获取数据就到connect的参数1
mapStateToProps()
中设置映射,再从this.props上去拿 - 在组件上绑定事件函数要注意事件名称是驼峰形式的
- 函数如果要处理state中的数据就要通过action
- 需要涉及action操作的函数都放在connect的参数2
mapDispatchProps()
中进行定义 - (connect来自react-redux中间件)
换页旋转功能知识点:
- 在设置动画时可以使用**
ref
获取对应的DOM元素**进行操作 - js中的react 样式是字符串类型的,所以在组件中设置DOM元素样式时属性值需要引号
- 想要获取 样式属性值 中的数字,可使用字符串的relpace()结合正则表达式将所有非数字部分替换为空,则剩余的就是数字,但注意:得到的数字是字符串类型的
- ParseInt()将字符串=>数字,空字符串=>Nan,Nan+数字=Nan
- 简单的 旋转,缩放,倾斜或平移效果可以使用
transform
样式属性来完成,transform-origin
属性可设置中心点,动画效果可以使用transition
属性来实现。 - 注意:
- transition仅对block元素生效,需要使用
display:block;
** - block会使iconfont和“换一批”分成上下两行,所以需要
float:left
使iconfont脱离文档流左浮动以出现在文字左边。
- transition仅对block元素生效,需要使用
热门搜索换页功能
现在我们的热门搜索框内数据是全部显示的:
实现效果:每次只显示10个标签,点击“换一批”后显示另一批标签,也就是1页存放10个标签,点击“换一批”则下一页,到最后一页后又返回第一页。
每页显示10个标签
思路:
- 在header组件的store中添加两个数据
page
(当前所在页)和totalPage
(总页数) - 在获取
list
的action函数中改变totalPage
的值。 - actionCreators中获取标签数据后进行分页再传给reducer
- reducer拿到totalPage数据后添加到state中
- 在index.js中获取page,根据page显示list数据
store中添加两个数据
**header-store-reducer.js中添加两个数据page
和totalPage
**:
1 | const defaultState = fromJS({ |
获取数据后进行分页
我们在index中使用actionCreators.js中的getList()来获取热门标签数据,而获取到的数据是通过changeList()传给reducer的,所以分页处理也放到changeList()中完成即可。
header-store-actionCreators.js:
1 | const changeList = (data) => ({ |
reducer将totalPage添加到state
reducer拿到totalPage数据后添加到state中。
header-store-reducer.js:
redux效果:
可以通过redux看到state中数据(当前所在页page和总页数totalPage)的变化。
组件中根据page显示list数据
在index.js中,我们原本将整个list
循环显示在页面上,但现在我们应先获取page,根据page显示list数据
header-index.js:
1.在connect的参数1mapStateToProps()
中**获取到state的page
**:
1 | const mapStateToProps = (state) => { |
2.根据page循环10个标签:
页面效果:
一页只显示10个标签,但鼠标点击“热门搜索框”时搜索框消失。
immutable数组的toJS()
- immutable数组是不可改变的,增删查改都比较麻烦,所以我们可以通过
toJS()
将immutable数组转换为JS数组。 - 语法:
const jsList = toJS(immutable数组);
设置“热门搜索”显示条件
实现效果:鼠标停在“热门搜索”内时搜索框会一直显示。
思路:
- 在state中添加
mouseIn
数据 - 当鼠标移入“热门搜索”中时,
mouseIn
变为true:也就是给SearchInfo组件绑定onMouseEnter事件函数,触发时通过action改变state中mouseIn
的值。 - 鼠标移入热门搜索时mouseIn变为true,移出时要变回false,所以同2的流程处理一下。
- 原本“热门搜索”显示条件为focused,现在要增加一个“或者mouseIn”,我们要让她符合一个就能显示。
state中添加mouseIn
数据
header-store-reducer.js:
1 | const defaultState = fromJS({ |
onMouseEnter事件改变mouseIn
- 当鼠标移入“热门搜索”中时,
mouseIn
变为true:也就是给SearchInfo组件绑定onMouseEnter事件函数,触发时通过action改变state中mouseIn
的值。 - 要想改变mouseIn就要通过action
1.在SearchInfo组件上绑定onMouseEnter事件函数handleMouseEnter:
1 | <SearchInfo onMouseEnter={handleMouseEnter}> |
2.在mapDispatchProps()中定义函数handleMouseEnter,通过action(即mouseEnter)改变mouseIn:
1 | handleMouseEnter(){ |
3.在actionCreators.js中创建mouseEnter():
1 | export const mouseEnter = () => ({ |
4.在reducer.js中处理action:
验证redux:
onMouseLeave事件改变mouseIn
- 鼠标移入热门搜索时mouseIn变为true,移出时要变回false,所以同样的流程处理一下。
- 一样,要想改变mouseIn就要通过action
- 在SearchInfo组件上绑定onMouseLeave事件函数handleMouseLeave
- 在mapDispatchProps()中定义函数handleMouseLeave,通过action(即mouseLeave)改变mouseIn
- 在actionCreators.js中创建mouseLeave()
- 在reducer.js中处理action
验证:
同样使用redux进行验证,鼠标移入“热门搜索”时mouseIn变为true,移出时mouseIn变为false。
改变“热门搜索”显示条件
原本“热门搜索”显示条件为focused,现在要增加一个“或者mouseIn”,我们要让她符合一个就能显示。
store中引入mouseIn:
1 | const mapStateToProps = (state) => { |
增加一个mouseIn作为判断条件:
点击“换一批”换页
引入totalPage,给SearchInfoSwitch组件绑定onClick事件handleChangePage,执行handleChangePage函数时传递page和totalPage,在handleChangePage函数中进行判断后决定action(即将被使用的page)的值。
index.js:
1 | <SearchInfoSwitch |
actionCreator.js:
1 | export const changePage = (page) => ({ |
reducer.js:
解决key值报错
虽然我们在循环中给每一项都设置了key值:
1 | for (let i = (page - 1) * 10; i < page * 10; i++) { |
但还是报错了:
原因:
通过打印可以看到前面10次循环的key值都是undefined,因为初始化页面时render函数就执行了,带动getListArea()执行了for循环,但list中数据是通过AJAX获取的,而我们的AJAX请求时点击搜索框才发出的,所以初始化时list还是空数组,也就拿不到数组元素了。
解决方法:
list拿到数据时才进行循环即可:
1 | if (newList.length) { |
优化:merge()代替多次set()
- 使用多次set()修改immutable数据时可使用merge()代替来合成多次修改后的immutable对象。
reducer中:
1 | state.set("list", action.data).set("totalPage", action.totalPage); |
换页旋转动画效果
实现效果:点击“换一批”后,图标旋转
思路:
- iconfont中找到spin图标放到相应位置并设置样式
- 使用
ref
获取到spin图标的DOM元素 - 点击“换一批”时触发的事件绑定函数中,使用**
transform
样式属性使每次点击spin图标就增加360度来旋转**- 设置**
transform-origin
属性让图标围绕中心点旋转**。 - 由于度数需要每次增加360度,而点击时设置样式属性为360度则是写死了,无法递增。所以我们每次点击都需要获取当前
transform
样式属性值中的度数作为原始度数,在原始度数基础上加360度作为transform
样式属性值。 - 原始度数的获取:首先明确js中样式是字符串形式的,所以可以使用字符串的replace()替换属性值中所有非数字字符串为空,这样剩下的就是数字(即度数)。
- 注意:
- 获取到的原始度数是字符串类型的,使用ParseInt转换为数字后再进行加操作。
- 一开始是0度,替换字符串后得到空字符串,ParseInt(空字符串)=Nan,Nan+360=Nan,如果这样第一次设置旋转角度就会失败,所以要加个判断,让原始度数是空字符串时转换为数字0。
- 设置**
- 在spin图标的样式中使用**
transition
属性使旋转产生动画效果**- 注意:
- transition仅对block元素生效,需要使用
display:block;
** - block会使iconfont和“换一批”分成上下两行,所以需要
float:left
使iconfont脱离文档流左浮动以出现在文字左边。
iconfont下载、替换本地图标
搜索“spin”,添加到项目后下载到本地,解压后拷贝所需的5个文件到static中的iconfont文件夹中:
将文件夹中的iconfont.css内容拷贝到static-iconfont-iconfont.js中,一点点进行替换(记得@font-face中,只要不是data开头的路径前都要加./
将其改为相对路径)
使用spin图标、设置样式
1.index.js中使用spin图标:
1 | <SearchInfoSwitch |
结果图标出现在右下角:
原因:因为在style中我们设置了:SearchWrapper组件下的iconfont都相对SearchWrapper进行绝对定位在右下角。
解决方法:
2.设置spin图标样式
index.js中给spin图标增加样式spin:
1 | <SearchInfoSwitch |
style.js中:
1 | export const SearchInfoSwitch = styled.div` |
点击旋转360度
- 使用**
ref
获取到spin图标的DOM元素**,传入点击事件函数handleChangePage中 - handleChangePage函数拿到spin以后往spin的样式中添加transform属性 使每次点击spin图标就增加360度来旋转
- 设置**
transform-origin
属性让图标围绕中心点旋转**。 - 由于度数需要每次增加360度,而点击时设置样式属性为360度则是写死了,无法递增。所以我们每次点击都需要获取当前
transform
样式属性值中的度数作为原始度数,在原始度数基础上加360度作为transform
样式属性值。 - 原始度数的获取:首先明确js中样式是字符串形式的,所以可以使用字符串的replace()替换属性值中所有非数字字符串为空,这样剩下的就是数字(即度数)。
- 注意:
- 获取到的原始度数是字符串类型的,使用ParseInt转换为数字后再进行加操作。
- 一开始是0度,替换字符串后得到空字符串,ParseInt(空字符串)=Nan,Nan+360=Nan,如果这样第一次设置旋转角度就会失败,所以要加个判断,让原始度数是空字符串时转换为数字0。
- 设置**
结果:
通过打印spin可以看到点击以后旋转角度有所变化,但看不到效果,所以接下来要设置动画效果。
动画效果
- 在spin图标的样式中使用**
transition
属性使旋转产生动画效果**- 注意:
- transition仅对block元素生效,需要使用
display:block;
** - block会使iconfont和“换一批”分成上下两行,所以需要
float:left
使iconfont脱离文档流左浮动以出现在文字左边。