文章涉及的内容可能不全面,但量不少,须要慢慢看。我花了很长的时间整理,用心分享心得,但愿对你们有所帮助。可是不免会有打字的错误或理解的错误点,但愿发现的能够邮箱告诉我1163675970@qq.com,我会及时的进行修改,只但愿对你有所帮助,谢谢。css
import React from 'react'
import ReactDOM from 'react-dom'
function tick() {
let ele = <h1>{ new Date().toLocaleTimeString() }</h1>
// Objects are not valid as a React child (found: Sun Aug 04 2019 20:34:51 GMT+0800 (中国标准时间)). If you meant to render a collection of children, use an array instead.
// new Date() 是一个对象数据类型的值,React 元素不接收对象做为其子元素
ReactDOM.render(ele, document.querySelector('#root'))
}
tick()
setInterval(tick, 1000) // 若是不包在一个函数中,时钟是不会每秒更新一次
复制代码
可是 React 和 Vue 相同都是数据驱动的,可是这个时候和数据驱动没啥关系,每隔1秒钟从新建立一个 ele,而后再渲染到页面中,视图才发生变化;为了使用数据驱动,咱们须要使用 React 的组件html
在 React 组件中,jsx 元素(也称 react 元素)是组件的基本组成单位 在 react 中定义组件有两种方式:react
react 使用函数定义组件,就是声明一个函数;算法
// 1. 函数定义组件
function Welcome(props) {
// props 是一个对象,是使用组件时,写在组件行内的属性和属性值组成的;
console.log(data)
return (<div>
<p>{props.data.name}; {props.data.age}</p>
<p>{props.x}</p>
</div>)
}
ReactDOM.render(<Welcome data={{name: 'mabin', age: 18}} x='hahah' />, document.querySelector('#root'));
复制代码
经过 class 定义一个组件bootstrap
-看🌰数组
class Header extends Component {
constructor () {
super()
}
render () {
// 在 render 函数中经过 this.props 访问 props
return (<div>
{this.props.content}
</div>)
}
}
class Hello extends Component {
constructor (props) {
super()
// 注意在构造函数中不能访问 this.props ,props 会做为形参传入
}
render () {
return (
<div>
<Header content="如今是北京时间:" />
<p>{this.props.data.toLocaleString()}</p>
</div>
)
}
}
// 使用这个组件
ReactDOM.render(<Hello data={new Date()} />, document.getElementById('root'));
复制代码
React 也是数据驱动的,当数据发生变化时,视图就会自动发生变化(视图是数据的映射)。组件中的数据有两个来源:props 和 state,其中 props 就是组件被使用时接收的行内属性,是从外部传入的数据,而 state 是组件的私有数据,组件定义时就须要建立;bash
属性(prop)也是组件的数据,而视图是数据的映射,当数据发生变化,组件会自动从新渲染dom
-看🌰函数
function Welcome(props) {
return <div>{props.time.toLocaleString()}</div>
}
setInterval(() => {
// 每隔一秒钟 new Date的值会发生变化,即 Welcome 的 time prop 属性发生了变化,而视图自动变化
let now = new Date()
ReactDOM.render(<Welcome time={now} />, document.querySelector('#root'))
}, 1000)
复制代码
-看🌰ui
把数据经过属性传递给组件
function User(props) {
console.log(props)
let { name, age } = props;
return <div>
<p>{name}</p>
<p>{age}</p>
</div>
}
let data = {
name: 'mabin',
age: 18
}
// ReactDOM.render(<User name={data.name} age={data.age} />, document.getElementById('root'))
ReactDOM.render(<User {...data}/>, document.getElementById('root')) // 可使用展开运算符把一个对象传给组件的props,等效于上面的写法
复制代码
react 组件的数据有两个来源:props 和 state 属性(props):是父组件传递过来的 状态(state): 是组件本身管控的状态,状态是组件私有的数据
咱们来写一个计数器感觉一下 React 的数据驱动
class Count extends Component {
constructor () {
super()
// 在 constructor 中初始化一个状态;经过this.state 赋值一个对象的形式初始化;
// 只有用类声明的组件才有 state
this.state = {
num: 1,
x: 2
}
// this.add = this.add.bind(this)
}
add = () => {
// 在 react 中若是要修改 状态只能经过 this.setState() 方法修改
// setState 方法会进行合并 setState 有两种写法 一种是对象一种是函数
// 1. setState 能够接受一个回调,回调须要 return 一个新的 state 对象,新的对象中只需包含要修改的 属性便可,例如这里咱们要修改 num,return 的对象只须要包含num不用包含 x,react 会自动合并
// 若是下一个状态依赖上一个状态,咱们须要使用函数的形式
/*this.setState((prevState) => {
console.log(prevState); // prevState 以前的状态对象
return {
num: prevState.num + 1
}
})*/
// 2. setState 还能够接受一个对象,对象中须要包含要更新的 state 属性;
this.setState({
num: this.state.num + 1
})
// 咱们发现,咱们更新数据后,页面中使用 num 的地方的值也自动跟着改了;
// react 一样是数据驱动的,当咱们调用 setState 修改 state 时,react 会从新调用 render 函数,获得虚拟DOM 而后调用 DOM-diff 算法,把修改的那一部分从新渲染;
}
render () {
// react 绑定事件时,须要使用驼峰命名法的事件名 onClick = { 事件处理函数 }
// 在定义事件函数时,通常把事件函数声明在原型上,而绑定事件时,经过 this.add 访问这个事件函数
return (<div>
<p>NUM: {this.state.num} </p>
<p>X: {this.state.x} </p>
<button onClick={this.add}>给num加1</button>
</div>)
}
}
ReactDOM.render(<Count />, document.getElementById('root'))
复制代码
和 Vue 的 props 同样,React 的 props 一样支持校验;React 的 props 校验须要三方的库 prop-types
yarn add prop-types --save
复制代码
使用 类型校验须要 在 class 建立组件时建立静态属性 propTypes,值是一个对象,对象的属性是须要校验的 属性,值对应的是校验规则;
static propTypes = {
name: PropType.string.isRequired, // 要求 name 是字符串类型 isRequired 表示必传
age: PropType.number.isRequired // 要求 age 是数字类型,isRequired 表示必传
}
复制代码
static defaultProps = {
name: '珠峰',
age: 10
}
复制代码
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import PropType from 'prop-types'
// React 的props 一样能够校验,可是须要一个第三方的库 prop-types
class User extends Component {
constructor (props) {
super()
console.log(props) // 对象,把行内属性封装到一个对象中
// props.name = 123 // 若是想对 props 进行修改,能够在 constructor 中进行修改
}
static propTypes = {
name: PropType.string.isRequired, // 要求 name 是字符串类型 isRequired 表示必传
age: PropType.number.isRequired // 要求 age 是数字类型,isRequired 表示必传
}
// 给props 设置默认值
static defaultProps = {
name: '京东',
age: 19
}
render () {
return (<div>
<p>{ this.props.name }</p>
<p>{ this.props.age }</p>
</div>)
}
}
let obj = {
name: '张三',
age: 18
};
ReactDOM.render(<User {...obj} />, document.querySelector('#root'));
复制代码
在 React 中,父组件把数据传递给子组件,仍然是经过 props 的方式传递;
-看🌰
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class Header extends Component {
render () {
return (<h1>
<p>{this.props.data}</p>
</h1>)
}
}
// 此时的 Panel 是父组件而 Header 是子组件,父子组件通讯时父传子,仍然是经过 props 传递的
class Panel extends Component {
render () {
return (<div className="container">
<p>{this.props.news}</p>
<Header data={this.props.min} />
</div>)
}
}
let data = {
news: '快下课了',
min: '拖几分钟'
}
ReactDOM.render(<Panel {...data} />, document.getElementById('root'))
复制代码
在 React 中子组件修改父组件的方式和 Vue 不一样;子组件若是想修改父组件的数据,父组件在使用子组件的时候,经过 props 传给子组件一个能够修改父组件的方法,当子组件须要修改父组件的数据时,经过 this.props 找到这个方法执行对应的方法
-看🌰
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import 'bootstrap/dist/css/bootstrap.css'
class Panel extends Component {
static defaultProps = {
a: 1
}
constructor () {
super()
this.state = {
color: 'success'
}
}
changeColor = (color) => {
this.setState({
color
})
}
render () {
return (<div className="container">
<div className={`panel panel-${this.state.color}`}>
<div className="panel-heading">
{this.props.head}
</div>
<div className="panel-body">
{this.props.body}
</div>
{/*经过 modifyColor 这个 props 把 Panel 组件的 changeColor 方法传递给 Footer 组件*/}
<Footer type={this.state.color}
modifyColor={this.changeColor} />
</div>
</div>)
}
}
class Footer extends Component {
change = () => {
this.props.modifyColor('danger')
}
render () {
return (<div className="panel-footer">
<button className={`btn btn-${this.props.type}`} onClick={this.change}>变色</button>
</div>)
}
}
ReactDOM.render(<Panel head="头信息" body="信息主体"/>, document.getElementById('root'))
// React 一样是单向数据流,即数据只能经过只能从父组件流向子组件
// 因此子组件若是想修改父组件的数据,父组件在使用子组件的时候,经过props传给子组件一个能够修改父组件的方法,当子组件须要修改父组件的数据时,经过this.props 找到这个方法执行对应的方法就能够了
复制代码