30分鐘極速通關react mobx react-router及打通springboot

內容導航

  1. 簡單開發react
  2. 將react與mobx結合開發
  3. 使用react-router進行多頁面開發
  4. 將項目打包到後端項目中進行部署
  5. 將完成的項目作成腳手架,避免重複的環境搭建

須要環境

  1. 確保node已經安裝
  2. 確保npm已經安裝

建立項目

npx create-react-app test 
# test 爲你須要建立項目的名字,會在命令當前目錄下建立test的目錄,包含項目全部的文件

你已經完成了建立,開始跑起來css

npm start

你能夠看到react已經可以在local host:3000訪問了,只有一個歡迎頁面html

目錄結構

目錄結構圖

    1. node_modules

    是當前目錄安裝的模塊存放的地方前端

    1. public

    index.html 是單頁面的入口node

    1. src

    可存放本身編寫的代碼,App是默認生成的歡迎頁面邏輯,index 是js的主入口react

開始更改你的代碼

A. react簡單開發

1.將App.js的代碼更改以下git

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一下看看效果吧~

效果圖

  1. 能夠看到咱們組件已經可以響應點擊了

B. 引入mobx做爲狀態管理

提出問題

  1. 在上面咱們能夠看到想要更改狀態是比較困難的,首先要將handClick方法由子組件傳給父組件,再進行處理。若是咱們的組件是

四五層組件的時候得一步一步的往上級傳遞,這就會致使組件傳遞寫的很臃腫。這個時候就須要一個將狀態(即state這個值)獨立開來。github

  1. react有不少狀態管理的組件,好比redux,mobx。但redux寫起來仍是不如mobx簡單明瞭。下面咱們就來接入mobx。

接入步驟

  1. 安裝依賴spring

    npm install mobx --save
    npm install mobx-react --save
  2. 啓用裝飾器語法npm

    # 若是有git的話,要將沒有保存的文件上傳以後或者刪除以後才能跑eject命令
    yarn run eject
    npm install --save-dev babel-preset-mobx

    在package.json中找到babel項目,在presets裏面增長"mobx"json

    "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;

```
  1. npm start一下,來看看效果吧

簡要說明

  1. @inject("app")表示注入在index.js中的rootStore的屬性app。是由<Provider {...rootStore}>這個標籤來實現動態的注入的
  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了
    相關文章
    相關標籤/搜索