React之父子组件传递和其它一些要点
react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度。下面对一些react日常开发中的注意事项进行罗列。
React的组件生命周期
react主要思想是构建可复用组件来构建用户界面。在react里面一切皆组件。每个组件里面都是有自己的生命周期,这个生命周期规定了组件的状态和方法,分别在哪个阶段执行。下面附上一张React的生命周期图:
组件第一阶段:初始化、渲染以及装载完成;
组件第二阶段:组件运行时候的状态 ①:状态变化引发组件的更新和重新渲染到更新完成
②:父组件属性变化引发组件的更新(是常见的组件之间传递数据和同步状态的手段):比如父组件登录了,子组件也需变成登录状态
组件第三阶段:卸载组件
JSX 语法
const names = ['Alice', 'Emily', 'Kate'];
ReactDOM.render(
<div>
{
names.map((name) => {
return <div>Hello, {name}!</div>
})
}
</div>,
document.getElementById('example')
);
JSX 的基本语法规则:遇到 HTML 标签(以 <
开头),就用 HTML 规则解析;遇到代码块(以 {
开头),就用 JavaScript 规则解析。
所以给jsx添加注释只要这样子:
{/* 。。。 */}
父组件传向子组件
子:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
---------------------------------------
父:
ReactDOM.render(
<HelloMessage name="Muyy" />,
document.getElementById('example')
);
变量 HelloMessage
就是相当于一个子组件类。通过this.props.name获取到了Muyy。
另外注意
- 所有组件类都必须有自己的
render
方法,用于输出组件。 - 组件类的第一个字母必须大写,否则会报错,比如
HelloMessage
不能写成helloMessage
- 组件类只能包含一个顶层标签
class
属性需要写成className
,for
属性需要写成htmlFor
,这是因为class
和for
是 JavaScript 的保留字
子组件传向父(爷)组件
其实很简单,概括起来就是:react中state改变了,组件才会update。父组件写好state和处理该state的函数,同时将函数名通过props属性值的形式传入子,子调用父的函数,同时引起state变化。
例子1.这里如下图,用户邮箱为父,绿色框为子。 父组件为用户输入的邮箱设好state,即“{email: ''}”,同时写好处理state的函数,即“handleEmail”,这两个名称随意起;再将函数以props的形式传到子组件,子组件只需在事件发生时,调用父组件传过来的函数即可。
1 //子组件 2 var Child = React.createClass({ 3 render: function(){ 4 return ( 5 <div> 6 请输入邮箱:<input onChange={this.props.handleEmail}/> 7 </div> 8 ) 9 } 10 }); 11 //父组件,此处通过event.target.value获取子组件的值 12 var Parent = React.createClass({ 13 getInitialState: function(){ 14 return { 15 email: '' 16 } 17 }, 18 handleEmail: function(event){ 19 this.setState({email: event.target.value}); 20 }, 21 render: function(){ 22 return ( 23 <div> 24 <div>用户邮箱:{this.state.email}</div> 25 <Child name="email" handleEmail={this.handleEmail.bind(this)}/> 26 </div> 27 ) 28 } 29 }); 30 React.render( 31 <Parent />, 32 document.getElementById('test') 33 );
例子2.有时候往往需要对数据做处理,再传给父组件,比如过滤或者自动补全等等,下面的例子对用户输入的邮箱做简单验证,自动过滤非数字、字母和"@."以外的字符。
1 //子组件,handleVal函数处理用户输入的字符,再传给父组件的handelEmail函数 2 var Child = React.createClass({ 3 handleVal: function() { 4 var val = this.refs.emailDom.value; 5 val = val.replace(/[^0-9|a-z|\@|\.]/ig,""); 6 this.props.handleEmail(val); 7 }, 8 render: function(){ 9 return ( 10 <div> 11 请输入邮箱:<input ref="emailDom" onChange={this.handleVal}/> 12 </div> 13 ) 14 } 15 }); 16 //父组件,通过handleEmail接受到的参数,即子组件的值 17 var Parent = React.createClass({ 18 getInitialState: function(){ 19 return { 20 email: '' 21 } 22 }, 23 handleEmail: function(val){ 24 this.setState({email: val}); 25 }, 26 render: function(){ 27 return ( 28 <div> 29 <div>用户邮箱:{this.state.email}</div> 30 <Child name="email" handleEmail={this.handleEmail.bind(this)}/> 31 </div> 32 ) 33 } 34 }); 35 React.render( 36 <Parent />, 37 document.getElementById('test') 38 );
例子3.如果还存在孙子组件的情况呢?如下图,黑框为父,绿框为子,红框为孙,要求子孙的数据都传给爷爷。原理一样的,只是父要将爷爷对孙子的处理函数直接传下去。
1 //孙子,将下拉选项的值传给爷爷 2 var Grandson = React.createClass({ 3 render: function(){ 4 return ( 5 <div>性别: 6 <select onChange={this.props.handleSelect}> 7 <option value="男">男</option> 8 <option value="女">女</option> 9 </select> 10 </div> 11 ) 12 } 13 }); 14 //子,将用户输入的姓名传给爹 15 //对于孙子的处理函数,父只需用props传下去即可 16 var Child = React.createClass({ 17 render: function(){ 18 return ( 19 <div> 20 姓名:<input onChange={this.props.handleVal}/> 21 <Grandson handleSelect={this.props.handleSelect}/> 22 </div> 23 ) 24 } 25 }); 26 //父组件,准备了两个state,username和sex用来接收子孙传过来的值,对应两个函数handleVal和handleSelect 27 var Parent = React.createClass({ 28 getInitialState: function(){ 29 return { 30 username: '', 31 sex: '' 32 } 33 }, 34 handleVal: function(event){ 35 this.setState({username: event.target.value}); 36 }, 37 handleSelect: function(event) { 38 this.setState({sex: event.target.value}); 39 }, 40 render: function(){ 41 return ( 42 <div> 43 <div>用户姓名:{this.state.username}</div> 44 <div>用户性别:{this.state.sex}</div> 45 <Child handleVal={this.handleVal.bind(this)} handleSelect={this.handleSelect.bind(this)}/> 46 </div> 47 ) 48 } 49 }); 50 React.render( 51 <Parent />, 52 document.getElementById('test') 53 );
getDefaultProps && getInitialState
getDefaultProps
方法可以用来设置组件属性的默认值
var MyTitle = React.createClass({ getDefaultProps : function () { return { title : 'Hello World' }; }, render: function() { return <h1> {this.props.title} </h1>; } }); ReactDOM.render( <MyTitle />, document.body );
getInitialState 方法可以用来设置初始状态
getInitialState: function() { return {liked: false}; },
获取真实的DOM节点
从组件获取真实 DOM 的节点,这时就要用到 ref
属性
var MyComponent = React.createClass({ handleClick: function() { this.refs.myTextInput.focus(); }, render: function() { return ( <div> <input type="text" ref="myTextInput" /> <input type="button" value="Focus the text input" onClick={this.handleClick} /> </div> ); } }); ReactDOM.render( <MyComponent />, document.getElementById('example') );
上面代码中,组件 MyComponent
的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref
属性,然后 this.refs.[refName]
就会返回这个真实的 DOM 节点。
需要注意的是,由于 this.refs.[refName]
属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click
事件的回调函数,确保了只有等到真实 DOM 发生 Click
事件之后,才会读取 this.refs.[refName]
属性。
React 组件支持很多事件,除了 Click
事件以外,还有 KeyDown
、Copy
、Scroll
等,完整的事件清单请查看官方文档。
子组件传向父组件的另一种思路
父组件调用子组件的state、function,除了上面介绍的方法之外,也可以通过ref属性实现。推荐使用这种方式进行子组件向父组件的传递。举个简单的示范:
export default class 父组件a extends React.Component { constructor(props) { super(props) } render() { return ( <子组件b ref={r => this.bbbb =r} // bbbb自定义名字 /> ) } }
经过这样处理后后,现在父组件a中可以通过this.bbbb.state.xxx获取子组件的xxx状态,也可以通过this.bbbb.xxx获取子组件的xxx方法。
作者:牧云云
出处:http://www.cnblogs.com/MuYunyun/"
本文版权归作者和博客园所有,欢迎转载,转载请标明出处。
如果您觉得本篇博文对您有所收获,请点击右下角的 [推荐],谢谢!