react闲谈——webpack2、react-router4稳定版架构

前端之家收集整理的这篇文章主要介绍了react闲谈——webpack2、react-router4稳定版架构前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

随着react技术栈插件的不断升级,我也不想拖后腿,所以把webpack2和react-router4融入了项目中:https://github.com/hyy1115/re...

前端编程宗旨:工程化、流程化、简单化为目的,拒绝装逼无用的代码风格!

欢迎来到react的世界,下面你将会学习到react技术栈是如何使用的

1、认识本项目的结构

我采用的是react、redux、webpack2、react-router4的基本架构,属于经典主流类型。

文件夹介绍

  1. doc:项目文档
  2.  
  3. mock:静态数据
  4.  
  5. public:静态图片
  6.  
  7. src:前端主目录
  8.  
  9. test:基本测试代码
  10.  
  11. 根目录下面的 server.jswebpack.config.js需要多关注一下。

2、修改前端服务器端口号

在server.js中

  1. var port = 3011; //修改成你需要的端口

3、开启代理服务器

我们有时候会遇到跨域访问数据的问题,这时候你可以选择开启 server.js 中的代理服务器。

  1. //现在你只需要执行这一行代码,当你访问需要跨域的api资源时,就可以成功访问到了。
  2. // app.use('/api/*',proxy({
  3. // target: 'http://www.baidu.com',// changeOrigin: true
  4. // }))

4、webpack.config.js的作用

webpack的配置文件是一个object,你只需要记住webpack的配置都是通过设置entry、output等参数的值,还有更加丰富的功能去官网看看。

5、src目录的介绍

这个目录的重要性不言而喻,你今后的绝大部分react代码都会在该目录结构下组织,当前采用的是redux架构,所以你会看到整体目录结构由redux的几个主要部分构成。

  1. actionredux的控制中心,任何一个状态state的更新操作都需要dispatch一个action修改。这一步在一些人看来是鸡肋的操作,他们会觉得观察者模式比你这个统一大脑指挥中心方便多了。
  2.  
  3. components:管理比较细的一些组件。比如HeaderFormBanner等。
  4.  
  5. containers:管理路由级别的组件,这些大组件往往是一整个页面,内部嵌套了很多小组件,也可能嵌套其他路由级组件进来。
  6.  
  7. reducers:这里是redux的数据管理中心,reducer是纯函数,你不能在reducer修改当前的state,只能返回一个新的state,如果你直接修改state,将不能重新渲染。
  8.  
  9. utils:一些工具js的管理。
  10.  
  11. app.css:基本的css配置,你也可以把reset.css或者其他初始化样式的css写入app.css中。
  12.  
  13. appContainer.js:我们叫他根组件,在SPA应用中,通常只有一个根组件。
  14.  
  15. bundle.jsreact-router4中使用的懒加载代码,目前我已经注释掉,有需求的可以自己尝试使用。
  16.  
  17. index.jswebpackentry使用的入口js文件包括store的管理,根组件的渲染都在该文件中。

6、实现一个首页的流程步骤解析

有了这样一个搭建好的框架,你如果是个初学者,是不是很想快点用它做出自己的网站,下面我就将首页的实现过程大概梳理一下,之后你可以尝试写一个属于自己的页面

第一步:想要用react写一个网页,你的第一个想法便是去container目录新建一个文件夹,比如Home,表示当前首页的路由组件homeContainer.js,文件名我通常开头不大写,但是在class HomeContainer中就需要开头大写了。 此外,还需要在Home文件夹下面新建files和styles,分别用来存放当前组件的图片等资源和样式。

第二步:你可以开始写homeContainer组件的代码了,通常一个基本的路由组件是下面这种结构。

  1. import React,{ Component } from 'react'; //react必须导入
  2. import { bindActionCreators } from 'redux'; //bindActionCreators用来绑定你的action到该组件上
  3. import { connect } from 'react-redux'; //connect()是个函数,顾名思义是把react和redux连接起来。
  4. import PropTypes from 'prop-types'; //PropTypes原来是在React中使用,现在被官方拆分出来单独管理。
  5.  
  6. import Header from 'components/Home/header'; //导入子组件,子组件写在components文件夹。
  7.  
  8. require(`./styles/home.less`); //导入首页样式
  9.  
  10. //请注意@connect()必须写在组件的上面,而且紧挨着组件,不要拆散他们俩。
  11. @connect(
  12. state => state
  13. )
  14. export default class HomeContainer extends React.Component {
  15. render() {
  16. return (
  17. <div>
  18. <Header title="" imgUrl="" linkTo="" bgColor="" match=""/>
  19. </div>
  20. )
  21. }
  22. }

第三步:去components文件夹下面,新建一个Home文件夹,于containers下面的Home文件夹一一对应,这样做的好处是父子组件既能分开管理,也能快速找到。 接着在Home下面新建header.js文件。子组件可以是函数,也可以是react类型的组件。我在这里定义的是一个react子组件。

  1. import React,{ Component } from 'react'; //无论是函数组件还是react组件,都需要导入React。
  2. import { Link } from 'react-router-dom'; //Link相当于a标签
  3. import PropTypes from 'prop-types';
  4. //header子组件只作为数据渲染,数据从父组件传递到子组件使用props。在jsx中绑定数据使用大括号。请注意标签中的class需要改成classname,而style里面写成object的形式。
  5. 如果你不喜欢字符串之间的参数用加号拼接,那么可以使用`${value}`的方式。
  6. export class Header extends React.Component {
  7. render() {
  8. const {title,imgUrl,linkTo,bgColor,match} = this.props
  9. return (
  10. <header className='header' style={bgColor}>
  11. {title}
  12. <Link to={`${match.url + linkTo}`} className="a_link" >
  13. <img src={imgUrl} className="a_img" />
  14. </Link>
  15. </header>
  16. )
  17. }
  18. }

