您的位置:首页 > Web前端 > React

React 组件创建 生命周期 PropTypes

2019-01-07 12:49 465 查看

组件创建

第一种方式

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

// 第一种创建组件,props可以是其他,形参,但这样语义化
// 首字母大写
function HelloWorld(props){
console.log(props)
// props.name="Li Mei"  props只读,会报错

// return null
return <div>这是一个HelloWorld组件---大家好,我叫{props.name},今年我{props.age}</div>
}

const man = {
name:"David",
age:"19",
gender:"man"
}
// {...man} 展开运算符
ReactDOM.render(<HelloWorld name = {man.name} age = {man.age} gender = {man.gender}></HelloWorld>,document.getElementById('root'))

// 展开运算符
var object1 = {
data:"1",
name:"Li Mei",
age:"18"
}

var object2 = {
gender:"男",
...object1
}

console.log(object2,"object3")



单独把组件拎出来

import React from 'react';

// 第一种创建组件,props可以是其他,形参,但这样语义化   只读
export default function HelloWorld(props){
console.log(props,"props")
// props.name="Li Mei"

// return null
return <div>这是一个HelloWorld组件---大家好,我叫{props.name},今年我{props.age}</div>
}

引用组件时,记得import,后缀名要一致,可以jsx,或者js。有坑
import 文件时,若创建文件以.jsx结尾时,能省去。若创建文件以.js结尾时,就不能省去。(可能是react-app中webpack的规则问题,没找到位置,有知道的望告之)

第二种方式

  • 使用class关键字创建组件 实例属性
  • 静态属性
// 以前新建某某实例,以构造函数形式,
function Person(name,age){
this.name = name
this.age = age
}
Person.info = "我是一条信息"
var P1 = new Person("David",18)
console.log(P1)

// 通过new实例创建的构造函数或者类,叫做 实例属性
// P1.name  P1.age 即是实例属性
// 通过 构造函数直接访问的属性,叫做静态属性
// info 即是静态属性,不需要new

// 新建数组是不是也是 new 一下

// 创建一个类
class Person {
// 每个类都有一个构造器,哪怕没写,默认内部有个隐形空构造器
//构造器的作用:new 实例的时候,先执行构造器中的代码
constructor(name,age){
this.name = name
this.age = age
}
// 静态属性 访问 Person.info
static info = "我是一条static信息"
}

const p2 = new Person("David",18)

// 通过new实例创建的构造函数或者类,叫做 实例属性
// 通过 构造函数,直接访问的属性,叫做静态属性
// 这里name age 也是实例属性
  • 实例方法
  • 静态方法
// 原型,节约内存
Person.prototype.say = function(){
console.log("实例方法")
}

P1.say()  // 实例方法

Person.key = function(){
console.log("静态方法")
}
Person.key()

// 实例方法和静态方法
say(){

}
static say(){

}
// 静态属性和方法都会挂载到constructor,不在原型对象上面 ,有截图


注意:

  • class { } 只能写构造器,静态方法与属性,实例方法
  • class 语法糖

class继承

class Person {
constructor(name,age){
this.name = name
this.age = age
}
say(){
console.log("我是一个实例方法,原型,公共")
}
}
// 在class中,可以用extends实现继承
class Chinese extends Person{
// 在构造器中加 super() name  age 为undefined
// 下面是正确写法
constructor(name ,age){
super(name,age)
//  this....
}
}
var a = new Chinese("jack" ,18)
console.log(a)

