react基础

xiaoxiao2021-02-28  81

简介 在目前看来react毫无疑问是最流行的框架,没有之一。 之前看了阮一峰写的react基础,写的非常好。但这个教程在现在看来,有些用法已经过时了。 所以我打算用ES6语法写一篇这样的文章。 说到ES6,大家都知道目前还不能兼容所有浏览器,因此我们要用到babel。把ES6代码转化为浏览器识别的ES5代码。 在这里我用webpack搭建的环境,没用过webpack的,可以看我之前写的文章。这里就不一一讲解。


一、HTML模板


<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> <title>react主页</title> </head> <body> <div id="root"></div> <script src="http://localhost:8080/bundle.js"></script> </body> </html>

这里的root是根节点,下文就会用到 二.render


render是react的最基本语法,用于将HTML转化为语言,并插入指定的节点。 用react时我们要引进两个库 react和react-dom,用ES6中的import引进,后面每次都需要引入,不然无法执行代码。

import React,{ component } from 'react'; import { render } from 'react-dom'; render( <h1>hello world!</h1>, document.getElementById('root') )

运行结果如下:

hello world!

三、JSX语法


上一节的代码,HTML语言直接写在javascript语言中,不加任何引号,这就是JSX语法。 它允许HTML和JSX混写。

render( <div> { names.map(function(item,index){ return <h1 key={index}>hello {item}</h1> }) } </div>, document.getElementById('root') )