第四步:我们现在还没有用到action和reducer,别着急,看到nav.js组件没?Nav组件是一个li列表,列表的文案数据是从HomeContainer父组件传递过来的,这些菜单列表数据我用静态json文件的方式 写在了mock文件夹下面,正常情况下,它可能在你的后端服务器,也就是说你需要请求ajax返回导航数据。

可以思考一下,在什么时候、什么地方去请求后端的导航数据呢?

我是在homeContainer组件的componentWillMount(即将渲染前,也就是还没有开始渲染)使用ajax请求接口数据。有人可能会在componentDidMount(渲染完成后)再去服务器拿数据,当然,你喜欢这样,没人拦着。

是不是直接在componentWillMount写ajax代码就行了呢?别忘了你已经使用了redux,这时候你就需要在action中新建一个js,然后定于一个action用来发送保存从后端接收到的导航数据。

  1. //这个就是传说中的action,他只是返回一个对象,可以是多个参数。
  2. const receiveNav = (response) => ({
  3. type: 'RECEIVE_NAV',navMain: response.data
  4. })

通常你的ajax代码写在当前action的下面,两者写在一起管理非常方便,要是写到其他文件夹下面,到时候你的项目一大,找个ajax都找不到,特别头疼。

这是一个异步函数,你可以选择使用Promise或者其他异步方法,我在这里使用的是async/await,dispatch是redux中非常重要的一个方法

  1. export const getNav = () => async (dispatch,getState) => {
  2. try {
  3. let response = await getData(`/api/book/navigation`) //ajax请求采用axios插件
  4. await dispatch(receiveNav(response)) //靠着这个神奇的dispatch(),可以直接调用action对应的函数,去更新store里面的数据。
  5. } catch (error) {
  6. console.log('error: ',error)
  7. }
  8. }

第五步:现在数据有了,我们知道redux是单向数据流,那么数据会从action流向哪里呢?答案就是reducer。在reducers文件夹下面,新建一个nav.js文件, reducer作为数据流向store最后一层屏障,每次都会拷贝一个新的state,所以通常是这种写法。

  1. // 初始化状态
  2. let initNavList = {
  3. navMain: []
  4. }
  5.  
  6. export function nav(state = initNavList,action) {
  7. switch (action.type) {
  8. case 'RECEIVE_NAV':
  9. return {
  10. ...state,//三个点是展开符
  11. navMain: action.navMain
  12. }
  13.  
  14. default:
  15. return {...state};
  16. }
  17. }
  18.  
  19. 我们看看第一个case里面return出来的是什么东西
  20.  
  21. {
  22. navMain: [data]
  23. }

原来navMain是一个空数组,当有数据返回的时候,整个initNavList就会拷贝一个新的对象出来,注意这个initNavList仅仅是整颗store状态树的一部分节点。
第六步:你是不是有点好奇,为什么action和reducer不需要import或者require文件,数据就会那么听话的流过来呢?

答案就在reducers文件夹下面的index.js文件中。你如果在reducer文件夹下面新建了js文件,需要在该文件夹下的index.js中注册你的reducer。

  1. //关键的2个插件
  2.  
  3. import { combineReducers } from 'redux';
  4. import { routerReducer } from 'react-router-redux'

第七步:reducer写好了,那么数据下一步就要流向container组件了。来吧,宝贝。 在路由组件(或者叫做父组件)中,关联state和action是其中非常重要的一环,不然你是无法读取state和action的。

  1. import * as navActions from 'actions/nav'; //导入nav文件下面的所有函数,不管是action函数ajax方法
  2.  
  3. @connect(
  4. state => state,dispatch => bindActionCreators({...navActions},dispatch)
  5. )
  6. 接着你就可以在组件中通过props的方式去调用action里面的方法了。
  7.  
  8. componentWillMount() {
  9. const { navMain } = this.props.nav //读取reducer中的nav。
  10.  
  11. //如果state中的navMain为空,那么就执行getNav()函数去请求后端导航数据。
  12. if (navMain.length === 0) {
  13. this.props.getNav();
  14. }
  15. }

第八步:父子组件和数据都写好了,想要运行在网页上测试一下?你还有最后一步没有完成呢。

最关键的:路由。

在appContainer中,管理主要的路由组件,具体看代码

  1. import HomeContainer from './containers/Home/homeContainer';
  2.  
  3. <Route location={location} exact path="/" component={HomeContainer} />

你也可以结合我在文章开头分享的github项目来学习。

提问环节:

小白:我V2、V3都还没搞懂,你分享V4有什么用?

我:前端就是这样,每天都在出新的插件,紧跟步伐,才能更好的应用于项目之中。

猜你在找的React相关文章