super

  • 为什么要调用super() 子类通过extends关键字继承父类,那么,在子类的constructor 构造函数中,必须优先调用 super()
  • super
      super是一个函数,而且是父类的构造器,子类中的 super,其实是父元素constructor构造器的引用

    基本构建

    import React, { Component } from 'react';
    // React.Component
    class App extends Component {
    constructor(){
    super()
    this.state = { }
    }
    render() {
    return (
    <div >
    。。。。
    </div>
    );
    }
    }

    两种创建组件方式

    • 没多少区别,关键在于class创建的组件有私有数据(state)和生命周期,function创建的则没有,只有props
    • 构造函数 为 无状态组件 class 为 有状态组件(如果组件里只有render,也是无状态组件)
      没有特殊要求,无状态组件性能比较好

    state

    • this.state={} 类似于Vue中 data
    • 读取 this.state.msg
    • 修改 this.setState.msg

    props和state

    • props中的数据是外界传递过来的,只读
    • state/data中的数据是组件私有,可读可写
    • 读写 其实是set 和 get 属性控制

    React 生命周期

    生命周期函数

    组件加载之前,组件加载完成,以及组件更新数据,数据销毁

    组件加载的时候触发的函数

    • constructor
    • componentWillMount
    • render
    • componentDidMount(通常页面初次渲染,方法在此调用,dom操作)

    组件更新的时候触发的函数

    • shouldComponentUpdata( nextProps,nextState ){ return true} 判断是否更新数据
  • componentWillUpdata
  • render
  • componentDidMount
  • 组件将要卸载的函数

    • componentWillUnmount

    父组件改变props值

    • componentWillReceiveProps

    先componentWillReceiveProps,后shouldComponentUpdata

    PropTypes

    详情看官网
    import PropTypes from 'prop-types';  // 限制组件/容器中属性
    MyComponent.propTypes = {
    // 你可以将属性声明为以下 JS 原生类型
    optionalArray: PropTypes.array,
    optionalBool: PropTypes.bool,
    optionalFunc: PropTypes.func,
    optionalNumber: PropTypes.number,
    optionalObject: PropTypes.object,
    optionalString: PropTypes.string,
    optionalSymbol: PropTypes.symbol,
    
    // 任何可被渲染的元素(包括数字、字符串、子元素或数组)。
    optionalNode: PropTypes.node,
    
    // 一个 React 元素
    optionalElement: PropTypes.element,
    
    // 你也可以声明属性为某个类的实例,这里使用 JS 的
    // instanceof 操作符实现。
    optionalMessage: PropTypes.instanceOf(Message),
    
    // 你也可以限制你的属性值是某个特定值之一
    optionalEnum: PropTypes.oneOf(['News', 'Photos']),
    
    // 限制它为列举类型之一的对象
    optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
    ]),
    
    // 一个指定元素类型的数组
    optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
    
    // 一个指定类型的对象
    optionalObjectOf: PropTypes.objectOf(PropTypes.number),
    
    // 一个指定属性及其类型的对象
    optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
    }),
    
    // 你也可以在任何 PropTypes 属性后面加上 `isRequired`
    // 后缀,这样如果这个属性父组件没有提供时,会打印警告信息
    requiredFunc: PropTypes.func.isRequired,
    
    // 任意类型的数据
    requiredAny: PropTypes.any.isRequired,
    
    // 你也可以指定一个自定义验证器。它应该在验证失败时返回
    // 一个 Error 对象而不是 `console.warn` 或抛出异常。
    // 不过在 `oneOfType` 中它不起作用。
    customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
    return new Error(
    'Invalid prop `' + propName + '` supplied to' +
    ' `' + componentName + '`. Validation failed.'
    );
    }
    },
    
    // 不过你可以提供一个自定义的 `arrayOf` 或 `objectOf`
    // 验证器,它应该在验证失败时返回一个 Error 对象。 它被用
    // 于验证数组或对象的每个值。验证器前两个参数的第一个是数组
    // 或对象本身,第二个是它们对应的键。
    customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
    return new Error(
    'Invalid prop `' + propFullName + '` supplied to' +
    ' `' + componentName + '`. Validation failed.'
    );
    }
    })
    };

    defaultProps

    class Greeting extends React.Component {
    render() {
    return (
    <h1>Hello, {this.props.name}</h1>
    );
    }
    }
    
    // 为属性指定默认值:
    Greeting.defaultProps = {
    name: 'Stranger'
    };
    
    // 渲染 "Hello, Stranger":
    ReactDOM.render(
    <Greeting />,
    document.getElementById('example')
    );

    如果有问题,望斧正,也欢迎交流,共同脱坑

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: