react学习笔记(react基础+react全家桶+ant-ui知识)知识点边学边更新


title: react 第一次实战项目知识点记录

基础知识点项目地址:https://github.com/yangxinjian/reactPractice.git
完整项目地址(主要是这个)
https://github.com/yangxinjian/reactAntBike.git

环境配置

安装node.js(官网下载即可)

node -v (查看是否安装node完成)

安装yarn新一代的包管理工具facebook开发,你也可以选择cnpm

  • yarn的速度会比npm快
  • 安装版本统一,更安全
  • 更简洁的输出
  • 更好的语义化
sudo cnpm install yarn -g
yarn -v(查看是否安装yarn完成)

使用git在马云上进行托管,并在本地clone下来项目

git clone 你项目的地址
cd 你的项目

配置gitignore(git命令忽视)

vim .gitignore
i(编辑命令)
.DS_Store (Mac自带)
node_modules (node包)
dist (打包的压缩文件)
*.log(错误信息等)

初始化项目

yarn init  / cnpm init

提交项目

git add . (保存到暂存区)
git commit -m '备注信息' (把暂存区内容保存到分支)
git pull (拉取其他分支代码)
git push (将更新内容提交进入远程分支)

安装webpack打包工具(配置规则查看webpack章节)

yarn add webpack --dev / cnpm install webpack --dev
在根目录下创建一个webpack.config.js文件

1. 需要处理的文件类型
  
    html => html-webpack=plugin
    js es6 => babel + babel-preset-react
    css => css-loader + sass-loader
    img => url-loader + file-loader

2. 常用模块

    html-webpack-plugin => html单独打包成文件
    extract-text-webpack-plugin => 样式打包成单独文件
    CommonsChunkPlugin => 提出通用模块

3. webpack-dev-server

      (1) 为webpack项目提供web服务  
      (2) 更改代码自动刷新,路径转发
      (3) yarn add webpack-dev-server --dev
      (4) 解决多版本共存
1.配置webpack,在创建好的webpack.config.js中配置
  • 添加模块输出口

        const path = require('path')
        module.exports = {
            entry: './src/app.js',
            output: {
                path: path.resolve(__dirname, 'dist'), // __dirname代表根目录
                filename: '你想输出的文件名字.js'
            }
        }
    
  • 添加html插件

        yarn add html-webpack-plugin --dev // 生成html5文件插件
        
        在webpack.config.js中设置
    
         const path = require('path')
         const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
         module.exports = {
            entry: './src/app.js',
            output: {
                path: path.resolve(__dirname, 'dist'), 
                filename: '你想输出的文件名字.js'
            },
            plugins: [ // 使用插件
                new HtmlWebpackPlugin({
                      template: '.src/index.html' // 引用模板自定义html文件,使打包出来的html与此文件一致
                })
            ]
        }
    
  • 添加babel插件 (将es6语言转换成es5)

         yarn add [email protected] [email protected] [email protected] --dev // 安装
       
         在webpack.config.js配置
         const path = require('path')
         const HtmlWebpackPlugin = require('html-webpack-plugin')
    
         module.exports = {
            entry: './src/app.js',
             output: {
                 path: path.resolve(__dirname, 'dist'),
                 filename: 'app.js'
             },
             module: {
                 rules: [
                     {
                         test: /\.js$/,
                         exclude: /(node_modules)/,// 将不需要装换的文件夹排除
                         use: {
                             loader: 'babel-loader',
                             options: {
                                 presets: ['env']
                             }
                         }
                     }
                 ]
             },
              plugins: [
                 new HtmlWebpackPlugin({
                     template: '.src/index.html'// 引用自定义html文件
                 }) // 生成html5文件
             ]
         }
    
  • 安装react的插件
    yarn add babel-preset-react --dev / cnpm install babel-preset-react --dev

          yarn add html-webpack-plugin --dev // 生成html5文件插件
      
      在webpack.config.js中设置
    
       const path = require('path')
       const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
       module.exports = {
          entry: './src/app.js',
          output: {
              path: path.resolve(__dirname, 'dist'), 
              filename: '你想输出的文件名字.js'
          },
          plugins: [ // 使用插件
              new HtmlWebpackPlugin({
                    template: '.src/index.html' // 引用模板自定义html文件,使打包出来的html与此文件一致
              })
          ]
      }
    
  • 添加babel插件 (将es6语言转换成es5)

         yarn add [email protected] [email protected] [email protected] --dev // 安装
       
         在webpack.config.js配置
         const path = require('path')
         const HtmlWebpackPlugin = require('html-webpack-plugin')
    
         module.exports = {
            entry: './src/app.js',
             output: {
                 path: path.resolve(__dirname, 'dist'),
                 filename: 'app.js'
             },
             module: {
                 rules: [
                     {
                         test: /\.js$/,
                         exclude: /(node_modules)/,// 将不需要装换的文件夹排除
                         use: {
                             loader: 'babel-loader',
                             options: {
                                 presets: ['env', 'react'] // 只需要在这里引用react
                             }
                         }
                     }
                 ]
             },
              plugins: [
                 new HtmlWebpackPlugin({
                     template: '.src/index.html'// 引用自定义html文件
                 }) // 生成html5文件
             ]
         }
    
  • 安装样式的插件

    > 安装css
    yarn add [email protected] [email protected] --dev
    
    在项目src中新建一个index.css页面,并在app.jsx中引入页面
    import React from 'react'
    import ReactDOM from 'react-dom'
    import './index.css'
    
    安装webpack打包css成独立文件的插件
    yarn add [email protected] --dev
    
    在webpack.config.js中更改对css的配置配置
    
    引入 
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    
     {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({ // 这里改变
                fallback: 'style-loader',
                use: 'css-loader'
            })
      }
    由于这是一个插件,需要在plugin中配置
    
    > 安装sass
    
    yarn add sass-loader --dev
    yarn add node-sass --dev
    
    在webpack.config.js中rules css配置下添加
     {
            test: /\.scss$/,
            use: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: ['css-loader', 'sass-loader']
            })
      }
    
  • 对图片的处理

    yarn add url-loader --sev
    
    在webpack.config.js中配置
    {
              test: /\.(png|jpg|gif)$/,
              use: [
                  {
                      loader: 'url-loader',
                      options:{
                          limit: 8192 // 文件大于8k被当做文件
                      } 
                  }
              ]
     }
    
  • 对字体图标的处理

    yarn add font-awesome
    
    {
              test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
              use: [
                  {
                      loader: 'url-loader',
                      options:{
                          limit: 8192 // 文件大于8k被当做文件
                      } 
                  }
              ]
     }
    
  • 对公共模块的处理

