30分钟极速通关react mobx react-router及打通springboot

简介: 内容导航 简单开发react 将react与mobx结合开发 使用react-router进行多页面开发 将项目打包到后端项目中进行部署 将完成的项目做成脚手架,避免重复的环境搭建 需要环境 确保node已经安装 确保npm已经安装 创建项目 npx create-react-app te.

内容导航

  1. 简单开发react
  2. 将react与mobx结合开发
  3. 使用react-router进行多页面开发
  4. 将项目打包到后端项目中进行部署
  5. 将完成的项目做成脚手架,避免重复的环境搭建

需要环境

  1. 确保node已经安装
  2. 确保npm已经安装

创建项目

github项目地址

npx create-react-app test 
# test 为你需要创建项目的名字,会在命令当前目录下创建test的目录,包含项目所有的文件

你已经完成了创建,开始跑起来

npm start

你可以看到react已经能够在local host:3000访问了,只有一个欢迎页面

目录结构

目录结构图

    1. node_modules
      是当前目录安装的模块存放的地方
    1. public
      index.html 是单页面的入口
    1. src
      可存放自己编写的代码,App是默认生成的欢迎页面逻辑,index 是js的主入口

开始更改你的代码

A. react简单开发

1.将App.js的代码更改如下

import React, {Component} from 'react';
import './App.css';

class App extends Component {
    constructor(props) {
        super(props)
        this.state = {todos: [{checked: false, text: "hello"}, {checked: true, text: "world"}]}
        this.handleClick=this.handleClick.bind(this)
    }

    handleClick(index) {
        let todos = this.state.todos
        todos[index].checked = !todos[index].checked
        this.setState({todos:todos})
    }

    render() {
        let todos = this.state.todos
        let todosDiv = todos.map((item, index) => {
            return (<Todo index={index} checked={item.checked} text={item.text} handleClick={this.handleClick}/>)
        })
        return (
            <div className="App">
                {todosDiv}
            </div>
        );
    }
}

class Todo extends Component {
    constructor(props){
        super(props)
        this.handleClick=this.handleClick.bind(this)
    }
    handleClick() {
        let index = this.props.index
        this.props.handleClick(index)
    };
    render() {
        return (
            <p><input type={'checkbox'} checked={this.props.checked} onClick={this.handleClick}/>
                {this.props.text}:{this.props.index}
            </p>
        )

    }
}

export default App;
  1. 再次npm start一下看看效果吧~
    效果图
  2. 可以看到我们组件已经能够响应点击了

B. 引入mobx作为状态管理

提出问题

  1. 在上面我们可以看到想要更改状态是比较困难的,首先要将handClick方法由子组件传给父组件,再进行处理。如果我们的组件是
    四五层组件的时候得一步一步的往上级传递,这就会导致组件传递写的很臃肿。这个时候就需要一个将状态(即state这个值)独立开来。
  2. react有很多状态管理的组件,比如redux,mobx。但redux写起来还是不如mobx简单明了。下面我们就来接入mobx。

接入步骤

  1. 安装依赖

    npm install mobx --save
    npm install mobx-react --save
  2. 启用装饰器语法

    # 如果有git的话,要将没有保存的文件上传之后或者删除之后才能跑eject命令
    yarn run eject
    npm install --save-dev babel-preset-mobx

    在package.json中找到babel项目,在presets里面增加"mobx"

    "babel": {  
    "presets": [    
    "react-app",   
    "mobx"  
    ]},
  3. 加入core-decorators

    npm install core-decorators --save
  4. 在src下增加store.AppStore.js文件

    import {action, observable} from "mobx";
    
    class AppStore {
        @observable todos;
    
        constructor() {
            this.todos = [{checked: false, text: "hello"}, {checked: true, text: "world"}]
        }
    
        @action.bound handleClick(index) {
            let todos = this.todos
            todos[index].checked = !todos[index].checked
        }
    }
    export default AppStore;
    
  5. 改写index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    import {Provider} from "mobx-react";
    import AppStore from './store/AppStore'
    
    let rootStore = {}
    rootStore['app'] = new AppStore()
    ReactDOM.render(
        <Provider {...rootStore}>
            <App/>
        </Provider>, document.getElementById('root'));
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: https://bit.ly/CRA-PWA
    serviceWorker.unregister();
    
  6. 改写App.js

    import React, {Component} from 'react';
    import './App.css';
    import {inject, observer} from "mobx-react";
    import {autobind} from "core-decorators";
    @inject("app")
    @autobind
    @observer
    class App extends Component {
        constructor(props) {
            super(props)
        }
    
        render() {
            let todos = this.props.app.todos
            let todosDiv = todos.map((item, index) => {
                return (<Todo index={index}/>)
            })
            return (
                <div className="App">
                    {todosDiv}
                </div>
            );
        }
    }
    
    
    @inject("app")
    @autobind
    @observer
    class Todo extends Component {
        constructor(props) {
            super(props)
        }
    
        handleClick() {
            let index = this.props.index
            this.props.app.handleClick(index)
        };
    
        render() {
            let index = this.props.index
            let todo = this.props.app.todos[index]
            return (
                <p><input type={'checkbox'} checked={todo.checked} onClick={this.handleClick}/>
                    {todo.text}:{index}
                </p>
            )
    
        }
    }
    
    
    export default App;
    
  7. npm start一下,来看看效果吧

简要说明

  1. @inject("app")表示注入在index.js中的rootStore的属性app。是由这个标签来实现动态的注入的
  2. @autobind 将组件之间的绑定自动完成
  3. @observer mobx用来将react组件转换为响应式组件的注解,详情查看mobx的文档
  4. 上面可以看出,将原本的state的属性抽离到AppStore中了,对值得更改方法也是直接调用AppStore的方法,从而避免了react组件的一级一级往上传递

C. 引入react-router作为多页面管理

提出问题

  1. 上面我们完成了单页面的开发。当需要多个页面时我们就需要使用react-router来对不同路径进行渲染了

接入react-router步骤

  1. 安装依赖

    npm install react-router mobx-react-router --save
  2. 增加新的页面,在src中增加component/Test.js

        import * as React from "react";
    
      class Test extends React.Component{
          render() {
              return(<p>welcome!</p>)
          }
      }
      export default Test;
  3. 更改index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    import {Provider} from "mobx-react";
    import AppStore from './store/AppStore'
    import {Route, Router, Switch} from "react-router";
    import {RouterStore, syncHistoryWithStore} from "mobx-react-router";
    import createHashHistory from "history/createHashHistory"
    import Test from "./component/Test"
    let rootStore = {}
    const hashHistory = createHashHistory()
    
    const routerStore = new RouterStore()
    const history = syncHistoryWithStore(hashHistory, routerStore)
    rootStore['app'] = new AppStore()
    routerStore['routing'] = routerStore
    
    ReactDOM.render(
        <Provider {...rootStore}>
            <Router history={history}>
                <p>here is the menu</p>
                <Switch>
                    <Route path={"/test"} component={Test}/>
                    <Route path={"/"} component={App}/>
                </Switch>
    
            </Router>
        </Provider>, document.getElementById('root'));
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: https://bit.ly/CRA-PWA
    serviceWorker.unregister();
    
  4. npm start一下,访问下/#/test,和/#/路径,看看效果吧

简要说明

  1. createHashHistory是单页面的访问,会在url加个#号作为定位,这个对于要打包到后台作为页面时是很方便的。
  2. 如果你直接使用node部署的话可以直接使用createBrowserHistory,url就会是没有#号的url。

D. 结合ui框架

接入步骤

  1. 找到一个合适的react ui框架,install之后按照ui框架的教程就可以开发一个相对比较好看的页面了
  2. 常见的框架有semantic,bootstrap,ant等。

E. 结合maven打包进spring boot项目

提出问题

  1. 当我们需要跟spring boot等后端项目结合,而又不想单独部署前端页面时,就需要打包进后端项目了

