React教程

React教程,第1张

React教程

教程


一、demo

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Hello React!</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body> <div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script> </body>
</html>

二、安装

官方CDN,生成环境不要用

<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>

需要3个库:

  • react.min.js React的核心库
  • react-dom.min.js react的dom相关库
  • babel.min.js 对不支持es6的浏览器的兼容
使用npm构建环境

教程


三、元素渲染

<div id="example"></div>
<script type="text/babel">
function tick() {
const element = (
<div>
<h2>now is {new Date().toLocaleTimeString()}</h2>
</div>
)
ReactDOM.render(element, document.getElementById('example'))
} setInterval(tick, 1000) </script>
  • 定义一个element,它是React的元素对象
  • 通过 ReactDOM.render,把元素渲染到dom里面
  • 渲染后,修改元素不会同步到dom,如果要修改dom,需要重新渲染,也就是调用render函数
  • element只能是const,也就是只读类型

每次修改dom,就要重新获取元素,所以把元素的获取封装起来,就比较方便了。


可以通过元素函数,或者元素类来封装。


名字必须大写开头。


元素函数
function Clock(props) {
return (
<div>
<h2>now is {props.date.toLocaleTimeString()}</h2>
</div>
);
} function tick() { ReactDOM.render(<Clock date={new Date()}/>, document.getElementById('example')); } setInterval(tick, 1000);
  • 定义了获取元素的函数Clock
  • 通过<Clock date={new Date()}/>,这个代码会执行Clock函数,然后把入参存在函数的props属性
元素类

除了可以封装为函数外,也可以封装为类。


class Clock extends React.Component {
render() {
return (
<div>
<h2>now is {this.props.date.toLocaleTimeString()}</h2>
</div>
);
}
} function tick() { ReactDOM.render(<Clock date={new Date()}/>, document.getElementById('example')); }
  • 定义Clock类,继承React.Component
  • 定义render返回元素对象
  • 通过this.props访问props属性
  • 调用方法和函数一样,都是<Clock date={new Date()}/>

四、JSX

React使用JSX来代替js

JSX是很像XML的js语法拓展

JSX优点:

  1. 执行更快
  2. 类型安全,会检查编译错误
  3. 使用模板更加快捷简单

JSX是用来在js语法中,声明React的元素的(也就是html代码),但是又不像字符串。



var arr = [
<h1>h111</h1>,
<h2>h222</h2>,
3
]
var style = {
fontSize: 100,
color : 'blue'
}
const element1 = <h1>
<p style={style} font='1px' data-myattribute="kevinlu">{1 + 1},{1 == 1 ? 2 : 3}</p>
element1
{/*注释...*/}
<div>{arr}</div>
</h1> function tick() {
ReactDOM.render(element1, document.getElementById('example')); }
  • 这样就声明了一个元素element1 ,但是又不需要用引号包裹。


    声明时可以换行。


    最外层只能是一个标签


    • 例如这样是不行的:const ele = <p>1</p><p>2</p>因为最外层有2个标签
    • 这样可以:const ele = <div><p>1</p><p>2</p></div>,通过外层加一个div标签。


  • 如果要定义自定义属性,可以:<p font='15pt' data-myattribute = "kevinlu"></p>data-前缀
  • 可以在元素中使用js表达式,用{}包裹
  • 不支持if else,但可以用三元运算符{i == 1 ? 'True!' : 'False'}
  • 支持内联样式,把样式定义在一个字典里面,然后再元素里引用字典
  • 支持数组,数据里面的元素可以是元素,元素会被逐一展示

五、组件

一个元素可以以组件形式被另一个元素引用,而且可以传参数。


function Con(props) {
return (
<div>
<h2>I am Con name={props.name}</h2>
</div>
);
} const ele = <div><Con name="kevinlu"></Con><h3>content</h3></div> ReactDOM.render(ele, document.getElementById('example'));
  • Con是一个组件,通过props.name获取入参。


    组件也可以用类的形式来定义

  • ele 是一个元素,引用了Con组件,然后传输了入参name="kevinlu"
  • 也可以创建复合组件,就是多个组件组合为一个新组件
  • 组件必须大写开头,区别于html默认标签都是小写开头

六、组件状态

为组件赋予状态属性,通过修改状态来动态更新DOM

class Clock extends React.Component {
constructor(props) { //构建函数
super(props);
this.state = {date: new Date()}
} componentDidMount() {//当DOM被创建(挂载),执行该函数
this.timerId = setInterval(() => this.tick(), 1000) //() => this.tick()相当于定义了一个箭头函数,()表示无入参
} componentWillUnmount() { // 当DOM被删除(卸载),执行改函数
clearInterval(this.timerId)
} tick() {//通过setState来更新state,如果直接更新,例如this.state.date=new Date(),不会同步到DOM
this.setState({date: new Date()})
} render() {
return <div>
<h1>Time</h1>
<h2>Now is {this.state.date.toLocaleTimeString()}</h2>
</div>
}
} ReactDOM.render(
<Clock></Clock>,
document.getElementById('example')
)
  • 执行ReactDOM.render 渲染Clock元素到

    • 生成一个Clock实例
    • 执行构建函数constructor
    • 执行render生成元素的html代码
    • 渲染元素的html到DOM
    • 执行componentDidMount钩子,里面设置了一个定时器,定时器ID存储在实例的变量this.timerId中
  • 定时器定时执行() => this.tick()
    • 这是一个箭头函数,直接传this.tick是不行的,因为会丢失this参数。


    • 箭头函数执行this.tick也就是Clock实例的tick函数,
    • tock函数通过setState更新Clock实例的state里面的date属性,更新为当前时间
    • setState函数会做:
      • 更新变量
      • 重新这些render生成html
      • 把html更新到DOM
      • 所以如果直接更新变量,例如this.state.date=new Date(),是不会同步到DOM的
  • 当DOM被删除componentWillUnmount函数会被执行,然后删除定时器

七、props

类型检查,元素组件支持入参,props支持类型检查,检查入参是否符合要求,如果不符合,或早console显示warning信息。


<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
function Clock(props) {
return <div>{props.name}</div>
} Clock.propTypes = {
name: PropTypes.string
}
ReactDOM.render(
<Clock name={123}></Clock>,
document.getElementById('example')
)
  • Clock要求的name入参类型是string
  • 要加入babel文件的引入
  • 传入了number,所以警告:
react.development.js:372 Warning: Failed prop type: Invalid prop `name` of type `number` supplied to `Clock`, expected `string`.
in Clock

支持的类型:

	// 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string, // 可以被渲染的对象 numbers, strings, elements 或 array
optionalNode: React.PropTypes.node, // React 元素
optionalElement: React.PropTypes.element,

八、事件

元素里面的事件,需要调用函数来触发。


class Toggle extends React.Component{
constructor(props){
super(props);
this.state={isToggleOn:true}
this.handleClick=this.handleClick.bind(this) //需要绑定this
}
handleClick(){
this.setState({isToggleOn:!this.state.isToggleOn})
}
render(){
return <button onClick={this.handleClick}>
{this.state.isToggleOn?'ON':'OFF'}
</button>
} }
ReactDOM.render(
<Toggle></Toggle>,
document.getElementById('example')
)
  • 这里写了一个开关功能,点击变ON,再次点击变OFF,以此循环。


  • 设置buttom的 onClick={this.handleClick},表示当buttom被点击,会调用handleClick函数
  • 这里需要事先为handleClick函数绑定this,否则在handleClick函数里面访问this会返回undefined,而不是Toggle的实例
不需要绑定this的方法

方法1:

class ToggleTest extends React.Component {
handleClick = () => {
console.log('this is ', this)
} render() {
return <button onClick={this.handleClick}>xxx</button>
}
}
ReactDOM.render(<ToggleTest ></ToggleTest >,document.getElementById('example'))
  • 修改定义handleClick 的方法,加上() =>,这个叫:属性初始化器语法

方法2:

class ToggleTest extends React.Component {
handleClick () {
console.log('this is ', this)
} render() {
return <button onClick={(e)=>this.handleClick(e)}>xxx</button>
}
}
ReactDOM.render(<ToggleTest ></ToggleTest >,document.getElementById('example'))
  • onclick的时候,填入箭头函数。


    这里相当于重新定义了一个函数。


    如果向更低阶的元素组件传递函数,会重复构建函数,导致性能问题。


传递参数
class ToggleParam extends React.Component {
handleClick(name, e) { // e是React的事件实例,需要放在最后面
alert(name)
}
handleClick1(name) { // 也可以不要e参数
} render() {
return <button onClick={this.handleClick.bind(this, 'kevinlu')}>xxx</button>
}
}
ReactDOM.render(<ToggleParam></ToggleParam>,document.getElementById('example'))
  • e是React的事件实例,需要放在所有参数最后面,也可以不设置e参数。


  • 这里通过bind的方法,绑定this和name参数,bind会返回一个新函数,当按钮被点击,React会调用该函数
  • 可以通过e.preventDefault();来阻止默认的 *** 作。


    例如点击链接会跳转到新页面,这个命令可以阻止跳转 *** 作。


九、条件渲染 1. if条件判断
function If(props) {
if (props.isLogin) {
return <h1>is Login</h1>
} else {
return <h1>is not Login</h1>
}
} class Login extends React.Component {
constructor(props) {
super(props);
this.state = {isLogin: false}
} login() {
this.setState({isLogin: true})
} logout() {
this.setState({isLogin: false})
} render() {
if (this.state.isLogin)
return <div>now is login <button onClick={this.logout.bind(this)}>logout</button></div>
else
return <div>now is logout <button onClick={this.login.bind(this)}>login</button></div>
} }
ReactDOM.render(<If isLogin={false}></If>, document.getElementById('example'))
  • If和Login两个元素组件,都是根据属性,来判断render的返回html
2.&&运算符
function At(props) {
return <div>kkkkk {props.number > 0 && <h2>number is {props.number} </h2>}</div>
}
  • 如果props.number,显示元素<h2>number is {props.number} </h2>