在plugin中处理

   const path = require('path')
   const webpack = require('webpack')  //为了引用webpack自带方法
   const HtmlWebpackPlugin = require('html-webpack-plugin')
   const ExtractTextPlugin = require('extract-text-webpack-plugin')

   module.exports = {
       entry: './src/app.jsx',
       output: {
           path: path.resolve(__dirname, 'dist'),
           filename: 'js/app.js'
       },
       module: {
           rules: [
               {
                   test: /\.jsx$/,
                   exclude: /(node_modules)/, // 将不需要装换的文件夹排除
                   use: {
                       loader: 'babel-loader',
                       options: {
                           presets: ['env', 'react'] // 自动根据环境打包
                       }
                   }
              },
               {
                   test: /\.css$/,
                   use: ExtractTextPlugin.extract({
                       fallback: 'style-loader',
                       use: ['css-loader']
                   })
               },
               {
                   test: /\.scss$/,
                   use: ExtractTextPlugin.extract({
                       fallback: 'style-loader',
                       use: ['css-loader', 'sass-loader']
                   })
               },
               {
                   test: /\.(png|jpg|gif|jpeg)$/,
                   use: [
                       {
                           loader: 'url-loader',
                           options:{
                               limit: 8192, // 文件大于8k被当做文件
                               name: 'resource/[name].[ext]'
                           } 
                       }
                   ]
               },
               {
                   test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
                   use: [
                       {
                           loader: 'url-loader',
                           options:{
                               limit: 8192, // 文件大于8k被当做文件
                               name: 'resource/[name].[ext]'
                           } 
                       }
                   ]
               }
           ]
       },
       plugins: [
           new HtmlWebpackPlugin({
               template: './src/index.html'// 引用自定义html文件
           }), // 生成html5文件
           new ExtractTextPlugin('css/[name].css'), // 将样式单独打包出来生成新的css页面
           // 提出公共模块,webpack自带
           new webpack.optimize.CommonsChunkPlugin({
               name: 'common',// 手动指定的通用木块
               filename: 'js/base.js'
           })
       ]
   }
  • webpack 自动刷新处理webpack-dev-server

      yarn add webpack-dev-server
    
      在config下与plugin同级加上
      devServer: {
      }
      为了防止打包后的图片在根目录下找不到
      output: {
          path: path.resolve(__dirname, 'dist'),
          publicPath: '/dist/',  //在这里添加路径
          filename: 'js/app.js'
      },
    
      编译打包就用webpack-dev-server就可以了
    

使用react环境搭建项目

      yarn add react react-dom

      在app.js中引用react结构,并将app.js的后缀更改为jsx,webpack.config.js中的js配置也要变成jsx,入口文件的js也要更改为jsx

      import React from 'react'
      import ReactDOM from 'react-dom'

package.json的配置

      "scripts": {
        "dev": "node_modules/.bin/webpack-dev-server",
        "dist": "node_modules/.bin/webpack -p"
      },

这样就可以使用yarn dev启动项目
yarn dist 打包项目

react正式开始咯(上诉方法均为自己手打搭建一个react项目,了解每一步,接下来是react提供的项目创建方法)

react => 视图层框架 组件化 JSX表达式 虚拟DOM
  • Facebook 开源的一个JavaScript库
  • React结合生态库构成一个MVC框架(vue也是mvc)
  • 特点:Declarative(声明式编码:只需要声明在哪里做什么,无需关心如何实现);Component-Based(组件化编码);高效-高效的DOM Diff算法,最小化页面重绘
  • 单向数据流
生态介绍

vue生态:vue + vue-router + vuex + axios + babel + webpack
react生态: react + react-router + redux + axios + babel + webpack

项目的创建(另一种方式,但是本人喜欢上面的手动配置,看得懂)

  yarn add / cnpm  install global/-g create-react-app (全局安装)
  在工作区创建项目

  create-react-app 你的项目名称

  cd 你的项目名称

  cnpm / yarn start 启动

JSX语法

  • 添加html

    let jsx = 
    this is a jsx programmer
    ReactDOM.render( jsx, // 将jsx组件放到渲染的dom下 document.getElementById('app) )
  • 添加样式

    行内样式
    let style = {
        color: 'red'
    }
    let jsx = 
    引入class样式 在index.scss中设置 body { .jsx { font-size: 16px; } } let jsx =
    // react中使用className引用样式名称
  • 添加逻辑
    (1)使用变量

        let name = "pig"
        let jsx = 
    I am a {pig}
    ReactDom.render( jsx, document.getElementById('app') )

    (2)条件判断

         let truth = true
         let jsx = (//加括号的目的是为了换行的时候,编辑器不会给我们自动填补分号
              
    { // 条件判断需要加上{} truth ?

    I am a pig

    :

    I am not a pig

    }
    )

    (3)jsx中插入注释

          {/*我是一个注释*/} 
    

    (4)数组的使用

          let names = ['pig', 'dog', 'chicken']
          let jsx = (
              {
                  names.map((name,index) => 

    I am {name}

    ) } )
  • 添加组件
    (1)基础

          function Component () {
                return 

    I am a pig

    } ReactDom.render( , // 如果是变量直接饮用,如果是组件需要加上标签 document.getElementById('app') )

    (2)es6组件写法

          class ES6Component extends React.Component{
                render () {
                      return 

    I am a pig in es6

    } } ReactDom.render(
    // 两个组件共存需要包裹在一个div中
    , document.getElementById('app') )

    (3)组件初始化变量

          class Component extends React.Component {
                constructor (props) {
                      super(props);
                      this.state = {
                            name: 'pig'
                      }
                }
                render () {
                     return 

    I am a {this.state.pig}

    } }

    (4)更改组件初始化变量

          class Component extends React.Component {
                constructor (props) { // props在子组件中只能被使用不能被改变
                      super(props);
                      this.state = {
                            name: 'pig'
                      }
                }
                render () {
                    setTimeOut(() => {
                           this.setState({
                              name: 'Pi g Pig'
                           })
                    }, 2000)
                     return 

    I am a {this.state.pig}

    } }

    (5)父组件传值

          class Component extends React.Component {
                constructor (props) {
                      super(props)
                }
                render () {
                     return 

    I am a {this.props.name}

    } } ReactDom.render( , docuement.getElementById('app') )

    (6)组件添加点击事件(方法一)

          class Component extends React.Component {
                constructor (props) {
                      super(props);
                      this.state = {
                          age: 18
                      }
                      this.addAge = this.addAge.bind(this)
                }
                addAge () {
                    this.setState({
                        age : this.state.age + 1
                    })
                }
                render () {
                     return (
                          

    I am {this.state.age} years old

    ) } } ReactDom.render( , docuement.getElementById('app') )

(7)组件添加点击事件(方法二)

        class Component extends React.Component {
              constructor (props) {
                    super(props);
                    this.state = {
                        age: 18
                    }
              }
              addAge () {
                  this.setState({
                      age : this.state.age + 1
                  })
              }
              render () {
                   return (
                        

I am {this.state.age} years old

) } } ReactDom.render( , docuement.getElementById('app') )

(8)组件添加输入框更改事件

        class Component extends React.Component {
              constructor (props) {
                    super(props);
                    this.state = {
                        age: 18
                    }
              }
              changeValue (e) {
                  this.setState({
                      age : e.target.value
                  })
              }
              render () {
                   return (
                        

I am {this.state.age} years old

{this.changeValue(e)}} />
) } } ReactDom.render( , docuement.getElementById('app') )

(9)容器性组件嵌套组件

        class Component extends React.Component {
              constructor (props) {
                    super(props);
                    this.state = {
                        age: 18
                    }
              }
              changeValue (e) {
                  this.setState({
                      age : e.target.value
                  })
              }
              render () {
                   return (
                        

I am {this.state.age} years old

{this.changeValue(e)}} />
) } } class Title extends React.Component{ constuctor (props) { super(props) } render (props) { return

{this.props.title}

} } class App extends React.Component{ render () { return (
<Component /> // 在这里引用小组件component </div> ) } } ReactDom.render( <App />, // 这里换成App docuement.getElementById('app') ) </code></pre> <p>(10)组件嵌套组件</p> <pre><code> class Component extends React.Component { constructor (props) { super(props); this.state = { age: 18 } } changeValue (e) { this.setState({ age : e.target.value }) } render () { return ( <div> <h1>I am {this.state.age} years old </h1> <input type="text" onChange={(e) => {this.changeValue(e)}} /> </div> ) } } class App extends React.Component{ render () { return ( <div> <h1>app</h1> <Component /> // 在这里引用小组件component </div> ) } } ReactDom.render( <App />, // 这里换成App docuement.getElementById('app') ) </code></pre> <p>(11)容器性组件嵌套组件,传值可以为任何html形式</p> <pre><code> class Component extends React.Component { constructor (props) { super(props); this.state = { age: 18 } } changeValue (e) { this.setState({ age : e.target.value }) } render () { return ( <div> <h1>I am {this.state.age} years old </h1> <input type="text" onChange={(e) => {this.changeValue(e)}} /> </div> ) } } class Title extends React.Component{ constuctor (props) { super(props) } render (props) { return <h1>{this.props.children}</h1> // 这里变成获取子children } } class App extends React.Component{ render () { return ( <div> <Title> <span>我是spanspan</span> <a href="">link</a> //更改为html形式
) } } ReactDom.render( , // 这里换成App docuement.getElementById('app') )

(12)子组件给父组件传值

    class Father extends React.Component {
       constructor (props) {
           super(props);
           this.state = {
               bgColor: 'red'
           }
       }
       changeMyBgColors (color) {
           this.setState({
               bgColor: color
           })
       }
       render () {
           return (
               

我是爸爸

{this.changeMyBgColors(color)}}/>
) } } class Child extends React.Component { constructor (props) { super(props) } changeMyBgColor () { this.props.changeColor('blue') } render () { return (

我是baby

) } } ReactDOM.render( , document.getElementById('app') )

(13)兄弟之间的组件通信(子1传父,父在传子2)

        class Child1 extends React.Component{
           constructor (props) {
               super(props)
               this.state = {
                   color1: 'red'
               }
           }
           changeMyBrotherColor (props) {
               this.props.change2Color(this.state.color1)
           }
           render () {
               return (
                   

我是孩子1

) } } class Child2 extends React.Component{ constructor (props) { super(props) } render () { return (

我是孩子2

) } } class Father extends React.Component{ constructor (props) { super(props) this.state = { color2: 'yellow' } } changColor (colorsss) { this.setState({ color2: colorsss }) } render () { return (

这是我的孩子们

{this.changColor(color)}}/>
) } } ReactDOM.render( , document.getElementById('app') )

react生命周期

getDefaultProps // 初始化props属性,props来自其他组件
getInitialState // 初始化组件的状态
componentWillMount // 组件加载之前
render // 渲染
componentDidMount // 组件dom插入之后
componentWillReceiveProps // 接受父组件的传递
shouldComponentUpdate // 组件的更新处罚
componentWillUpdate // 组件要更新前
componentDidUpdate // 组件更新后
componentWillUnmount // 组件的销毁

  • Mounting : 挂载阶段

  • Updating: 运行时阶段

  • Unmounting: 卸载阶段

  • Error Handling: 错误处理

    import React from 'react'
    import ReactDOM from 'react-dom'
    
    import './index.scss'
    
    class Child extends React.Component{
        // 构造函数
       constructor (props) {
            super(props)
            this.state = {
                data: 'oldzhuzhu'
            }
            console.log('这里是初始化数据constructor')
        }
        componentWillMount () {
            // 组件渲染前
            console.log('componentWillMount')
        }
        componentDidMount () {
            // 组件渲染结束
            console.log('componentDidMount')
        }
        componentWillReceiveProps () {
            // 将要接受父组件传来的props触发
            console.log('componentWillReceiveProps')
        }
        shouldComponentUpdate () {
            // 子组件是不是应该更新
            console.log('shouldComponentUpdate')
            return true
            // 如果是false,后面的update就不会跟着更新
        }
        componentWillUpdate () {
            // 组件将要更新
            console.log('componentWillUpdate')
        }
        componentDidUpdate () {
            // 组件更新完成
            console.log('componentDidUpdate')
        }
        componentWillUnmount () {
            // 组件将要销毁调用
            console.log('componentWillUnmount')
        }
        // 点击事件
        handleClick () {
            console.log('这里是更新数组')
            this.setState({
                data: 'zhuzhuzhu'
            })
        }
        // 渲染
        render () {
            console.log('render')
            return (
                
    {this.state.data} 接收到的props: {this.props.data}
    ) } } class Father extends React.Component{ constructor (props) { super(props) this.state = { data: 'old props' } } changeData () { this.setState({ data: 'new props', show: true }) } byeChild () { this.setState({ show: false }) } render () { return (
    { this.state.show ? : null }
    ) } } ReactDOM.render( , document.getElementById('app') )

按顺序输出值:

constructor  // 构造函数初始化
componentWillMount  // 组件渲染前
render  // 组价渲染
componentDidMount  // 选件渲染完成
componentWillReceiveProps  // 子组件接收到父组件传来的props
shouldComponentUpdate  // 是否组件进行更新,true更新,false接下来的周期不触发
componentWillUpdate  // 组件更新前
render  //  更新
componentDidUpdate  // 组件更新结束
componentWillUnmount  // 组件被摧毁之前

react-router

1.router几种方式
  • 页面路由

      window.location.href = '地址' // www.baidu.com
      history.back()  //回退
    
  • hash 路由

    window.location = '#hash'
    window.onhashchange = function () {
        console.log('current hash' + window.location.hash)
    }
    
  • h5路由

    history.pushState('name', 'title', '/path')  // 推进一个状态
    history.replaceState('name', 'title', '/path') // 更换一个状态
    window.onpopstate = function () {
        console.log(window.location.href)
        console.log(window.location.pathname)
        console.log(window.location.hash)
        console.log(window.location.search)
    }
    
2. react-router几种方式
  • hash

      import React from 'react'
      import ReactDOM from 'react-dom'
      import {HashRouter as Router,Route,Link} from 'react-router-dom'  // 这里是Hash
    
      import './index.scss'
    
      class A extends React.Component {
          constructor (props) {
              super(props)
          }
          render () {
              return (
                  
    Component A
    ) } } class B extends React.Component { constructor (props) { super(props) } render () { return (
    Component B
    ) } } class Wrapper extends React.Component { constructor (props) { super(props) } render () { return (
    组件A
    组件B {this.props.children}
    ) } } ReactDOM.render( , document.getElementById('app') )
  • browser

    如果改成
    import {BrowserRouter as Router,Route,Link} from 'react-router-dom'
    路径地址都会变成 http://localhost:8080/a,
    此时请求的是后端代码,在复制这个链接在其他页面打开时,会报成404,因为后台并没有生成这个地址
    
3.router传参,组件接受不同组件传参
  • 引入switch
    import {HashRouter as Router,Route,Link,Switch} from 'react-router-dom'
  class A extends React.Component {
      constructor (props) {
          super(props)
      }
      render () {
          return (
              
Component A { return
当前组件是不带参数的A
}} /> path={`${this.props.match.path}/sub`} render={(route) => { return
当前组件是sub
}} /> { return
当前组件是带参数的A,参数是 : {route.match.params.id}
}}/>
) } } class B extends React.Component { constructor (props) { super(props) } render () { return (
Component B
) } } class Wrapper extends React.Component { constructor (props) { super(props) } render () { return (
组件A
带参数的组件A
/a/sub子路径
组件B {this.props.children}
) } } ReactDOM.render( , document.getElementById('app') )

开始正式共享单车项目知识点(react全家桶+ant ui 组件+公共机制封装)

地址:https://github.com/yangxinjian/reactAntBike.git

  • react基础知识,生命周期(见上部分的基础知识点)
  • router4.0
  • redux集成开发
  • ant最实用基础组件
  • ant栅格系统
  • Etable组件封装
  • BaseForm组件封装
  • 表格内嵌单选,复选封装
  • axios请求插件封装
  • api封装
  • 错误拦截
  • 权限,菜单封装等
  • 地图,图表的使用

安装脚手架(上述有步骤,可选择自己搭建,也可以使用官方脚手架)

sudo cnpm install -g create-react-app

初始化项目

create-react-app bikesystem (你项目的名称:注意不用大写字母)

安装react-router

yarn add react-router

启动项目

yarn start

项目所需要的插件

  • 安装react-router,axios
  • 安装AntD
  • 暴露webpack配置文件
  • 安装less-loader
  • 修改less-loader
sudo yarn add react-router-dom axios less-loader
sudo yarn add less
sudo yarn antd   (支付宝做的ui组件)

引用antd样式

  import {Button} from 'antd'  // 引用某一个组件
  
  import 'antd/dist/antd.css'
  • 想要按需加载对应组件css,需要安装babel,安装后就无需引用上面的css
 sudo yarn add babel-plugin-import
 sudo yarn add less@^2.7.3
  在package.json 的babel下加入
  "plugins": [
  [
    "import",
    {
      "libraryName": "antd",
      "style": "css"
    }
  ]
]

暴露webpack文件,得到config文件夹

sudo yarn eject

更改config/webpack.config.js ,使项目能识别less文件,配置后重启生效

  • 在 // style files regexes下 添加
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
  • 在 cssRegex引用后面下 添加less配置对象
{
          test: lessRegex,
          exclude: lessModuleRegex,
          use: getStyleLoaders(
            {
              importLoaders: 3,  // 这里不要与其他配置的数字一样
              sourceMap: isEnvProduction && shouldUseSourceMap,
            },
            'less-loader'
          ),
          sideEffects: true,
        },
        {
          test: lessModuleRegex,
          use: getStyleLoaders(
            {
              importLoaders: 3,  // 这里不要与其他配置的数字一样
              sourceMap: isEnvProduction && shouldUseSourceMap,
              modules: true,
              getLocalIdent: getCSSModuleLocalIdent,
            },
            'less-loader'
          ),
        },

项目架构

  • 在src中新建组件文件夹,取名component,分别根据项目搭建出header头部文件夹,footer底部文件夹,NavLeft左菜单文件夹,以及在src下新建admin.js


    react学习笔记(react基础+react全家桶+ant-ui知识)知识点边学边更新_第1张图片
    Jietu20190401-163524.jpg

    在admin.js中配置主结构,用row,col,并引入三个外部组件,注意!!!三个外部组件的内容不能为空,否则会报错

          import React from 'react'
         import { Row, Col} from 'antd';
         import Header from './components/header';
         import Footer from './components/footer';
    
         export default class Admin extends React.Component{
             render () {
                 return (
                     
                         
                             left
                         
                         
                             
    header
    contet
    footer
    ) } }
  • 作为主要的菜单结构,单独封装出一个js,写在了config下的menuConfig.js中,请大家自行git clone 我的项目地址,本项目是开源的项目

  • public里文件是将要被打包部署到服务器上。一般是图片等元素信息

项目中使用的功能方法

1. 请求外部的百度地图下的天气API

  • 先在百度地图开放平台,创建应用,选择浏览器,生成自己的AK码

  • 在代码中安装jsonp

     sudo yarn add jsonp --save
    
  • 封装jsonp方法

      import JsonP from 'jsonp'
      export default class Axios {
          // 链式调用
          static jsonp (options) {
              return new Promise((resolve, reject) => {
                  JsonP(options.url,{
                      param: 'callback'
                  },function(err, response){
                      if (response.status == 'success') { // 成功回调
                          resolve(response);
                      } else {
                          reject(response.messsage); //  失败回调
                      }
                  })
              })
          }
      }
    
  • 在组件中调用

    import axios from '../../axios'
    state={}
    componentWillMount () {
        this.getWeatherAPIData() // 调用方法
    }
    // 获取天气api,encodeURIComponent编码对中文的处理
    getWeatherAPIData () {
            let city = '北京'
            axios.jsonp({
                url: 'http://api.map.baidu.com/telematics/v3/weather?location='+encodeURIComponent(city)+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'  // api地址 , ak是你自己申请的应用ak
            }).then((res) => {
                if(res.status == 'success'){
                    let data = res.results[0].weather_data[0];  // 取当前的天气
                    this.setState({
                        dayPictureUrl:data.dayPictureUrl,
                        weather:data.weather
                    })
                }
            })
        }
            // 在render中渲染
           
               
            
             
                  {this.state.weather}
             
    

2.react-router4.0(不需要路由配置,一切皆组件,浏览器端)

  • 核心用法:

    1. HashRouter和BrowserRouter

       hash: http://localhost:3000/#/admin
       browser: http://localhost:3000/admin
      

    2.Route:path,exact,component,render --- 参考项目中的pages下的router-demo下的router2文件夹的内容

           
               // home 是主界面,包含的都是他的子组件路由
                  
                  
                  
              
          
    
          主界面加载子组件的地方,添加{this.props.children}
    

    3.NavLink,Link ------ 通过this.props.match接受路由带的内容--- 参考项目中的pages下的router-demo下的router1文件夹的内容

          
              {/* 需要根节点 */}
              
    • Home
    • About
    • Topics
    {/* /about会检索到/和/about,所以防止加载两次,加上exact精确匹配 */}

    4.Switch

          
                      {/* switch只会加载一次,按顺序 */}
                      
                      
                      
                  
    

    5.Redict

          
    
    1. withRouter 直接跳转路由
      import {withRouter} from 'react-router-dom'   引入

      使用
      this.props.history.push({
              pathname: '/admin'
      })

      渲染,在export default 中增添
      withRouter(Form.create()(OrganizeManage))

3.项目中运用router实现菜单导航路由

  1. 根路由的编写
  • 在src目录下建立router.js文件 , 并在全局index.js中更换Router

  • 在router.js中引用app.js作为主框架

     import React from 'react'
     import {HashRouter, Route, Switch} from 'react-router-dom'
     import App from './App'
     import Login from './pages/login'
     import Admin from './admin'
     export default class IRouter extends React.Component{
         render () {
             return (
                 
                     
                          (一级路由--登录界面)
                          (一级路由--登录进来的页面)
                     
                 
             )
         }
     }
    
  • 在app中引用子路由

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    class App extends Component {
      render() {
        return (
          
    {this.props.children}
    ); } } export default App;
  • 在一级路由下嵌套二级路由,更改的admin界面下的路由配置

         
                      // 二级路由
                      
                          
                      
                  }/>
    
      在admin.js中更改
      
                     {this.props.children}  // 这里引用
                  
    
  • 菜单路由link配置

     引用路由 在NavLeft页面下
    import {NavLink} from 'react-router-dom'
    在menu-item中包裹路由
    
                  {item.title}  // 这里跳转地址
              
    
  • 配置路由加载错误的情况下的展示页面

先建立文件夹nomatch包裹404展示文件,再在路由里面引用

   
               
                
   

Ant design UI组件的基本使用

  • 在项目地址下的ui文件夹有基本的使用展示,你可以选择clone我的项目下到本地进行查看,接下来的笔记介绍几种初学者会遇到的使用