上面的代码体现了JSX的基本语法规则:遇到HTML(以<开头),就用HTML解析规则;遇到代码块(以{开头),就用javascript规则解析。 上面的代码运行结果如下: hello 张三 hello 李四 hello 王五

JSX允许在模板中插入javascript变量,如果这个这个变量是一个数组,会展开数组所有的成员。

var arr = [ <h1>hello 张三</h1>, <h1>hello 李四</h1> ]; render( <div>{arr}</div>, document.getElementById('root') )

执行结果如下:

hello 张三 hello 李四 四、组件


React允许将代码封装成组件(component),然后像插入普通HTML一样,在网页中插入组件。用class定义一个类组件。

class Hello extends Component{ render(){ return ( <h1>hello {this.props.name}</h1> ) } } render( <Hello name="张三" />, document.getElementById('root') )

上面代码,Hello 就是用ES6的class定义的一个类。模板插入时,就会自动生成Hello的一个实例(下文的“组件”都指组件类的实例)。所有的组件类都有自己的render方法,用于输出组件。 PS:

1.组件类的第一个字母必须大写,否则无法显示内容。比如,Hello不能写成hello。 2.组件类只能包含一个顶层标签,否则会报错。 class Hello extends Component{ render(){ return ( <h1>hello { this.props.name }</h1> <h1>小</h1> ) } } render( <Hello name="张三" />, document.getElementById('root') )

上面这个会报错。 但这样不会报错,原因正在探索中

class Hello extends Component{ render(){ return ( <h1>hello { this.props.name}</h1>, <h1>小</h1> ) } } render( <Hello name="张三" />, document.getElementById('root') )

运行的结果为 小 父组件<Hello name="张三" />中的name属性传递给子组件。this.props.name用于获取父组件传递的值。 组件的用法和原生的HTML标签完全一样,可以加入任意属性。比如,<Hello name="张三" /> 就是Hello组件加入的一个name属性,值为张三。组件的属性可以在组件的this.props对象上获取。比如那么属性就可以通过this.props.name属性读取。 添加组件属性,需要注意的地方是class属性要写成className,for属性要写成htmlFor。这是因为class和for是javascript的保留字。 五、this.props.children this.props对象的属性与组件的属性一一对应,但是有一个例外就是this.props.children属性,它表示组件的所有子节点。

class NoteList extends Component{ render(){ console.log(this.props.children); return( <div> { React.Children.map(this.props.children,function(item,index){ return <h1 key={index}>{item}</h1> }) // this.props.children.map(function(item,index){ // return <h1 key={index}>{item}</h1> // }) } </div> ) } } render( <NoteList> <span>hello</span> <span>world</span> </NoteList>, document.getElementById('root') )

上面代码的NoteList 组件有两个span子节点,它们都可以通过this.props.children读取,运行结果如下: hello world 这里要注意的是,this.props.chidren的值有3种可能 第一种可能是:没有子节点,这时它的值为undefined 第二种可能是:只有一个子节点,这时它的值是一个对象。 第三种可能是: 有两个及以上子节点时,它的值是一个数组。 如果用下面这种方法遍历时需要注意:

this.props.children.map(function(item,index){ return <h1 key={index}>{item}</h1> }) 遍历的是数组还是对象。于是react提供了一种方法,React.Children.map,不管你是数组还是对象我都可以遍历。

六、propTypes


组件的属性接受任意值,字符串、对象、函数等等都可以。有时我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。 组件类的Proptypes属性,就是用来验证组件实例的属性是否符合要求。

class Hello extends Component{ constructor(props){ super(props); } render(){ return <h1>{this.props.title}</h1> } } Hello.propTypes = { title: React.PropTypes.string }

上面的Hello组件有一个title属性。PropTypes告诉React,这个title属性时必须的,而且它的值必须是字符串,我们给它设置一个数字,看会有什么结果?

var data = 123; render( <Hello title={data} />, document.getElementById('root') )

结果呢?报错了

Warning: Failed prop type: Invalid prop `title` of type `number` supplied to `Hello`, expected `string`. in Hello

如果写成这样,title属性就不会通过验证了,控制台会会报错。

var data = '123';

此外,defaultProps可以设置组件属性的默认值。

class Hello extends Component{ constructor(props){ super(props); } render(){ return <h1>{this.props.title}</h1> } } Hello.defaultProps = { title: 'hello world' } render( <Hello />, document.getElementById('root') )

上面的代码会输出

hello world

七、获取真实的DOM节点


class Hello extends Component{ handleClick(){ this.refs.myTextInput.focus(); console.log(this.refs.myTextInput.focus()); } render(){ return ( <div> <input type="text" ref="myTextInput" /> <input type="button" value="Focus the text Input" onClick={this.handleClick.bind(this)} /> </div> ) } } render( <Hello />, document.getElementById('root') )

八、this.state


组件免不了要和用户互动,React的一大创新,就是将组件看成一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化。从而触发重新触发UI。

class Hello extends Component{ constructor(props){ super(props); this.state = { liked: false } } handleClick(){ this.setState({liked:!this.state.liked}) } render(){ var text = this.state.liked ? '喜欢':'不喜欢'; return( <p onClick={this.handleClick.bind(this)}> You {text} toggle </p> ) } } render( <Hello />, document.getElementById('root') )

我们逐个代码块分析

constructor(props){ super(props); this.state = { liked: false } }

this.state 初始化状态,所以第一次渲染完之后就是不喜欢

handleClick(){ this.setState({liked:!this.state.liked}) }

当我们发生点击事件时,就会取它相反的状态。每次修改状态之后就会调用render方法,就会再次渲染页面。 由于this.props和this.state都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是:this.props表示哪些一旦定义就不在改变的特性,而this.state是随着用户互动而产生变化的特性。

九、表单


用户在表单填入的内容属于用户和组件的互动,所以不能用this.props.

class Hello extends Component{ constructor(props){ super(props); this.state = { value: 'Hello!' } } handleClick(){ this.setState({liked:!this.state.liked}) } handleChange(e){ this.setState({value: e.target.value}) } render(){ var value = this.state.value; return( <div> <input type="text" value={value} onChange={this.handleChange.bind(this)} /> <p>{value}</p> </div> ) } } render( <Hello />, document.getElementById('root') )

上面的代码中,文本框中的值不能通过this.props.value读取,要定义onChange的回调函数。通e.target.value读取用户输入的值。textarea元素、select元素、radio元素都属于这种情况。 十、组件的生命周期


组件的生命周期分为3个状态:

Mounting: 已插入真实的DOM Updating:正在被重新渲染 UnMounting: 已移除真实的DOM

React为每个状态都提供了两种状态函数,will函数在进入状态之前调用,did函数在进入状态之后调用。三种状态共计5种处理函数。

ComponentWillMount() ComponentDidMount() componentWillUpdate(object nextProps,object nextState) componentDidUpdate(object prevProps,object prevState) componentWillUnMount()

此外,React还提供两种特殊状态的处理函数。

componentWillReceivesProps(object nextProps)已加载组件收到新的参数时调用。 shouldComponentUpdate(object nextProps,object nextState)组件判断是否重新渲染时调用 class Hello extends Component{ constructor(props){ super(props); this.state = { opacity: 1.0 } } componentDidMount(){ var opacity = this.state.opacity; this.timer = setInterval(function(){ opacity -= 0.05; if(opacity < 0.1){ opacity = 1; } this.setState({opacity: opacity}) }.bind(this),100) } render(){ return ( <h1 style={{opacity:this.state.opacity}}>Hello {this.props.name}</h1> ) } } render( <Hello name="xiao" />, document.getElementById('root') )

十一、 Ajax 组件的数据来源是通过ajax请求从服务器获取,可以使用componentDidMount()方法设置ajax请求,等请求成功之后,再用this.setState方法重新渲染UI。

class Hello extends Component{ constructor(props){ super(props); this.state = { username: '', lastGistUrl: '' } } componentDidMount() { $.get(this.props.source, function(result) { var lastGist = result[0]; //if (this.isMounted()) { this.setState({ username: lastGist.owner.login, lastGistUrl: lastGist.html_url }); //} }.bind(this)); } render(){ return( <div> {this.state.username} <a href={this.state.lastGistUrl}>here</a> </div> ) } } render( <Hello source="https://api.github.com/users/octocat/gists" />, document.getElementById('root') )
转载请注明原文地址: https://www.6miu.com/read-83053.html

最新回复(0)