We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React提供了两种方式来声明组件,一种是函数式,一种是类式,就是用ES6的class我们所有的组件都继承自React.Component 函数式很简单,就像我们平常写函数一个,接受一个参数作为输入,然后进行相应的输出,只不过它输出的jsx格式
React.Component
jsx
注意组件只能有一个根元素
function Wscats(props) { return <h1> {props.name}</h1> } //ES6 const Wscats = ({props}) => ( <div> <h1>{props.name}</h1> </div> )
import React from 'react'; //推荐这种 class Wscats extends React.Component { render() { return <h1> {this.props.name}</h1> } } //or 这种方法将要废弃 var Wscats = React.createClass({ render() { return <h1> {this.props.name}</h1> } }
HTML标签怎么使用,组件就怎么使用
HTML标签有两种使用方式
img
<img />
h1
<h1></h1>
同理,组件也有这两种使用方式。传参则像是给html标签写属性,属性名 = 属性值,如name =”Wscats” , 组件内部的props,则把这些属性组合在一起形成对象{name: "Oaoafly"}
属性名 = 属性值
props
{name: "Oaoafly"}
<Wscats name="Oaoafly" />//标签一定要闭合,就是后面的/不能漏掉 <Wscats></Wscats>
使用组件,它返回了<h1>Oaoafly</h1>,很像html代码,其实它是React所说的虚拟DOM,并不是真实的DOM,我们要把虚拟DOM渲染成真实的DOM,才能显示到页面中,这需要用到ReactDOM的render方法,它接受的第一个参数,就是虚拟DOM,第二个参数就是我们要把DOM渲染到什么地方
<h1>Oaoafly</h1>
html
ReactDOM.render( {/*虚拟DOM*/} <Wscats name="Oaoafly" />, {/*DOM渲染的地方*/} document.getElementById('root') );
render()应该是一个纯粹函数,即使不使用组件的state,每次调用都返回同样的结果,不读写DOM,不与浏览器交互,只做最单纯的渲染。当需要修改状态或有交互时,应该在componentDidMount等组件生命周期函数中进行
render()
componentDidMount
属性值是一个字符串,是最简单的方式进行传值,其实属性值可以是任何的JS表达式,只要把它们包括在{}中,在jsx中,{}里面的所有东西都当作JS表达式进行解析,比如我们向组件中传递一个数字18,我们就可以写age = {18}
{}
age = {18}
function Wscats(props) { // 新增num 属性 return <h1> {props.name} {props.age}</h1> } ReactDOM.render( <Wscats name="Oaoafly" age={16}/>, //JS表达式进行传值 document.getElementById('root'));
如果要传递多个属性, 一个一个传会很麻烦,这时可以使用对象,但如果用对象进行传值,又不符合属性名=属性值的写法,这时要用到ES6中的扩展运算符...,React对ES6中的扩展运算符(…)进行扩展,它能运用到对象上,对对象进行分割,{…obj};
属性名=属性值
...
(…)
{…obj}
var obj = { name: "Wscats", age: 16 } {…obj} => name = "Wscats", age = 16,
正好对应父组件向子组件传递数据
var obj = { name: "Wscats", age : 16 } //函数式组件 function Wscats(props) { return ( <div> <h1>{props.name}</h1> <h1>{props.age}</h1> </div> )} // 渲染成真实的DOM ReactDOM.render( <Wscats {...obj} />, document.getElementById('root') );
组件Props传对象
类式组件和函数组件可以互相组合
//类式组件 class Wscats extends React.Component { render() { return <h1> {this.props.name}</h1> } } //函数组件的组合 function App() { return ( <div> <Wscats name="Oaoafly"/> <Wscats name="Eno"/> </div> ); } ReactDOM.render( <App/>, //自闭合标签 document.getElementById('root'));
这时有两点需要注意:
render
div
类式组件和函数组件组合
使用class声明组件有一个好处,就是组件内部可以有自己的状态,给组件添加一个内部状态,用的是类的构造函数,因为构造函数保存的就是实例身上的属性,可以看成这个实例(组件)的状态, 我们组件也可以使用这个状态
在这里一定要注意调用构造函数时,super()这是ES6的语法规定,子类中没有this, 只能调用super生成子类的 this,如果在调用super之前使用this,就会报错。 这个地方其实是不会变化的,可以看成一个模式。每次给组件添加状态的时候,我们就按照这个模式书写就可以了
super()
ES6
//类式组件 class Wscats extends React.Component { constructor(props) { super(props); this.state = { date: new Date() } // 给组件添加状态 } render() { return ( <div> <h1> {this.props.name}</h1> <h2>现在时间是:{this.state.date.toLocaleTimeString()}</h2> </div> ) } } //组件的组合 function App() { return ( <div> <Wscats name="Oaoafly"/> <Wscats name="Eno"/> </div> ); } ReactDOM.render( <App/>, //自闭合标签 document.getElementById('root'));
所以往后在组件中添加状态,只要往this.state的对象中添加键值对就可以了
this.state
constructor(props){ super(props); this.state = {name: "Hello Wscats"} // 给组件添加状态 }
然后你就可以用表达式把state的状态呈现
state
<div>现在时间是:{this.state.date.toLocaleTimeString()}</div>
组件添加状态
在render方法中添加注释,要用{/* */}方式
{/* */}
{/*要添加的注释*/}
组件有状态,这涉及到组件的生命周期,react定义了非常完善的生命周期函数,组件渲染到页面中叫挂载(mounting),所以渲染完成后,叫做componentDidMount, 组件的卸载叫Unmount,所以组件将要卸载 叫做componentWillUnmount。我们想要在什么时候使用状态,就可以直接调用生命周期函数,把想要做的事情写到函数里面,生命周期函数直接写在组件内部
Unmount
componentWillUnmount
详情见 React组件生命周期
比如,页面渲染完成后时间自动加一秒,这时还要涉及到组件的状态更改。React不允许直接更改状态, 或者说,我们不能给状态(如: date)进行赋值操作, 必须调用组件的setState()方法去更改状态。这里写一个函数changeTime来更改状态
setState()
changeTime
setState更改状态
changeTime函数也可以直接写到组件里面,根据ES6class语法的规定,直接写在类中的函数都会绑定在原型上,所以this.changeTime可以调用。但要保证this指向的是我们这个组件,而不是其他的东西, 这也是在setInterval中使用箭头函数的原因
class
this.changeTime
//类式组件 class Wscats extends React.Component { constructor(props) { super(props); this.state = { date: new Date() } // 给组件添加状态 } changeTime() { this.setState({date: new Date()}) } // 生命周期函数 componentDidMount() { setInterval(() => { this.changeTime() }, 1000) } render() { return ( <div> <h1> {this.props.name}</h1> <h2>现在时间是:{this.state.date.toLocaleTimeString()}</h2> </div> ) } } //组件的组合 function App() { return ( <div> <Wscats name="Oaoafly"/> <Wscats name="Eno"/> </div> ); }
注意这里this的指向,如果不是箭头函数,this指向就是window
setInterval(function() { this.changeTime() }.bind(this), 1000) //or setInterval(() => { this.changeTime() }, 1000)
React中给元素添加事件,就像我们给元素添加行内事件一样简单,但这里也有不同的地方,事件名用驼峰命名法onClick,事件处理函数是函数名,用{}括起来
onClick
{}
handleClick(e) { e.preventDefault(); console.log(this);// null console.log("clicked"); }
在页面中点击可以看到handleClick中的事件处理函数console.log输出是null, 然后报错了。这主要是由于this是在函数运行的时候动态绑定的,this.handleClick指向了handleClick函数,点击的时候,这个函数开始执行,但this却没有指定,它是在哪个环境下执行, 由于ES6class是在严格模式下进行的,所以输出了null
我们必须使this指向我们这个组件,改变this指向可以使用两种方法,一种是ES5提供的bind()方法,它的第一个参数就是指定函数中this的,且它返回 一个函数,可以知道,返回的这个函数中this已经写死了,在程序运行的时候也不会变化了
this.handleClick = this.handleClick.bind(this)
也就是在构造函数中加上,此时调用this就可以查看修改到state的状态
constructor(props) { super(props); this.state = { date: new Date() } // 给组件添加状态 this.handleClick = this.handleClick.bind(this) }
这样也可以
<button onClick={this.handleClick.bind(this)}>点击</button>
<button onClick={() => this.handleClick()}>点击</button>
组件的this指向
生命周期相关参数,是React定义组件时提供的一系列处理函数(钓子函数),这些函数会在组件生命周期的某个阶段调用
object getDefaultProps()
object getInitialState()
在组件挂载前(即:创建期)调用一次,其返回值将做为this.state的初始值
getInitialState()方法会组件类创建的时候调用一次,其返回值会被缓存下来。该方法用于设置props属性的默认值,但仅对于非必须属性。如果父组件没有指定props中的某个值,此返回对象中的相应属性将会合并到this.props
getInitialState()
this.props
getInitialState()方法会在组件实例创建前调用,这时还不能使用this.props属性,且其返回对象是在所有实例间共享的
componentWillMount()
componentWillMount()服务器端和客户端都只调用一次,在初始化渲染执行之前被调用。如果在这个方法内调用setState()方法,render()方法将会收到更新后的state,也就是说这是我做在组件渲染前最后一个修改state的机会
componentDidMount()
componentDidMount()会在组件初始化(渲染完成)后立即调用一次,我们一般在这个方法中使用this.getDOMNode()方法访问原始DOM
this.getDOMNode()
componentWillReceiveProps(object nextProps)
componentWillReceiveProps()方法会在组件生命周期的存在期调用,当组件感知到props属性改变会,会调用此方法。render()方法将会在其后调用,这时我们可以通过this.setState()来阻止组件的再次渲染。
componentWillReceiveProps()
this.setState()
boolean shouldComponentUpdate(object nextProps, object nextState)
shouldComponentUpdate()方法发生在组件生命周期的存在器,在组件收到新的props或state。在这个方法中,我们可以访问组件的props和state属性,通过这两个属性可以确认组件是否需要更新,如果不需要更新,则返回false,则其后的方法将不会在执行。如:
shouldComponentUpdate()
shouldComponentUpdate: function(nextProps, nextState) { return nextProps.id !== this.props.id; }
componentWillUpdate(object nextProps, object nextState)
componentWillUpdate()会在收到新的props或state后调用,类似componentWillMount()
componentWillUpdate()
componentDidUpdate(object prevProps, object prevState)
componentDidUpdate()会在组件重新渲染后立即被调用,当我们需要在组件重新渲染后操作DOM则需要使用这个方法
componentDidUpdate()
componentWillUnmount()
componentWillUnmount()是组件销毁&清理期唯一调用的方法,它会在组件从DOM中移除时被调用,这时我们可以清理一些状态或清理在componentDidMount中创建的DOM元素
可以配置less样式,然后导入到组件,然后利用less的命名空间来约束组件的样式
import React, { Component } from 'react'; import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; import { matchRoutes, renderRoutes } from 'react-router-config'; import "./root.less"; //新版本的写法 推荐 //class Wscats extends React.Component { class Wscats extends Component { render() { return( <div id="root"> <h1>Root</h1> <Link to="/">home</Link> <Link to="/index">index</Link> {/* child routes won't render without this */} {renderRoutes(this.props.route.routes)} {console.log(this)} </div> ) } } module.exports = Wscats;
root.less
#root { h1 { font-size: 50px; color: green; } }
平时我们习惯一个单JSX文件导出一个组件,事实上,我们可以一个JSX文件导出多个组件,例如我们可以把一类相似功能的组件放在一起,然后类声明多个组件,然后再导出,我们就可以在使用的时候,导入一个组件,从而使用多个组件的功能
import React from "react"; // 第一个公有组件 class PublicA extends React.Component { constructor(props) { super(props) this.state = {} } render() { return ( <div> 第一个公有组件 </div> ) } } // 第二个公有组件 class PublicB extends React.Component { constructor(props) { super(props) this.state = {} } render() { return ( <div> 第二个公有组件 </div> ) } } // 默认导出一个,仅且一个 // export default PublicA // 导出多个 export {PublicA, PublicB}
注意这里我们用的是export{xxx}而不是export default xxx
export{xxx}
export default xxx
下面我们使用的时候就可以引入一个JSX文件,但是同时导入了PublicA和PublicB组件了
import React from 'react'; // 导入多个组件 import {PublicA, PublicB} from "../components/public.jsx"; class PageB extends React.Component { constructor(props) { super(props); // 设置 initial state this.state = {}; } componentDidMount() {} render() { return ( <div> <PublicA/> <PublicB/> </div> ) } } export default PageB;
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Uh oh!
There was an error while loading. Please reload this page.
React组件
React提供了两种方式来声明组件,一种是函数式,一种是类式,就是用ES6的class我们所有的组件都继承自
React.Component
函数式很简单,就像我们平常写函数一个,接受一个参数作为输入,然后进行相应的输出,只不过它输出的
jsx
格式函数式组件
注意组件只能有一个根元素
类式组件
渲染组件
HTML标签有两种使用方式
img
自闭合标签<img />
h1
之类的双标签<h1></h1>
同理,组件也有这两种使用方式。传参则像是给html标签写属性,
属性名 = 属性值
,如name =”Wscats” , 组件内部的props
,则把这些属性组合在一起形成对象{name: "Oaoafly"}
使用组件,它返回了
<h1>Oaoafly</h1>
,很像html
代码,其实它是React所说的虚拟DOM,并不是真实的DOM,我们要把虚拟DOM渲染成真实的DOM,才能显示到页面中,这需要用到ReactDOM的render方法,它接受的第一个参数,就是虚拟DOM,第二个参数就是我们要把DOM渲染到什么地方render()
应该是一个纯粹函数,即使不使用组件的state,每次调用都返回同样的结果,不读写DOM,不与浏览器交互,只做最单纯的渲染。当需要修改状态或有交互时,应该在componentDidMount
等组件生命周期函数中进行Props传值
属性值是一个字符串,是最简单的方式进行传值,其实属性值可以是任何的JS表达式,只要把它们包括在
{}
中,在jsx中,{}
里面的所有东西都当作JS表达式进行解析,比如我们向组件中传递一个数字18,我们就可以写age = {18}
如果要传递多个属性, 一个一个传会很麻烦,这时可以使用对象,但如果用对象进行传值,又不符合
属性名=属性值
的写法,这时要用到ES6中的扩展运算符...
,React对ES6中的扩展运算符(…)
进行扩展,它能运用到对象上,对对象进行分割,{…obj}
;正好对应父组件向子组件传递数据
组件Props传对象
类式组件和函数组件可以互相组合
这时有两点需要注意:
html
标签进行区分render
方式中把所有元素都放到一个div
元素中的原因类式组件和函数组件组合
组件状态
使用class声明组件有一个好处,就是组件内部可以有自己的状态,给组件添加一个内部状态,用的是类的构造函数,因为构造函数保存的就是实例身上的属性,可以看成这个实例(组件)的状态, 我们组件也可以使用这个状态
在这里一定要注意调用构造函数时,
super()
这是ES6
的语法规定,子类中没有this, 只能调用super生成子类的 this,如果在调用super之前使用this,就会报错。 这个地方其实是不会变化的,可以看成一个模式。每次给组件添加状态的时候,我们就按照这个模式书写就可以了所以往后在组件中添加状态,只要往
this.state
的对象中添加键值对就可以了然后你就可以用表达式把
state
的状态呈现组件添加状态
注释
在render方法中添加注释,要用
{/* */}
方式生命周期
组件有状态,这涉及到组件的生命周期,react定义了非常完善的生命周期函数,组件渲染到页面中叫挂载(mounting),所以渲染完成后,叫做
componentDidMount
, 组件的卸载叫Unmount
,所以组件将要卸载 叫做componentWillUnmount
。我们想要在什么时候使用状态,就可以直接调用生命周期函数,把想要做的事情写到函数里面,生命周期函数直接写在组件内部详情见 React组件生命周期
比如,页面渲染完成后时间自动加一秒,这时还要涉及到组件的状态更改。React不允许直接更改状态, 或者说,我们不能给状态(如: date)进行赋值操作, 必须调用组件的
setState()
方法去更改状态。这里写一个函数changeTime
来更改状态setState更改状态
changeTime
函数也可以直接写到组件里面,根据ES6class
语法的规定,直接写在类中的函数都会绑定在原型上,所以this.changeTime
可以调用。但要保证this指向的是我们这个组件,而不是其他的东西, 这也是在setInterval中使用箭头函数的原因注意这里this的指向,如果不是箭头函数,this指向就是window
React中给元素添加事件,就像我们给元素添加行内事件一样简单,但这里也有不同的地方,事件名用驼峰命名法
onClick
,事件处理函数是函数名,用{}
括起来在页面中点击可以看到handleClick中的事件处理函数console.log输出是null, 然后报错了。这主要是由于this是在函数运行的时候动态绑定的,this.handleClick指向了handleClick函数,点击的时候,这个函数开始执行,但this却没有指定,它是在哪个环境下执行, 由于ES6
class
是在严格模式下进行的,所以输出了null我们必须使this指向我们这个组件,改变this指向可以使用两种方法,一种是ES5提供的bind()方法,它的第一个参数就是指定函数中this的,且它返回 一个函数,可以知道,返回的这个函数中this已经写死了,在程序运行的时候也不会变化了
解决方案1
也就是在构造函数中加上,此时调用this就可以查看修改到state的状态
解决方案2
这样也可以
解决方案3
组件的this指向
生命周期相关参数,是React定义组件时提供的一系列处理函数(钓子函数),这些函数会在组件生命周期的某个阶段调用
在组件挂载前(即:创建期)调用一次,其返回值将做为this.state的初始值
getInitialState()
方法会组件类创建的时候调用一次,其返回值会被缓存下来。该方法用于设置props属性的默认值,但仅对于非必须属性。如果父组件没有指定props中的某个值,此返回对象中的相应属性将会合并到this.props
getInitialState()
方法会在组件实例创建前调用,这时还不能使用this.props
属性,且其返回对象是在所有实例间共享的componentWillMount()
服务器端和客户端都只调用一次,在初始化渲染执行之前被调用。如果在这个方法内调用setState()
方法,render()
方法将会收到更新后的state,也就是说这是我做在组件渲染前最后一个修改state的机会componentDidMount()
会在组件初始化(渲染完成)后立即调用一次,我们一般在这个方法中使用this.getDOMNode()
方法访问原始DOMcomponentWillReceiveProps()
方法会在组件生命周期的存在期调用,当组件感知到props属性改变会,会调用此方法。render()
方法将会在其后调用,这时我们可以通过this.setState()
来阻止组件的再次渲染。shouldComponentUpdate()
方法发生在组件生命周期的存在器,在组件收到新的props或state。在这个方法中,我们可以访问组件的props和state属性,通过这两个属性可以确认组件是否需要更新,如果不需要更新,则返回false,则其后的方法将不会在执行。如:componentWillUpdate()
会在收到新的props或state后调用,类似componentWillMount()
componentDidUpdate()
会在组件重新渲染后立即被调用,当我们需要在组件重新渲染后操作DOM则需要使用这个方法componentWillUnmount()
是组件销毁&清理期唯一调用的方法,它会在组件从DOM中移除时被调用,这时我们可以清理一些状态或清理在componentDidMount
中创建的DOM元素样式
可以配置less样式,然后导入到组件,然后利用less的命名空间来约束组件的样式
root.less
导出多个组件
平时我们习惯一个单JSX文件导出一个组件,事实上,我们可以一个JSX文件导出多个组件,例如我们可以把一类相似功能的组件放在一起,然后类声明多个组件,然后再导出,我们就可以在使用的时候,导入一个组件,从而使用多个组件的功能
下面我们使用的时候就可以引入一个JSX文件,但是同时导入了PublicA和PublicB组件了
The text was updated successfully, but these errors were encountered: