Header组件热门搜索栏的实现示例

目录
  • 1. 基本布局
    • 1.1 热门搜索框
    • 1.2 热门搜索Title和换一换图标
    • 1.3 热门Tag
  • 2. 控制展示
    • 3. 使用 Ajax 请求获取 Tag 数据
      • 3.1 使用 redux-thunk 返回函数
      • 3.2 使用 Immutable 的数组进行 state 统一更新
      • 3.3 使用 map 方法循环展示内容
    • 4. 优化 reducer

      1. 基本布局

      本次任务是实现热门搜索模块的布局和展示控制功能。

      1.1 热门搜索框

      在布局过程中,我们发现热门搜索框并没有出现。这可能是由于外部组件存在 overflow: hidden 属性导致的,因此我们需要给一个高度解决这个问题:

      cssCopy code
      export const SearchInfo = styled.div`
        position: absolute;
        left: 0;
        top: 56px;
        width: 240px;
        height: 100px;
        padding: 0 20px;
        background: green;
      `;
      

      接下来,我们通过简书官网调试的方法补全其他属性。

      1.2 热门搜索Title和换一换图标

      接下来,我们需要添加热门搜索Title和换一换图标。

      cssCopy code
      export const SearchInfoTitle = styled.div`
        margin-top: 20px;
        margin-bottom: 15px;
        line-height: 20px;
        font-size: 14px;
        color: #969696;
      `;
      

      然后需要实现换一换的功能。

      1.3 热门Tag

      我们还需要添加热门Tag的样式:

      cssCopy code
      export const SearchInfoItem = styled.a`
        display: block;
        float: left;
        line-height: 20px;
        padding: 0 5px;
        font-size: 12px;
        border: 1px solid #ddd;
        color: #969696;
        border-radius: 2px;
        margin-right: 10px;
        margin-bottom: 15px;
      `;
      

      但是此时发现高度出了问题了,因此我们需要在外层布局进行修改:

      cssCopy code
      export const SearchWrapper = styled.div`
        position: relative;
        float: left;
        .iconfont {
          position: absolute;
          right: 5px;
          bottom: 5px;
          width: 30px;
          height: 30px;
          line-height: 30px;
          border-radius: 15px;
          text-align: center;
          &.focused {
            background: #777;
            color: #fff;
          }
        }
        .slide-enter {
          transition: all 0.2s ease-out;
        }
        .slide-enter-active {
          width: 240px;
        }
        .slide-exit {
          transition: all 0.2s ease-out;
        }
        .slide-exit-active {
          width: 160px;
        }
      `;
      export const SearchInfo = styled.div`
        position: absolute;
        left: 0;
        top: 56px;
        width: 240px;
        padding: 0 20px;
        background: green;
      `;
      

      同时,我们将上面 SearchInfo 写死的高度去掉。

      2. 控制展示

      官方文档描述了 SearchInfo 区域应该在鼠标聚焦时显示,失去焦点时隐藏。我们可以通过控制 SearchInfo 区域来实现这个逻辑,而且这个控制逻辑与之前用于控制动画的控制参数非常相似。

      3. 使用 Ajax 请求获取 Tag 数据

      实际上,热门 Tag 的数据是从服务器获取的。我们希望通过 Ajax 来获取这些数据,就像简书网站一样。而且我们只需要在第一次聚焦时获取数据,然后进行本地缓存。

      此时,我们需要将 header 中的列表内容进行存储,以便后续进行状态管理。初始时,它是一个空数组。

      3.1 使用 redux-thunk 返回函数

      当 Nav 聚焦时,我们需要获取 Ajax 数据。由于这是一个异步操作,所以需要使用第三方库。我们统一使用 redux-thunk 进行操作,将异步操作放在 action 中处理。

      应该在创建 store 时使用 redux-thunk:

      接下来,我们需要派发异步 action:

      然后创建这个 Action:

      如果需要使用 Ajax,则需要使用第三方库 axios 来实现异步请求:

      import axios from 'axios';
      export const getList = () => { return (dispatch) => { // 异步请求 axios.get('/api/headerList.json').then(()=>{
          }).catch(()=>{
              console.log('error');
          });
      }
      };
      

      当后端数据还未开发完成时,我们可以使用前端制作的假数据。我们可以使用 create-react-app 的特性,在 public 和 src 目录下创建一个对应的 JSON 文件,然后就可以访问了。在此期间,路由也需要进行修改,以便实现假数据。

      然后,我们需要修改 state。我们需要在回调中派发一个新的 action:

      const changeList = (data) => ({ type: constants.CHANGE_LIST, data });
      export const getList = () => { return (dispatch) => { // 异步请求 axios.get('/api/headerList.json').then((res) => { const data = res.data; dispatch(changeList(data.data)) }).catch(()=>{ console.log('error'); }); } };
      

      3.2 使用 Immutable 的数组进行 state 统一更新

      接下来,我们需要在 reducer 中根据获取的 data 更新 list。但是有一点需要注意:我们使用 fromJS() 方法将 list 变成了一个 Immutable 数组。但是,当我们调用 state.set() 方法去改变 list 时,action.data 本身是一个普通的数组,这两种数据类型不同会出现错误。因此,我们需要将 data 转换为 Immutable:

      然后,我们可以按如下方式编写 reducer:

      3.3 使用 map 方法循环展示内容

      最后,需要将数据展示出来。可以使用 map 方法来遍历数组,并渲染列表项:

      javascriptCopy code
      getListArea(show) {
        if (show) {
          return (
            <SearchInfo>
              <SearchInfoTitle>
                热门搜索
                <SearchInfoSwitch>
                  换一批
                </SearchInfoSwitch>
              </SearchInfoTitle>
              <SearchInfoList>
                {this.props.list.map((item) => {
                  return <SearchInfoItem key={item}>{item}</SearchInfoItem>;
                })}
              </SearchInfoList>
            </SearchInfo>
          );
        } else {
          return null;
        }
      }
      

      即使是使用 immutable 数组,也可以使用 map 方法进行遍历。

      4. 优化 reducer

      之前的 reducer 大量使用 if 语句,可以通过使用 switch-case 进行优化:

      cCopy code
      export default (state = defaultState, action) => {
        switch (action.type) {
          case constants.SEARCH_FOCUS:
            return state.set('focused', true);
          case constants.SEARCH_BLUR:
            return state.set('focused', false);
          case constants.CHANGE_LIST:
            return state.set('list', action.data);
          default:
            return state;
        }
      };
      

      使用 switch-case 可以让 reducer 代码更加清晰易懂。

      以上就是Header组件热门搜索栏的实现示例的详细内容,更多关于Header组件热门搜索栏的资料请关注风君子博客其它相关文章!

      您可能感兴趣的文章:

      • 详解Vue后台管理系统开发日常总结(组件PageHeader)
      • Vue header组件开发详解
      • VSCode多行注释插件KoroFileHeader使用示例
      • Flutter实现固定header底部滑动页效果示例
      • NSURLSession跨域重定向透传HTTP Header问题解决
      • Go结构体SliceHeader及StringHeader作用详解
      • 好用的VSCode头部注释插件Fileheader Pro
      • resty更新header控制api版本数据源读写分离

      Published by

      风君子

      独自遨游何稽首 揭天掀地慰生平

      发表回复

      您的电子邮箱地址不会被公开。 必填项已用 * 标注