• wordpress CMS主题:ssmay主题 wordpress CMS主题:ssmay主题
  • 首页 > 前端开发 > Next.js踩坑入门系列(六) —— 再次重构目录

    Next.js踩坑入门系列(六) —— 再次重构目录

    作者: 分类:前端开发 点击: 1,222 次
    wordpress CMS主题:ssmay主题

      扫描下面的二维码,“关注”我的百家号。

      Next.js踩坑入门系列

      上一节引入了redux以及使用redux-saga来进行异步函数的处理,而上一节的目录只是简单的引入redux而已,redux可是相当庞大和复杂的,并且也算是个人习惯了吧。action分离,reducer分离,状态组件container等等。我喜欢把这些东西划分的清清楚楚,这样一个项目维护起来才会方便~这一节就从头到尾来进行目录的划分,因为Next.js和原本的React SPA项目有一定的区别,主要体现在路由部分,所以我也是按照自己的理解和舒服的方式进行目录重构!

      重构完的目录

      // ================ 目录结构 ================== //
      ——————
        | -- asserts         // ant-design全局less变量设置文件夹
        | -- components      // React展示组件(也就是UI组件)文件夹
        | -- constants       // 整个应用的常量文件夹
            | -- ActionsTypes.js   // 存放所有action type的常量文件
            | -- ApiUrlForBE.js    // 存放所有后端数据的apiUrl
            | -- ...
        | -- containers      // React状态组件文件夹
        | -- pages           // Next.js路由文件夹
        | -- redux
            | -- actions     // 处理整个应用所有的action
            | -- middlewares // 中间件,处理各种特殊情况,比如获取失败之后的message提醒
            | -- reducers    // 处理整个应用所有的reducer
            | -- sagas       // 处理整个应用所有的saga
            | -- store.js  
        | -- static          // 存放整个应用所有的静态资源(如图片等)
        | -- .babelrc
        | -- .eslintrc
        | -- .gitignore
        | -- next.config.js  // Next.js配置文件
        | -- package.json   
        | -- server.js       // 服务端server文件
        | ...
      

      原谅我臭不要脸一下,个人认为这个结构还是非常清晰的,只不过可能新手写起来可能会觉得有些繁琐,不过项目大的情况下,state树很大,这种结构非常的清晰~

      重构actions

      其实actions完全可以放在一个文件里使用,不过项目庞大了以后维护起来还是有些麻烦的,所以按照组件化思想,每一个组件对应一个action,或者每一个大功能块对应一个action还是比较合理的。

       -- redux
         | -- actions
             |  -- home.js // 处理首页action
             |  -- user.js // 处理与用户有关action
             |  ...        // 其他action
      

      重构reducers

      reducer部分肯定是要分离的,因为redux的官方为我们提供combineReducer这个API就是合并不同组件的reducer的,所以可以理解为redux的reducer推荐就是根据组件进行划分的~就如同整个应用只有一个状态树一样,每一个reducer负责处理树的不同枝叶派发出来的action。具体reducer内容还是去看redux官方文档吧。

      重构sagas

       -- redux
         | -- reducers
             |  -- home    // 首页部分reducer
             |  -- user    // 用户相关reducer
             |  ...        // 其他reducer
             | index.js    // rootReducer,由combineReducer生成
      

      抽离container

      这里需要特别说明一下~~~由于Next.js的特殊原因,其实已经做到了UI组件的分离,其实这一层container完全可以由pages文件夹代替,也就是可以用路由组件通过react-redux的connect函数封装一下,这样就变成了一个带状态的路由组件,不知道大家明不明白我说的话。。。下面是两种方法,大家按需自己采取,以UserList组件为例:

      • 第一种,抽离container
          // /conatiners/user/UserList.js
          import { connect } from 'react-redux';
          import { fetchUserListData } from '../../redux/actions/user';
          import UserList from '../../components/User/UserList';
          
          const mapStateToProps = state => ({
            list: state.user.list.list,
          });
          
          const mapDispatchToProps = dispatch => ({
            fetchUserListData() {
              dispatch(fetchUserListData());
            }
          });
          
          export default connect(mapStateToProps, mapDispatchToProps)(UserList);
      
          // pages/user/userList.js
          import UserList from '../../containers/user/UserList';
          import { fetchUserListData } from '../../redux/actions/user';
          // 这部分内容下一章节讲~
          UserList.getInitialProps = async (props) => {
            const { store, isServer } = props.ctx;
            if (store.getState().user.list.list.length === 0) {
              store.dispatch(fetchUserListData());
            }
            return { isServer };
          };
          
          export default UserList;
      

      简单来说其实就是路由组件导入的是状态组建UserList.js,而状态组建是通过react-redux的connect方法封装UI组件UserList.js而得来的。

      • 第二种,带状态的路由组件
      // /pages/user/userList.js
      import { connect } from 'react-redux';
      import UserList from '../../containers/user/UserList';
      import { fetchUserListData } from '../../redux/actions/user';
      
      UserList.getInitialProps = async (props) => {
        const { store, isServer } = props.ctx;
        if (store.getState().user.list.list.length === 0) {
          store.dispatch(fetchUserListData());
        }
        return { isServer };
      };
      
      const mapStateToProps = state => ({
        list: state.user.list.list,
      });
      
      const mapDispatchToProps = dispatch => ({
        fetchUserListData() {
          dispatch(fetchUserListData());
        }
      });
      
      export default connect(mapStateToProps, mapDispatchToProps)(UserList);
      

      简单来说,就是在路由组件内把UI组件UserList.js通过connect变成了状态组件。

      个人推荐第一种方法,虽然写起来稍微麻烦了一些,但是第二种方法完全是因为Next.js的特殊性才能实现的,当然,对于Next.js来说,第二种方式确实更简单一些~

      结束语

      经历了上面几个部分的重构,整个基于Next.js的服务端渲染脚手架基本结构也就成型了。在搭建过程中还是遇到了很多坑的,不过也都一点点的踩过去了。希望对大家有些帮助,个人认为这个结构还是值得参考一下的~原本到这里就可以结束系列文章了,不过我在使用过程又发现了一些坑,顺便的Next.js还有一些内容我还没碰过,就帮大家都踩一踩,下一节来一个其他内容的大杂烩~

      代码地址



      欢迎“关注”我的百家号。

      头条二维码
      加入我的QQ群
      头条二维码
      关注我的百家号

    文章作者:sunny
    本文地址:http://wanlimm.com/77202006208302.html
    版权所有 © 转载时必须以链接形式注明作者和原始出处!

    上一篇:
    下一篇:
    wordpress CMS主题:ssmay主题

    或许你会感兴趣的文章:

    发表评论

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

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据