React
引用jspang的资源
入门案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="reactContainer"></div>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script>
var HelloComponent =React.createClass({
render:function(){
return React.createElement('h1',null,'Hello world');
}
});
ReactDOM.render(
React.createElement(HelloComponent,null),
document.getElementById('reactContainer')
)
</script>
</body>
</html>
JSX
JSX即Javascript XML,它使用XML标记来创建虚拟DOM和声明组件。
JSX 如果要使用JSX语法的支持,你可以使用Babel来进行转换,但是为了方便我们这里直接引入Babel的核心文件 browser.min.js。你可以去网上提供的静态资源库引用(
http://www.bootcdn.cn/),也可以自己下载。
JSX 入门
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="reactContainer"></div>
<script type="text/babel">
var HelloComponent =React.createClass({
render:function(){
return <h1>Hello World</h1>;
}
});
ReactDOM.render(
<HelloComponent/>,
document.getElementById('reactContainer')
)
</script>
</body>
</html>
JSX 渲染数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="reactContainer"></div>
<script type="text/babel">
let names = ['JSPang','技术胖','React']; var HelloComponent =React.createClass({ render:function(){ return
<div>
{ names.map(function(name){ return
<div key={name}>Hello,{name}!</div>
}) }
</div>
} }); ReactDOM.render(
<HelloComponent name="jspang" />, document.getElementById('reactContainer') )
</script>
</body>
</html>
JSX允许直接在模版插入JavaScript变量。如果这个变量是一个数组,则会展开这个数组的所有成员。
let arr=[
<h1 key="1">Hello world!</h1>,
<h2 key="2"> React is awesome</h2>
];
ReactDOM.render(
<div>{arr}</div>, document.getElementById('reactContainer') )
React 组件– state
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="reactContainer"></div>
<script type="text/babel">
var TextBoxComponent = React.createClass({
getInitialState:function(){
return {enable:false}
},
handleClick:function(event){
this.setState({enable:!this.state.enable})
},
render:function(){
return (
<p>
<input type="text" disabled={this.state.enable} />
<button onClick={this.handleClick}>改变textbox状态</button>
</p>
)
}
});
ReactDOM.render(<TextBoxComponent/>,document.getElementById("reactContainer"));
</script>
</body>
</html>
getInitialState函数必须有返回值,可以是null,false,一个对象
React组件—props
props是组件固有属性的集合,其数据由外部传入,一般在整个组件的生命周期中都是只读的。
render函数应该是纯粹的,也就是说,在render函数内不应该修改组件state,不读写DOM信息,也不与浏览器交互。如果需要交互,应该在生命周期中进行交互。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
let HelloBox=React.createClass({
render:function(){
return <div>{'Hello '+this.props.myattr}</div>;
}
})
ReactDOM.render(<HelloBox myattr="world"/>,document.getElementById("demo"));
</script>
</body>
</html>
React组件 — 生命周期
omponentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
var AddCount=React.createClass({
getInitialState:function(){
console.log('1...getInitialSate');
return {count:1};
},
componentWillMount:function(){
console.log('2...componentWillMount');
},
componentDidMount:function(){
console.log('3...componentDidMount');
},
componentWillUpdate:function(){
console.log('4...componentWillUpdate');
},
componentDidUpdate:function(){
console.log('4...componentDidUpdate');
},
handleClick:function(event){
this.setState({count:this.state.count+1})
},
render:function(){
return(
<p>
{this.state.count}<br/>
<button onClick={this.handleClick}>Add</button>
</p>
)
}
})
ReactDOM.render(
<AddCount/>,
document.getElementById("demo")
);
</script>
</body>
</html>
React 组件 — this.props.children
组件经常会写入很多子属性,就像我们HTML当中的<ul>下,一定有很多<li>标签。这种子属性的需求,就要用到this.props.children属性。
这里需要注意,this.props.children的值有三种可能,如果当前组件没有子节点,他就是undfined;如果有一个子节点,数据类型是object;如果有多个子节点,数据类型就是array。所以处理this.proprs.children的时候要小心。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
var NotesList=React.createClass({ render:function(){ return(
<ol>
{ React.Children.map(this.props.children,function(child){ return(
<li>{child}</li>) }) }
</ol>
) } }); ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>, document.getElementById("demo") );
</script>
</body>
</html>
React组件—props验证
React引入了propTypes机制。React.PropTypes提供各种验证器(validator)来验证传入数据的有效性。当向props传入无效数据时,React会在JavaScript控制台抛出警告。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
var MyTitle = React.createClass({
propTypes:{
title:React.PropTypes.string.isRequired,
},
render:function(){
return <h2>{this.props.title}</h2>
}
})
var data=123;
ReactDOM.render(<MyTitle title={data}/>,document.getElementById('demo'));
</script>
</body>
</html>
使用getDefaultProps方法可以用来设置组件属性的默认值。
var MyTitle = React.createClass({
getDefaultProps:function(){
return {
title:'Hello JSPang'
}
},
render:function(){
return <h2>{this.props.title}</h2>
}
})
ReactDOM.render(<MyTitle/>,document.getElementById('demo'));
React组件 — 获取真实的DOM节点
从组件中获取真实的DOM节点,来进行业务逻辑的编写,React为我们提供了ref属性。下面我们通过一个实例来了解Ref的用法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
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("demo")
)
</script>
</body>
</html>
React表单–bind
事件响应 表单组件可以通过设置onChange()回调函数来监听组件变化。当用户的交互行文导致一下变化时,onChange()被执行并通过浏览器做出响应。
bind复用 bind方法为事件相应函数增加一个参数,事件响应函数通过该参数识别事件源。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
var MyForm = React.createClass({
getInitialState:function(){
return{
username:'',
gender:'man',
checked:true
}
},
handleChange:function(name,event){
var newState={};
newState[name]=name=="checked"?event.target.checked:event.target.value;
this.setState(newState);
console.log(newState);
},
submitHandler:function(e){
e.preventDefault();
var is = this.state.checked?'是':'不是';
var gender= this.state.gender == "man" ? "帅哥":"美女";
alert(this.state.username+ is + gender +'.' );
},
render:function(){
return (<form onSubmit={this.submitHandler}>
<label htmlFor="username">情输入您的姓名:</label>
<input type="text" name="username" onChange={this.handleChange.bind(this,"username")} value={this.state.username} id="username" />
<br/>
<label htmlFor="checkbox">是或否:</label>
<input type="checkbox" value="是否" name="checked" id="checkbox" onChange={this.handleChange.bind(this,"checked")} checked={this.state.checked} />
<br/>
<label htmlFor="username">请选择</label>
<select name="gender" onChange={this.handleChange.bind(this,"gender")} value={this.state.gender}>
<option value="man">帅哥</option>
<option value="woman">美女</option>
</select>
<br/>
<button type="submit">提交</button>
</form>)
}
});
ReactDOM.render(<MyForm/>,document.getElementById('demo'))
</script>
</body>
</html>
React表单—name复用
name复用方式直接读取表单的属性值,比bind写法少一个参数(React中事件响应函数会自动绑定this)。其原理是在所有的标签中设置统一的name属性,并将这个属性值对应为state属性,在事件响应函数中通过读取表单的name值获得state属性,从event.target.value获取用户输入的值(check控件稍有不同),要求所有相关的标签(包括input标签)都要统一设置name属性。–引用《React前端技术与工程实践》
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
var MyForm = React.createClass({
getInitialState:function(){
return{
username:'',
gender:'man',
checked:true
}
},
handleChange:function(event){
var newState={};
newState[event.target.name]=event.target.name=="checked"?event.target.checked:event.target.value;
this.setState(newState);
console.log(newState);
},
submitHandler:function(){
e.preventDefault();
var is = this.state.checked?'是':'不是';
var gender= this.state.gender == "man" ? "帅哥":"美女";
alert(this.state.username+ is + gender +'.' );
},
render:function(){
return (<form onSubmit={this.submitHandler}>
<label htmlFor="username">情输入您的姓名:</label>
<input type="text" name="username" onChange={this.handleChange} value={this.state.username} id="username" />
<br/>
<label htmlFor="checkbox">是或否:</label>
<input type="checkbox" value="是否" name="checked" id="checkbox" onChange={this.handleChange} checked={this.state.checked} />
<br/>
<label htmlFor="username">请选择</label>
<select name="gender" onChange={this.handleChange} value={this.state.gender}>
<option value="man">帅哥</option>
<option value="woman">美女</option>
</select>
<br/>
<button type="submit">提交</button>
</form>)
}
});
ReactDOM.render(<MyForm/>,document.getElementById('demo'))
</script>
</body>
</html>
React表单—可控组件
在React中的input标签是有些小坑的,input本身就有自己的缓存机制,然后React的State也有缓存机制。这两种缓存机制我们在编码中是要进行取舍的。将input中的value绑定到state的React组件就是可控组件,反之则是不可控组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="http://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="demo"></div>
<script type="text/babel">
var MyForm = React.createClass({
getInitialState:function(){
return {value:'jspang'}
},
handleChange:function(event){
this.setState({value:event.target.value});
console.log(this.state.value)
},
render:function(){
return(
<div>
<input type="text" value={this.state.value} onChange={this.handleChange} />
</div>
)
}
});
ReactDOM.render(<MyForm/>,document.getElementById('demo'))
</script>
</body>
</html>
React表单—不可控组件
当然我们也可以给input加入默认值,但是不是value了,而是defaultValue。
组件完成之后给它加上一个onChange事件,发现是可以监控到变化值的。如果要获得iput中的value值,需先拿到其DOM节点,然后获取其value值。
var MyForm = React.createClass({
handleChange:function(){
var inputValue=ReactDOM.findDOMNode(this.refs.jspang).value;
console.log(inputValue);
},
render:function(){
return(
<div>
<input type="text" onChange={this.handleChange} ref="jspang" defaultValue='jspang'/>
</div>
)
}
});