3. 三目运算符

和IF类似,不过它可以在元素里面通过{}的方式定义:{props.number ?"large 0":'least 0'}

4. 阻止渲染

直接让元素组件返回null,就不会渲染这个元素。


function NoneTest(props) {
if (props.number > 0)
return <div>number is {props.number}</div>
else
return null
}
十、数组
var l = [1, 2, 3, 4, 5]
const ele = <ul>
{l.map(
(number) => <li key={number}>{number}</li>
)}
</ul>
ReactDOM.render(ele, document.getElementById('example'))
  • 通过JS的map方法,遍历l数组,对每个元素执行(number) => <li>{number}</li>函数,返回的是元素数组
  • 对于元素列表,React会遍历数组,逐个显示,所以url标签里面会有5个li标签
  • 数组构建的元素,需要包含一个唯一的key,不然会报错。


    key一般是数组元素的id,如果没有id可以用下标,即(number,index) => <li key={index}>{number}</li>


一、组件API

  • setState(object nextState[, function callback]) 设置状态

    *callback可选,会在修改状态后,渲染DOM后被调用

    • 没有设置的key,不会被替换
  • replaceState(object nextState[, function callback]) 替换状态
    • 和setState类似,区别是没有设置的key,会被设置为undefined
  • setProps(object nextProps[, function callback]) 设置props
  • replaceProps(object nextProps[, function callback])
  • forceUpdate([function callback]) 通知组件重绘DOM
  • DOMElement findDOMNode() 获取组件对应的DOM元素,如果没有,返回null
  • bool isMounted() 判断组件挂载状态

二、组件生命周期

生命周期有:

  • Mounting 已挂载,也就是已插入到真实的DOM
  • Updating 更新中,重新渲染
  • Unmounting 已移出真实的DOM

方法:

  • componentWillMount 组件将要挂载前调用
  • componentDidMount 组件挂载完成调用
  • componentWillReceiveProps 组件接收一个新的prop时被调用,第一次渲染不会调用。


    主要用户组件的更新

  • shouldComponentUpdate 返回bool值,在组件接收到新的props或者state时被调用,第一次渲染不调用
  • componentWillUpdate 在组件接收到新的props或者state但还没有render时被调用
  • componentDidUpdate 更新完成后调用,第一次渲染不调用
  • componentWillUnmount 组件被移除前调用

三、AJAX

一般在componentDidMount 中通过AJAX获取数据,然后通过setState更新组件。


class AjaxTest extends React.Component{
constructor(props) {
super(props);
this.state={content:"test"}
} componentDidMount() {
this.req = $.get('/demo/react_demo/data', function (res) {
this.setState({content: res})
}.bind(this))
}
componentWillUnmount(){
this.req.abort()
}
render(){
return <div>{this.state.content}</div>
}
}
  • 这里用了jq的ajax方法,导入:`
  • get的回调函数需要bind this 不然回调函数里面访问this,不会执行组件实例
  • componentWillUnmount当组件被卸载,关闭http请求

    `

四、表单

class Form extends React.Component {
constructor(props) {
super(props);
this.state = {name: "unknow"}
} onAttrChange(key, e) {
var state = {}
state[key] = e.target.value
this.setState(state, () => console.info('new name', this.state.name))
} render() {
return <div>名字:<input value={this.state.name} onChange={this.onAttrChange.bind(this, 'name')}></input></div>
}
}
  • 表单的值修改后,需要通过onChange事件,更新新的值到组件的变量

如果是嵌套组件,需要把父组件的this传给子组件

function Input(props) {
return <input value={props.this.state.name} onChange={props.this.onAttrChange.bind(props.this, 'name')}></input>
} class Form extends React.Component {
constructor(props) {
super(props);
this.state = {name: "unknow"}
} onAttrChange(key, e) {
var state = {}
state[key] = e.target.value
this.setState(state, () => console.info('new name', this.state.name))
} render() {
return <div>名字:<Input this={this}></Input></div>
}
}

Select

class Select extends React.Component {
constructor(props) {
super(props);
this.state = {value: "unknow"}
} onAttrChange(key, e) {
var state = {}
state[key] = e.target.value
this.setState(state, () => console.info('new value', this.state.value))
} render() {
return <div><select value={this.state.value} onChange={this.onAttrChange.bind(this, 'value')}>
<option value="gg">Google</option>
<option value="fb">Facebook</option>
</select></div>
}
}

五、Ref

我们可以在元素里面的某个标签,设置一个id,然后通过ref,获取到这个标签。


class RefTest extends React.Component {
constructor(props) {
super(props);
} onClick() {
var name = this.refs.myRef //获取到input实例
console.info(name.value)//获取input的值
} render() {
return <div>
name: <input ref="myRef"></input>
<button onClick={this.onClick.bind(this)}>BTN</button>
</div>
}
}
  • 这里我们为input 加了一个ref属性
  • 在onClick里,通过this.refs.myRef可以获取到这个input的实例,然后获取它的value值

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/585923.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存