• React


    react历史

    • Vue2014年开源
    • 2013年面向开发者不是开源的
    • angular2009年
    • vue双向数据绑定->双向数据流
    • react单向数据流
      • 内存的改变影响页面的改变不管页面的改变,影响内存的改变,自己处理页面的改变,影响内存,通过事件
    • 没有指令

    import和require

    • import属于加载前置的机制,因此将其全放再代码顶部,代码解析逐个import获取一个引入的列表,先引入依赖,再向下执行代码,加载前置
    • require
      • if(true) { let querystring=require(’ querystring’); }
      • 加载滞后,代码执行到哪一行才进行加载

    脚手架

    • 下载脚手架工具 npm i -g create-react-app
    • 使用
      • create-react-app 项目名options 构建项目解构
      • cd项目目录&& npm i安装依赖包
    • 运行
      • npm run start启动
      • npm run build生成dist

    jsx语法

    js+ xml

    基本操作总结

    • 1:引入React对象
    • 2:引入ReactDOM对象
    • 3:操作jsx
      • jsx不能用+=来运算(不是字符串)
      • jsx可以通过数组来输出数据
        1
        ,
        2
      • const arr = [
        1
        2
        ]
    • 4:渲染到指定的元素上
      • reactDOM. render (,document . getE lementById(‘app’);
    • 5:启动npm run dev

    官方推荐的class方式

    • 儿子class ->子类构造器中必须super(父类构造器

    编写App渲染内容

    • 只能有一个根节点函数

    调用的示例

    • this指向

    react中有变化的属性

    • className
    • htmlFor

    传递参数及DOM

    • react中之 直接给属性就是数据,在子组件中this.props.属性名获取
    • 直接往子组件中扔DOM就是传入的DOM,在自组件中使用this.props.children输出
    • 更加健壮的排除空节点undefined或者单节点Object或多子节点Array
      • React. Children. map(this . props . children, child=>{ })

    获取DOM元素

    生命周期

    constructor( )

    1 constructor (props)

    react的构造器是在装载之前被调用的,当构造器实现了React.Component类,你应该在任意的生命之前调用super(props)

    • Otherwise, this.props will be undefined in the constructor, which can lead to bugs.

    常见的构造函数内目的:

    • Initializing local state by assigning an object to this .state .
    • Binding event handler methods to an instance.
    constructor (props) {
    super(props);
    // Don't ca11 this .setState() here!
    this.state = { counter: 0 };
    this.handTeClick = this.hand1eClick.bind(this);//改变handleClick的this的上下文
    

    componentWillMount

    官方不推荐在此处发请求,原因可能会造成渲染的阻塞,而将请求放在componentDidMount(数据已经装载,据网上流传会引起二次render)

    render ()

    在一个class或者function组件中必须需要的

    Note

    render() will not be invoked if shoul dComponentUpdate( returns false.

    componentDidMount( )

    1 componentDidMount ()

    实际应用发网络请求

    组件安装后立即调用componentDidMount () (插入到树中) 。需要DOM节点的初始化应该到这里。如果您需要从远程端点加载数据,那么这是实例化网络请求的好地方

    这个方法是建立任何订阅的好地方。如果您这样做,请不要忘记在componentWillUnmount ()中取消订阅。

    componentDidupdate()

    1 componentDidUpdate (prevProps, prevstate, snapshot)

    componentDi dupdate() is invoked immediately after updating occurs. This method is not called for theinitial render.

    当组件被更新时,将此作为在DOM.上操作的机会。这也是一一个进行网络请求的好地方,只要您将当前的props与以前的props进行比较(例如,如果props没有改变, 网络请求可能就不需要了)。

    componentDidUpdate (prevProps) {
    // Typical usage (don't forget to compare props):
      if (this.props.userID !== prevProps.userID) {
    		this.fetchData(this.props.userID) ;
    	}
    }
    

    注意:

    componentDidupdate() will not be invoked if shouldComponentupdate() returns false.

    shouldComponentUpdate()

    componentWillUpdate()

    componentWillUnmount()

    传值及slot

    • 属性约束及默认值
    import PropTypes from 'prop-types' ;
    static propTypes = {
    	name :PropTypes.number //string.isRequired
    }
    static defaultProps = {
    	name: 'abc'
    }
    
    • 传值
    import React, {Component} from 'react';
    import Son from "./son.js";
    
    class App extends Component{
        constructor(){
            super();
            this.state = {
                age:12,
            }
        }
    
      render() {
        let {age} = this.state;
        let header = (<div>header</div>);
        let footer = (<div>footer</div>)
        return (
            <div>
              我是app组件,一下使用son组件
              <hr/>
                {/*组件的使用必须首字母大写*/}
              {/*<Son age={this.state.age} name="jack"/>*/}
                <Son age={age} name="jack" head={header} foot={footer}>
                    <ul>
                        <li>1</li>
                        <li>2</li>
                        <li>3</li>
                    </ul>
                </Son>
            </div>
        )
      }
    }
    export default App;
    
    import React, {Component} from 'react';
    import PropTypes from 'prop-types';
    
    class Son extends Component{
        //属性的约定和默认值
        static propType = {
            text: PropTypes.number // string.isRequired
        }
        static defaultProps = {
            text :'abc',
        }
    
        constructor(props){
            super(props);
        }
        render() {
            console.log(this.props)
            //声明一rage, name属性,this. props中的同名属性进行赋值
            let {age, name, head, text} = this.props;
            //改变age与this. props. age无关
            // 声明一 个引用类型属性,this. props中同名属性的地址进行赋值
            //Let{obj}= this. props;
            //改变obj.xxx 与this. props.obj.xxx有关
            return (
                <div>
                    我是子组件,数据如下:
                    <hr/>
                    {/*{this.props}*/}
                    {name}, {age}
                    <div style={{backgroundColor:'red'}}>
                        {head}
                    </div>
                    {this.props.children}
                    <div style={{backgroundColor:'blue'}}>
                        {this.props.foot}
                    </div>
                    {text}
                </div>
            )
        }
    }
    
    export default Son;
    

    内置便捷函数

    • this.props.children有可能有三种数据结构: 对象/数组/undefined
      • React.Children.map (children, function[(thisArg)]) // 返回数组
    • 更加健壮的排除空节点undlefined或者null的情况
      • React.Children.forEach (children, function [(thisArg)]) //遍历

    template补充

    • 保证一个跟节点
      在这里插入图片描述

    • 解决方案

      • 在react16以后, 可以支持编写[]

      • render(){ return [

        1

        ,

        2

        ] }

      • render(){ 
          return <React.Fragment>
            <h1>1</h1>
            <h1>2</h1>
          </React.Fragment>
        }
        
      • 该方式不会创建对于的元素

    react15和16的区别

    React.createClass和 extends Component的区别主要在于:

    1. 语法区别
    2. propType 和 getDefaultProps
    3. 状态的区别
    4. this区别
    5. Mixins 混合的区别

    语法区别

    React.createClass

    import React from ' react ' ;
    const Contacts = React.createClass({
        render() {
            return (
               <div></div>
            );
        } 
    });
    export default Contacts ;
    

    React.Component

    import React from react' ;
    class Contacts extends React.Component {
        constructor (props) {
            super (props);
        }
        render() {
          return (
            <div></div>
           );
        }
    }
    

    后一种方法使用ES6的语法,用constructor构造器来构造默认的属性和状态。

    propType和getDefaultProps

    React.createClass:通过proTypes对象和getDefaultprops ()方法来设置和获取props.

    import React from ' react ' ;
    const Contacts = React.createClass ({
      propTypes: {
        name: React.PropTypes.string},
        getDefaultProps() {
      		return {
            name:'abc'
          };
        },
      render() {
        return (
       		 <div></div>
        );
      }
    });
    export default Contacts ;
    
    

    React.Component:通过设置两个属性propTypes和defaultProps

    import React form 'react' ;
    class TodoItem extends React.Component{
        static propTypes = { // as static property
          name: React.PropTypes.string
        };
        static defaultProps = { // as static property
          name : 1!
        };
        constructor (props){
        	super (props)
        }
        render(){
        	return <div></div>
        }
    }
    
    

    状态的区别

    React.createClass:通过getInitialstate()方法返回一个包含初始值的对象

    import React from 'react ' ;
    let TodoItem = React. createClass({// return an object
        getInitialState(){
          return {
          	isEditing: false I
          }
        },
        render(){
        	return <div></div>
    		}
    })
    
    

    React.Component:通过constructor设置初始状态

    import React from 'react' ;
    class TodoItem extends React . Component{
        constructor (props){
            super(props) ;
            this.state = { // define this.state in constructor
              isEditing: false
            }
        }
        render(){ 
      		  return <div></div>
        }
    }
    
    

    this区别

    React.createClass:会正确绑定this

    import React from' react' ;
    const Contacts = React.createClass({
      handleClick() {
        console.1og(this); // React Component instance
      },
      render() {
        return (
          <div onClick={this . hand1eclick}></div>//会切换到正确的this上下文
        );
      }
    });
    export default Contacts ;
    

    React.Component:由于使用了ES6,这里会有些微不同,属性并不会自动绑定到React类的实例上。

    import React from 'react ' ;
    class TodoItem extends React.Component{
      constructor(props){
      	super(props);
      }
      handleClick(){
      	console.1og(this); // null
      }
      hand1eFocus(){ // manually bind this 
      	console.1og(this); // React Component Instance
      }
      hand7eBlur: ()=>{ // use arrow function
      	console.1og(this); // React Component Ins tance
      }
      render(){
        return <input onClick={this.handleclick}
                      onFocus={this.handleFocus.bind(this)}
                      onB7ur={this.hamp1eB1ur}/>
      }
    }
    

    我们还可以在constructor中来改变this.handleClick执行的上下文,这应该是相对上面一种来说更好的办法,万一我们需要改变语法结构,这种方式完全不需要去改动JSX的部分:

    import React from 'react' ;
    c1ass Contacts extends React.Component {
      constructor(props) {
        super (props);
        this .hand1eClick = this.handleClick.bind(this);
      }
      handleClick() {
      	console.1og(this); // React Component instance
      }
      render() {
        return (
        	<div onClick={this . handleClick}></div>
        );
      }
    }
    export default Contacts;
    

    Mixins

    如果我们使用ES6的方式来创建组件,那么React mixins的特性将不能被使用了。

    React.createClass:

    import React from 'react';
    1et MyMixin = {
      doSomething(){}
    }
    1et TodoItem = React.createClass({
      mixins: [MyMixin], // add mixin
      render(){
      	return <div></div>
      }
    })
    

    使用React.createClass的话,我们可以在创建组件时添加一个叫做mixins 的属性,并将可供混合的类的集合以数组的形式赋给mixins。

    React.Compoent

    export default function (Son) {
      return class wrap extends Component {
        compomentDidMount () {
          conso1e.1og('aaaaa') ;
          console.1og()
        }
        render() {
        <Son/>
        }
      }
    }
    

    插件相关

    基本使用

    • react-router-dom(在浏览器使用)
    • react-router-native(开发手机原生应用使用的)。推荐使用react-navigation

    使用流程

    • 下载npm i react-router-dom ;
    • 引入对象,按需引|入,HashRouter, BrowserRouter ,Route
    • HashRouter代表路由框架的坑
    • BrowserRouter代表路由的坑,最终 是没有#的方式,原理基于click + history.pushState
    • Route 代表锚点及组件和填入的位置

    Switch选择-个

    • 横线匹配一个
    • 被其包裹的Route从上到下,只会匹配一个(选其一 )

    exact精确匹配

    React-router 默认是模糊匹配,所以需要添加exact来适配精确匹配

    • 纵向(深入匹配)一个
    • 精确匹配锚点(只会匹配一个)
    • 应用场景:首页’/’ 需要使用,因为/范围太大,会匹配很多东西
      • 其他路由不适用,为了能使用嵌套路由(不要控制纵向(深入)只匹配一个)

    默认重定向(相当于404)

    • 放在路由最后一位,用来处理页面找不到,配合Switch
    • Redirect,常用to属性

    NavLink类似router-link

    • NavLink 按需引入import {NavLink} from ‘react-router-dom’ ;
    • 当做组件来使用,其中属性to(路径与Route中的path匹配
    <NavLink to="/index/course" activeSty1e={{ co1or: '#4dc060' }}>样式</NavLink>
    <NavLink to=" /index/mine" activeClassName="selected">类名</NavLink>
    

    代码注意

    • 主体组件App只能有一个根节点
    • 主体坑(HashRouter)也只能有一 个根节点
      • NavLink 只能在主体坑中
      • Switch中不能有Navllink

    路由参数

    <Route path= '/user/:data' component= {UserPage}></Route>1
    

    使用

    var data = {id:3,name:sam,age:36};
    data = JSON.stringify(data);
    var path = '/user/${data}';
    1.<Link to={path}>用户</Link>
    2. hashHistory.push(path);
    

    获取数据:

    var data = JSON.parse(this.props.params.data) ;
    var {id,name,age} = data;12
    

    通过这种方式跳转到UserPage页面时只能通过传递字符串来传递参数,那么是否有其他方法来优雅地直接传递对象而不仅仅是字符串呢?

    二.query

    query方式使用很简单,类似于表单中的get方法,传递参数为明文:首先定义路由:

    <Route path='/user' component={UserPage}></Route>1
    

    使用

    var data = {id:3,name:sam,age:36};
    var path = {
      pathname:'/user',
      search:'?id=4',		#url拼接
      query:data,				# 跳转后附带是参数
    }
    <Link to={path}>用户</L ink>xxxHistory.push(path);
    

    获取数据:

    var data = this.props.location.query;
    var {id ,name ,age} = data;
    

    query方式可以传递任意类型的值,但是页面的URL也是由query的值拼接的,URL很长,那么有没有办法类似于表单post方式传递数据使得传递的数据不以明文传输呢?

    三. state

    state方式类似于post方式,使用方式和query类似,首先定义路由:

    <Route path= ' /user' component={Us erPage}></Route>1
    

    使用:

    var data = {id:3,name: 'sam' ,age:36} ;
    var path = {
        pathname:'/user' ,
        state :data,
    }
    <Link to={path}>用户</Link>
    hashHistory.push(path) ;
    

    获取数据:

    var data = this.props.1ocation.state ;
    var {id,name,age} = data;
    

    编程导航

    • this.props.history.push
      • 改变锚点值,引发页面变更
      • 前进或后退this. props . history . goBack() IIgoForward();
      • 前进或后退,根据参数
    • 通过历史记录来操作导航

    嵌套路由

    • 在部分相同布局的情况下,局部发生变化
    • 避免相同布局的重复渲染
    • 在需要出现嵌套路由的组件位置中,直接写上坑、path、 组件
    • 嵌套的子路由的path必须写成完成的路径
  • 相关阅读:
    iscsi一致性的测试验证方法
    ceph各个版本之间参数变化分析
    rgw的rgw_thread_pool_size配置调整
    rgw前端替换civetweb为beast
    配置内网访问的TV
    关于vm.min_free_kbytes的合理设置推测
    rbd的删除回收站功能
    python爬取微博热门话题榜
    Selenium+Pytest自动化测试框架—禅道实战
    python带参数装饰器的两种写法
  • 原文地址:https://www.cnblogs.com/daozhangblog/p/12446330.html
Copyright © 2020-2023  润新知