1. form组件实现登录

  • 创建用户名和密码以及登录摁钮

        需要引用FormItem
        const FormItem = Form.item
        
    } placeholder="请输入用户名"/> } placeholder="请输入密码"/>
  • 添加输入验证
    第一步:在render中创建getFieldDecorator对象

      const { getFieldDecorator } = this.props.form;
    

    第二步:给标签内嵌入js语法实现验证

                    
                          {
                              getFieldDecorator('userName',{ // username是定义的用户名变量,不同输入框的命名要是分别的
                                  initialValue:'',
                                  rules:[
                                      {
                                          required:true,
                                          message:'用户名不能为空'
                                      },
                                      {
                                          min:5,max:10,
                                          message:'长度不在范围内'
                                      },
                                      {
                                          pattern:new RegExp('^\\w+$','g'),  // 正则表达式都可以
                                          message:'用户名必须为字母或者数字'
                                      }
                                  ]
                              })(
                                  } placeholder="请输入用户名" />
                              )
                          }
                      
    

    第三步:通过Form创建表单

      class FormLogin extends React.Component 将前面的export default 去掉
      
      export default Form.create()(FormLogin); 在结尾中加入
    
  • 添加摁钮点击校验
    第一步: 给摁钮绑定事件

        
    

    第二步:编写事件

    handleSubmit = ()=>{
      let userInfo = this.props.form.getFieldsValue();
      this.props.form.validateFields((err,values)=>{
          if(!err){ // 如果没有错的情况下
              message.success(`${userInfo.userName} 恭喜你,您通过本次表单组件学习,当前密码为:${userInfo.userPwd}`)
          }
      })
    }
    

2. datePicker日期控件的引用

想要设置默认值,需要引用moment插件

     sudo yarn add moment --save

        import moment from 'moment
            
                        {
                            getFieldDecorator('birth', {
                                initialValue: moment('2018-08-08') , // 获取moment
                                rules: [
                                    {
                                        required: true
                                    }
                                ]
                            })(
                                
                            )
                        }
                    

3.栅格左右大小分配格式提取

    const formItemLayout = { // 栅格样式 复用
        labelCol: {
            xs: 24,
            sm: 4
        },
        wrapperCol: {
            xs: 24,
            sm: 8
        }
    }

    使用es6结构赋值
   

4.上传文件

    
          {this.state.userImg?:}
    
 handleChange = (info) => { // 上传图像
    if (info.file.status === 'uploading') {
        this.setState({ loading: true });
        return;
    }
    if (info.file.status === 'done') {
        // 正常是调用服务器的上传地址
    }
}

5. easy mock,语法参考mock.js

是一款可以适用于前端编写线上接口,以便测试调用,自动创建项目,编写接口,放入数据

' result|10': [ { // 生成十条数据
    "code": 0,
    "message": '失败',
    "result|10": [{
      'id|+1': 0, // 递增+1
      'userName': '@cname', // 随机的名字
      'sex|1-2': 1, // 随机在1-2中选择
      'telephone': '888888',
      'state|1-5': 1,// 随机在1-5中选择
      'interest|1-8': 1,// 随机在1-8中选择
      'birth': '1995-06-30',
      'address': '地球',
 }]

6. axios使用与封装

  • 最简单的引用

      // 动态获取mock数据,根据上步创建的接口获取
    import axios from 'axios
    request = () => {
      let baseUrl = 'https://www.easy-mock.com/mock/5caffee40ee3ff114ba3e62b/yxjapi' 
      axios.get(`${baseUrl}/table/list`).then((res) =>{
          if (res.data.code == '0') {
              this.setState({
                  dataSource2: res.data.result
              })
          }
      })
    }
    
  • 封装axios请求

    static ajax(options){
      const baseURL = 'https://www.easy-mock.com/mock/5caffee40ee3ff114ba3e62b/yxjapi'  // 接口地址
      return new Promise((resolve,reject) => {
          axios({
              url: options.url,
              method: 'get',
              baseURL: baseURL,
              timeout: 7000,
              params: (options.data.params && options.data) || ''
          }).then((response) => {
              if (response.status == '200') {// http请求自带status
                  let res = response.data
                  if (res.code == '0') { // 项目服务器后台接口业务层面的判断
                      resolve(res)
                  }else {
                      Modal.info({
                          title: '提示',
                          content: res.data.messsage
                      })
                  }
              }else {
                  reject(response.data)
              }
          })
      })
    }
    
  • 使用

    axios.ajax({
          url: '/table/list',
          data: {
              params: {
                  page: 1
              }
          }
      }).then((res) => {
          if (res.code == '0') {
              this.setState({
                  dataSource2: res.result
              })
          }
      })
    

7. 表格分页的封装

    // 分页的封装
pagination (data, callback) {
    let page = {
        onChange: (current) => {
            callback(current)
        },
        current: data.result.page,
        pageSize: data.result.page_size,
        total: data.result.total,
        showTotal: () => {
           return `共${data.result.total}条` 
        },
        showQuickJumper: true
    }
    return page
}
  • 使用

    request = () => {
      axios.ajax({
          url: '/table/list',
          data: {
              params: {
                  page: 1
              },
              isShowLoading: true
          }
      }).then((res) => {
          if (res.code == '0') {
              this.setState({
                  dataSource2: res.result.list,
                  selectedRowKeys: [], // 删除后的重置
                  selectedRows: null, // 删除后的重置
                  pagination: util.pagination(res, (current)=>{ // 根据点击的页玛进行数据变化处理
                      // to-do
                      _this.params.page = current
                      _this.request()
                      message.success(`当前页${current}`)
                  })
              }) 
          }
      })
    

    8 . 组件使用外部class的form表单,获取表单对象

    绑定wrappedComponentRef方法输出表达对象给dataform自定义,通过

      let drgInfo = this.dataForm.props.form.getFieldsValue() 获取数据
    
        {this.dataForm = datas}} />
    

    9. 地图功能的实现(基于项目中的骑车路线)

    • 创建ak,加载百度地图sdk
    • 地图初始化,添加地图控件
    • 绘制路线(通过坐标点)
    • 绘制服务区地图

    (1) 创建ak,加载百度地图sdk

    第一步:打开map.baidu.com,找到地图开放平台,点击进入
    第二步:点击开发文档,点击web开发下的JavaScript API
    第三步:在产品简介中,点击申请秘钥ak,创建应用,选择浏览器 端,白名单中设置*号,点击创建即可获取ak值
    第四步:在public文件夹下的index.html的head部分中引用以下代码

        
    

    (2)初始化地图

    第一步:创建一个渲染地图的容器,取一个id值

        

    第二步:为获取地图对象添加方法,并且添加控件,同时在接口数据返回后调用方法

         renderMap = (result)=>{
                this.map = new window.BMap.Map('orderDetailMap');
                // 添加地图控件
                this.map.centerAndZoom('北京',11); // 设置地图的中心点
                this.addMapControl();
          }
          // 添加地图控件
             addMapControl = ()=>{
                 let map = this.map;
                 map.addControl(new window.BMap.ScaleControl({ anchor: window.BMAP_ANCHOR_TOP_RIGHT}));
                 map.addControl(new window.BMap.NavigationControl({ anchor: window.BMAP_ANCHOR_TOP_RIGHT }));
             }
    

    (3)绘制路线

          // 绘制用户的行驶路线
    drawBikeRoute = (positionList)=>{
        let map = this.map;
        let startPoint = '';
        let endPoint = '';
        // lon 经度 lat 纬度
        if (positionList.length>0){ // 判断行驶轨迹是否存在
            let first = positionList[0]; 
            let last = positionList[positionList.length-1];
            startPoint = new window.BMap.Point(first.lon,first.lat);// 获取地图点
            
            // 创建开始坐标点的图标
            let startIcon = new window.BMap.Icon('/assets/start_point.png',
            new window.BMap.Size(36,42),{// 整个图标
                imageSize:new window.BMap.Size(36,42), // 图片的大小
                anchor: new window.BMap.Size(18, 42)
            })
            
            // marker是为了将icon图标嵌入到地图里面,并且要设置坐标点实现点
            let startMarker = new window.BMap.Marker(startPoint, { icon: startIcon});
            this.map.addOverlay(startMarker);
    
            // 创建结束坐标点的图标
            endPoint = new window.BMap.Point(last.lon, last.lat);
            let endIcon = new window.BMap.Icon('/assets/end_point.png', new window.BMap.Size(36, 42), {
                imageSize: new window.BMap.Size(36, 42),
                anchor: new window.BMap.Size(18, 42)
            })
            
            // marker是为了将icon图标嵌入到地图里面,并且要设置坐标点实现点
            let endMarker = new window.BMap.Marker(endPoint, { icon: endIcon });
            this.map.addOverlay(endMarker);
    
            // 连接路线图
            let trackPoint = [];
            for(let i=0;i

    (4) 绘制服务区地图

           // 绘制服务区
    drwaServiceArea = (positionList)=>{
        // 连接路线图
        let trackPoint = [];
        for (let i = 0; i < positionList.length; i++) {
            let point = positionList[i];
            trackPoint.push(new window.BMap.Point(point.lon, point.lat));
        }
        // 绘制服务区
        let polygon = new window.BMap.Polygon(trackPoint, {
            strokeColor: '#CE0000',
            strokeWeight: 4,
            strokeOpacity: 1,
            fillColor: '#ff8605',
            fillOpacity:0.4
        })
        this.map.addOverlay(polygon);
    }
    

    10. echart的使用

    • 安装

      sudo yarn add echarts-for-react --save
      sudo yarn add echarts --save
      
    • 引用

      import ReactEcharts from 'echarts-for-react';
      import echarts from 'echarts/lib/echarts'
      可以按需引用echart中某一个组件
      // 引入饼图和折线图
      import 'echarts/lib/chart/pie'
      
    • 使用

      getOption() {
        let option = {
            title: {
                text: '用户骑行订单',
                x : 'center'
            },
            legend : {
                orient: 'vertical',
                right: 10,
                top: 20,
                bottom: 20,
                data: ['周一','周二','周三','周四','周五','周六','周日']
            },
            tooltip: {
                trigger : 'item',
                formatter : "{a} 
    {b} : {c} ({d}%)" }, series: [ { name : '订单量', type : 'pie', radius : '55%', center : [ '50%', '60%' ], data:[ { value:1000, name:'周一' } ], itemStyle : { emphasis: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] } return option; } // render中渲染

    11. 富文本编辑器的使用 ------ react-draft-wysiwyg

    • 安装富文本组件以及将组件内容装换成html格式的draftjs

         sudo yarn add react-draft-wysiwyg draftjs-to-html --save  
      
    • 使用 参考项目代码把。。。文字过长了,不让发了,我都提交了

    你可能感兴趣的:(react学习笔记(react基础+react全家桶+ant-ui知识)知识点边学边更新)