接入步骤

  1. 新建一个多模块的maven项目
  2. 按照之前创建的步骤,创建前端的模块,假设模块名字为view,并在前端模块的目录下增加pom.xml

    <build>
            <plugins>
                <plugin>
                    <groupId>com.github.eirslett</groupId>
                    <artifactId>frontend-maven-plugin</artifactId>
                    <version>1.2</version>
                    <executions>
                        &lt;-- Install our node and npm version to run npm/node scripts-->
                        <execution>
                            <id>install node and npm</id>
                            <goals>
                                <goal>install-node-and-npm</goal>
                            </goals>
                            <configuration>
                                &lt;-- 指定node的版本例如 v6.9.1 -->
                                <nodeVersion>${nodeVersion}</nodeVersion>
                                <npmVersion>${npmVersion}</npmVersion>
                                <nodeDownloadRoot>https://npm.taobao.org/mirrors/node/</nodeDownloadRoot>
                                <npmDownloadRoot>http://registry.npmjs.org/npm/-/</npmDownloadRoot>
                            </configuration>
                        </execution>
    
                        &lt;-- Set NPM Registry -->
                        <execution>
                            <id>npm set registry</id>
                            <goals>
                                <goal>npm</goal>
                            </goals>
                            <configuration>
                                &lt;--<arguments>config set registry https://registry.npmjs.org</arguments>-->
                                <arguments>config set registry https://registry.npm.taobao.org</arguments>
                            </configuration>
                        </execution>
    
                        &lt;-- Set SSL privilege -->
                        <execution>
                            <id>npm set non-strict ssl</id>
                            <goals>
                                <goal>npm</goal>
                            </goals>
                            &lt;-- Optional configuration which provides for running any npm command -->
                            <configuration>
                                <arguments>config set strict-ssl false</arguments>
                            </configuration>
                        </execution>
    
                        &lt;-- Install all project dependencies -->
                        <execution>
                            <id>npm install</id>
                            <goals>
                                <goal>npm</goal>
                            </goals>
                            &lt;-- optional: default phase is "generate-resources" -->
                            <phase>generate-resources</phase>
                            &lt;-- Optional configuration which provides for running any npm command -->
                            <configuration>
                                <arguments>install</arguments>
                            </configuration>
                        </execution>
    
                        &lt;-- Build and minify static files -->
                        <execution>
                            <id>npm run build</id>
                            <goals>
                                <goal>npm</goal>
                            </goals>
                            <configuration>
                                <arguments>run build</arguments>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
  3. 当进行mvn package时就会在目录下生成build目录,包含所有的页面和脚本了。
  4. 在spring boot后端项目中,将前端打包好的页面拷贝到后端目录中

     <build>
         <plugins>
             <plugin>
                 <artifactId>maven-resources-plugin</artifactId>
                 <executions>
                     <execution>
                         <id>Copy App Content</id>
                         <phase>generate-resources</phase>
                         <goals>
                             <goal>copy-resources</goal>
                         </goals>
                         <configuration>
                             <outputDirectory>src/main/resources/public</outputDirectory>
                             <overwrite>true</overwrite>
                             <resources>
                                 <resource>
                                     <directory>${project.parent.basedir}/view/build</directory>
                                     <includes>
                                         <include>static/</include>
                                         <include>index.html</include>
                                     </includes>
                                 </resource>
                             </resources>
                         </configuration>
                     </execution>
                 </executions>
             </plugin>
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
    • 其中outputDirectory指明要放入的文件夹
    • directory指明要拷贝哪里的资源文件,需要根据你的前端模块名进行相应的修改
    1. mvn package 一下,后端模块的打包jar里面就会有相应的资源文件啦

F. 前后端联调

步骤

  1. 在前端项目package.json中指明接口的代理
"proxy":"http://localhost:8080/"
  • 如果servletPath不为/,则需要在后面补上相应的servletPath
  1. 当你的后端项目有设置servletPath的时候,需要相应配置前端的打包的servletPath,否则默认为/的servletpath
  • 方法1: package.json 增加

    "homepage": "."
  • 方法2: config.paths.js文件下修改配置

    function getServedPath(appPackageJson) {
      const publicUrl = getPublicUrl(appPackageJson);
      //将/修改为./
      const servedUrl =
        envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : './');
      return ensureSlash(servedUrl, true);
    }

