组件创建
第一种方式
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')
);