WEB前端程序开发Web前端之路前端开发

react学习笔记(react基础+react全家桶+ant-u

2018-09-28  本文已影响80人  送你一堆小心心

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

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

环境配置

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

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

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

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中配置

在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'
           })
       ]
   }

使用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
生态介绍

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语法

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

        class Component extends React.Component {
              constructor (props) {
                    super(props);
                    this.state = {
                        age: 18
                    }
              }
              addAge () {
                  this.setState({
                      age : this.state.age + 1
                  })
              }
              render () {
                   return (
                        <div>
                              <h1>I am  {this.state.age} years old </h1>
                              <button onclick={(e) => {this.addAge(e)}}><button />
                        </div>
                  )
              }
        }
        ReactDom.render(
              <Component />,
               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 (
                        <div>
                              <h1>I am  {this.state.age} years old </h1>
                              <input type="text" onChange={(e) => {this.changeValue(e)}} />
                        </div>
                  )
              }
        }
        ReactDom.render(
              <Component />,
               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 (
                        <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.title}</h1>
              }
        }
        class App extends React.Component{
              render () {
                  return (
                      <div>
                          <Title title="app" />
                          <Component />  // 在这里引用小组件component
                      </div>
                  )
              }
        }
        ReactDom.render(
              <App />, // 这里换成App
               docuement.getElementById('app')
        )

(10)组件嵌套组件

        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')
        )

(11)容器性组件嵌套组件,传值可以为任何html形式

        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>
                          </Title> //更改为html形式
                          <Component /> 
                      </div>
                  )
              }
        }
        ReactDom.render(
              <App />, // 这里换成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 (
               <div style={{background: this.state.bgColor}}>
                   <h1>我是爸爸</h1>
                   <Child bgColor={this.state.bgColor} changeColor={(color) => {this.changeMyBgColors(color)}}/>
               </div>
           )
       }
   }
   class Child extends React.Component {
       constructor (props) {
           super(props)
       }
       changeMyBgColor () {
           this.props.changeColor('blue')
       }
       render () {
           return (
               <div>
                   <h2>我是baby</h2>
                   <button onClick={(e) => {this.changeMyBgColor(e)}}>我想改变我爸爸的背景颜色</button>
               </div>
           )
       }
   }
   ReactDOM.render(
       <Father />,
       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 (
                   <div>
                       <h2>我是孩子1</h2>
                       <button onClick={(e) => {this.changeMyBrotherColor(e)}}>我要改变我弟弟的颜色咯</button>
                   </div>
               )
           }
       }
       class Child2 extends React.Component{
           constructor (props) {
               super(props)
           }
           render () {
               return (
                   <div>
                       <h2 style={{color: this.props.color22}}>我是孩子2</h2>
                   </div>
               )
           }
       }
       class Father extends React.Component{
           constructor (props) {
               super(props)
               this.state = {
                   color2: 'yellow'
               }
           }
           changColor (colorsss) {
               this.setState({
                   color2: colorsss
               })
           }
           render () {
               return (
                   <div>
                       <h1>这是我的孩子们</h1>
                       <Child1 change2Color={(color) => {this.changColor(color)}}/>
                       <Child2 color22={this.state.color2}/>
                   </div>
               )
           }
       }
       ReactDOM.render(
           <Father />,
           document.getElementById('app')
       )

react生命周期

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

按顺序输出值:

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

react-router

1.router几种方式
2. react-router几种方式
3.router传参,组件接受不同组件传参
  class A extends React.Component {
      constructor (props) {
          super(props)
      }
      render () {
          return (
              <div>
                  Component   A  
                  <Switch>
                      <Route 
                          exact // 必须完全符合path
                          path={`${this.props.match.path}`}
                          render={(route) => {
                              return <div>当前组件是不带参数的A</div>
                          }}
                      />
                     <Route >
                          path={`${this.props.match.path}/sub`}
                          render={(route) => {
                              return <div>当前组件是sub</div>
                          }}
                      />
                      <Route 
                      path={`${this.props.match.path}/:id`} // 通过路由地址解析
                      render={(route) => {
                          return <div>当前组件是带参数的A,参数是 : {route.match.params.id}</div>
                      }}/>
                  </Switch>
              </div>
          )
      }
  }
  class B extends React.Component {
      constructor (props) {
          super(props)
      }
      render () {
          return (
              <div>Component B</div>
          )
      }
  }
  class Wrapper extends React.Component {
      constructor (props) {
          super(props)
      }
      render () {
          return (
              <div>
                  <Link to="/a" >组件A</Link>
                  <br />
                  <Link to="/a/123" >带参数的组件A</Link> 
                  <br />
                  <Link to="/a/sub" >/a/sub子路径</Link>
                  <br />
                  <Link to="/b" >组件B </Link>
                  {this.props.children}
              </div>
          )
      }
  }
  
  ReactDOM.render(
      <Router>
           <Wrapper>
              <Route path="/a" component={A}/>
              <Route path="/b" component={B}/>
          </Wrapper>
      </Router>
     ,
      document.getElementById('app')
  )

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

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

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

sudo cnpm install -g create-react-app

初始化项目

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

安装react-router

yarn add react-router

启动项目

yarn start

项目所需要的插件

sudo yarn add react-router-dom axios less-loader
sudo yarn add less
sudo yarn antd   (支付宝做的ui组件)

引用antd样式

  import {Button} from 'antd'  // 引用某一个组件
  <Button>使用组件</Button>
  import 'antd/dist/antd.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文件,配置后重启生效

const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.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'
          ),
        },

项目架构

项目中使用的功能方法

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

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

      import {withRouter} from 'react-router-dom'   引入

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

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

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

  1. 根路由的编写

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

   <Switch>
               <Route path="/admin/ui/buttons" component={Buttons}/>
                <Route component={NoMatch}></Route>
   </Switch>

Ant design UI组件的基本使用

1. form组件实现登录

2. datePicker日期控件的引用

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

     sudo yarn add moment --save

        import moment from 'moment
            <FormItem label="生日" >
                        {
                            getFieldDecorator('birth', {
                                initialValue: moment('2018-08-08') , // 获取moment
                                rules: [
                                    {
                                        required: true
                                    }
                                ]
                            })(
                                <DatePicker
                                    showTime
                                    format="YYYY-MM-DD"
                                />
                            )
                        }
                    </FormItem>

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

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

   <FormItem {... formItemLayout}> 使用es6结构赋值
   </FormItem>

4.上传文件

    <Upload
              listType="picture-card"
              howUploadList={false}
              // axtion是服务器的地址
             action="//jsonplaceholder.typicode.com/posts/"
             nChange={this.handleChange}
     >
          {this.state.userImg?<img src={this.state.userImg} />:<Icon type="plus"></Icon>}
    </Upload>
 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使用与封装

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
}

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

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

  let drgInfo = this.dataForm.props.form.getFieldsValue() 获取数据

   <OpenFormDatas wrappedComponentRef={(datas) => {this.dataForm = datas}} />

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

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

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

    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的ak秘钥"></script>

(2)初始化地图

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

    <div id="orderDetailMap" className="order-map"></div>

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

     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<positionList.length;i++){
            let point = positionList[i];
            trackPoint.push(new window.BMap.Point(point.lon, point.lat));
        }

        // 设置线的样式
        let polyline = new window.BMap.Polyline(trackPoint,{
            strokeColor:'#1869AD',
            strokeWeight:3,
            strokeOpacity:1
        })
        this.map.addOverlay(polyline);
        this.map.centerAndZoom(endPoint, 11);
    }
    
}

(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的使用

  getOption() {
    let option = {
        title: {
            text: '用户骑行订单',
            x : 'center'
        },
        legend : {
            orient: 'vertical',
            right: 10,
            top: 20,
            bottom: 20,
            data: ['周一','周二','周三','周四','周五','周六','周日']
        },
        tooltip: {
            trigger : 'item',
            formatter : "{a} <br/>{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中渲染
  <ReactEcharts
           option={this.getOption()} 
           style={{ height: 500 }}/>

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

上一篇下一篇

猜你喜欢

热点阅读