G. 将你创建好的项目做成脚手架

提出问题

  1. 如果每个项目都要经历上面的步骤,才能完成,那前期工作量是在太繁琐又重复
  2. 借助maven的archetype来帮你自动生成一个初始项目吧

接入步骤

  1. 按照上面的流程我们已经建好了项目
  2. 在项目目录下执行 mvn archetype:create-from-project,生成的target就是你的脚手架项目
  3. cd target/generated-sources/archetype 目录下,执行mvn install 就把archetype放入了本地仓库了,可以进行使用了
  4. 为了deploy到远程仓库中,需要在target/generated-sources/archetype 目录下的pom.xml中加入自己的远程仓库的地址,然后在target/generated-sources/archetype 目录下mvn deploy就可以了

屏蔽掉部分不想打包进archetype的文件

  1. 要屏蔽部分文件夹时在pom中加入plugin
<plugin>
                <artifactId>maven-archetype-plugin</artifactId>
                <version>3.0.1</version>
                <configuration>
                    <propertyFile>archetype.properties</propertyFile>
                </configuration>
            </plugin>
  1. 新建archetype.properties文件,配置要忽略的通配符excludePatterns=/.idea/,**.iml

怎么使用archetype

  1. 创建项目在idea中,在点击file-> new-> project后弹出的对话框中选择maven
  2. 在create from archetype打勾,点击Add archetype加入创建好的archetype
  3. 填写对应的groupId,artifaceId,version后在列表中选择已有的archetype
  4. 按引导进行后续步骤的创建,然后就会自动生成跟你项目一样的啦

跨store的访问

什么是跨store访问

  1. 在上面我们有这样的代码
const routerStore = new RouterStore() 
rootStore['app'] = new AppStore() 
routerStore['routing'] = routerStore
  1. 有时候我们往往需要在一个store的方法中去访问下别的store的内容,这个时候就是跨store的访问,就需要在初始化时将rootStore传给这个store,通过rootStore去访问,改写index.js
rootStore['app'] = new AppStore(rootStore) 

改写AppStore.js,增加构造函数

constructor(rootStore) {
        this.rootStore = rootStore
    }
  1. 这样就可以在AppStore.js的函数中通过this.rootStore 去获取所有store的json,从而访问所有的store了
目录
相关文章
|
3月前
|
前端开发 JavaScript
使用 MobX 优化 React 代码
使用 MobX 优化 React 代码
34 0
|
7月前
|
缓存 前端开发 API
React + MobX 快速上手2
React + MobX 快速上手
|
3月前
|
存储 JavaScript 开发者
Mobx+Mobx-React快速上手 简单可扩展的状态管理解决方案
Mobx+Mobx-React快速上手 简单可扩展的状态管理解决方案
29 0
|
5月前
从零开始学习React-路由react-router配置(四)
从零开始学习React-路由react-router配置(四)
17 0
|
5月前
|
前端开发 Java 数据库连接
基于SpringBoot+Mybatis plus+React.js实现条件选择切换搜索功能
基于SpringBoot+Mybatis plus+React.js实现条件选择切换搜索功能
27 0
|
6月前
|
前端开发 JavaScript 容器
React的魅力: React-Router-集中式管理和Redux-核心概念
React的魅力: React-Router-集中式管理和Redux-核心概念
43 1
|
7月前
|
缓存 移动开发 前端开发
【React】react-router 路由详解
【React】react-router 路由详解
258 1
【React】react-router 路由详解
|
7月前
|
存储 前端开发
React + MobX 快速上手1
React + MobX 快速上手
|
8月前
|
Java Maven
打通Maven中Pom.xml与SpringBoot多环境配置
通过pom.xml配置profiles节点,以及自定义打包配置文件实现SpringBoot多环境文件配置
349 0
|
8月前
|
XML Java API
一张思维导图带你打通SpringBoot自定义拦截器的思路
一张思维导图带你打通SpringBoot自定义拦截器的思路
62 0