在组件上面,声明属性,会直接放到实例对象的props属性中。
这样外部组件传递过来的值,就可以直接调用了。
<script type="text/babel">
// 创建组件
class Person extends React.Component{
render() {
console.log(this)
let {name,age,sex} = this.props
return (
<div>
<ul>
<li>姓名:{name}</li>
<li>性别:{age}</li>
<li>年龄:{sex}</li>
</ul>
</div>
);
}
}
// 渲染组件到页面
ReactDOM.render(<Person name="tom" age="18" sex="男"/>,document.getElementById('test'))
</script>
** …xxx 叫做 展开运算符:**
在React中就可以使用这种方式,因为babel和react是能够进行加工操作的!
props的写法有以下两种:(知道就好,第一种已经弃用。)
对组件的props进行限制,就需要到了prop-types.js功能包。
引入prop-types.js:用于对组件标签属性进行限制。
<body>
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 4.引入prop-types.js:用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
// 创建组件
class Person extends React.Component{
render() {
console.log(this)
// 调用的时候直接调用props里面的函数。
this.props.speak()
let {name,age,sex} = this.props
return (
<div>
<ul>
<li>姓名:{name}</li>
<li>性别:{age + 10}</li>
<li>年龄:{sex}</li>
</ul>
</div>
);
}
}
// react底层会自动走propTypes,来对Person的props进行限制。
// 可以设置类型,设置是否必须等等。
Person.propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func // 如果传入函数就是func
}
// 指定默认标签属性值,也就是设置属性默认值。
Person.defaultProps = {
sex: '不男不女',
}
function speak(){
console.log('我说话了')
}
const p = {name:'老刘',age:18}
// 渲染组件到页面
ReactDOM.render(<Person {...p} speak={speak}/>,document.getElementById('test'))
</script>
</body>
React的props是只读的。
搞懂:修改什么意思,可以理解为重新赋值的意思。就是地址发生改变。
其实下面的代码就是往Person里面添加属性,那么可以直接简写到Person类中:
// react底层会自动走propTypes,来对Person的props进行限制。
// 可以设置类型,设置是否必须等等。
Person.propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func // 如果传入函数就是func
}
// 指定默认标签属性值,也就是设置属性默认值。
Person.defaultProps = {
sex: '不男不女',
}
简写形式如下:
class Person extends React.Component{
// 定义props属性
static propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func // 如果传入函数就是func
}
// 定义props默认值
static defaultProps = {
sex: '不男不女',
}
render() {
// 调用的时候直接调用props里面的函数。
this.props.speak()
let {name,age,sex} = this.props
return (
<div>
<ul>
<li>姓名:{name}</li>
<li>性别:{age + 10}</li>
<li>年龄:{sex}</li>
</ul>
</div>
);
}
}
类式组件构造器,在react中,仅用到以下两种情况:
注意点:
如果,不需要初始化constructor构造器,无影响。
如果,需要初始化了constructor构造器并且希望在构造器中通过this访问props,则必须要接受props和实现super(props),不然拿不到props!
几乎开发当中不会使用构造器的!
三大属性:state,props,refs。
函数式组件只能使用props,其他两个都不能使用。
props作为参数传递,并且限制props属性直接在外面定义就可以。
<script type="text/babel">
function Person(props){
const {name,sex,age} = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age + 1}</li>
</ul>
)
}
Person.propType = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number
}
Person.defaultProps = {
sex:'不男不女',
age:18
}
ReactDOM.render(<Person name="zhangsan" age={1}/>,document.getElementById('test'))
</script>
通过refs属性就可以操作对应dom节点:
<script type="text/babel">
class Demo extends React.Component {
// 展示左侧输入框的数据
showData = ()=>{
const {input1} = this.refs
alert(input1.value)
}
// 展示右侧输入框的数据
showDate2 = () => {
const {input2} = this.refs
alert(input2.value)
}
render() {
return (
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据"/>
<button ref="button1" onClick={this.showData}>点我提示左侧的数据</button>
<input ref="input2" onBlur={this.showDate2} type="text" placeholder="失去焦点提示数据"/>
</div>
);
}
}
// 渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
官方对字符串形式的refs给出的解释:
通过回调函数的形式来实现:
// 通过回调函数的形式来给this赋值。
render() {
return (
<div>
<input ref={c=>this.input1 = c} type="text" placeholder="点击按钮提示数据"/>
</div>
);
}
案例:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsx语法规则title>
head>
<body>
<div id="test">div>
<script type="text/javascript" src="../js/react.development.js">script>
<script type="text/javascript" src="../js/react-dom.development.js">script>
<script type="text/javascript" src="../js/babel.min.js">script>
<script type="text/javascript" src="../js/prop-types.js">script>
<script type="text/babel">
class Demo extends React.Component {
// 展示左侧输入框的数据
showData = ()=>{
const {input1} = this
alert(input1.value)
}
// 展示右侧输入框的数据
showDate2 = () => {
const {input2} = this
alert(input2.value)
}
// 通过回调函数的形式来给this赋值。
render() {
return (
<div>
<input ref={c=>this.input1 = c} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showDate2} ref={c=>this.input2 = c} type="text" placeholder="失去焦点提示数据"/>
</div>
);
}
}
// 渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'))
script>
body>
html>
通过使用{}将其转换为js表达式再通过/**/来注释。
render() {
return (
<div>
<input ref={c=>this.input1 = c} type="text" placeholder="点击按钮提示数据"/>
{/* */}
<input onBlur={this.showDate2} ref={c=>this.input2 = c} type="text" placeholder="失去焦点提示数据"/>
</div>
);
}
对于ref的内联函数回调,更新dom会出现的二次调用的情况:
上面函数有对应解决办法,可以将函数放到this类实例对象当中,这样就可以直接调用了。不用再写内联函数了。
两种情况都可以,但是知道两者的区别。
React.createRef()调用后可以返回一个容器,该容器可以存储被ref所标识的节点。
注意:React.createRef()只能锁定一个节点,专人专用!
class Demo extends React.Component {
/*
React.createRef()调用后可以返回一个容器,该容器可以存储被ref所标识的节点,不过它只能锁定一个节点,专人专用!。
*/
myRef = React.createRef()
showData = ()=>{
console.log(this.myRef.current)
}
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
</div>
);
}
}
// 渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'))
原理:走到input ref={this.myRef}的时候,检测到是一个通过React.createRef()创建的容器,就会把自身节点存到里面。
目前,推荐官方使用的一种形式。但是很多开发依然用的内联函数。
React的是通过onXxx属性
指定事件处理函数,注意中间是大小写。
所谓的事件委托将事件像冒泡一样委托给了最外层的元素。
通过event.target得到发生事件的DOM元素对象:
官方给出一个 勿过度使用Refs
,其实很多时候可以直接使用event.target来获取当前节点。
非受控组件就是现用现取:
<script type="text/babel">
// 创建组件
class Login extends React.Component{
handlerSubmit = (event)=>{
const {username,password} = this
alert(`${username.value},${password.value}`)
// 阻止form表单提交
event.preventDefault() //组织form表单默认事件。
}
render() {
return (
<div>
<form action="http://www.itholmes.com" onSubmit={this.handlerSubmit}>
用户名:<input ref={c => this.username = c} type="text" name="username"/>
密码:<input ref={c => this.password = c} type="password" name="password"/>
<button>登录</button>
</form>
</div>
);
}
}
// 渲染组件
ReactDOM.render(<Login/>,document.getElementById('test'))
</script>
其实受控组件有点像vue的双向绑定效果,就像下图通过react的onChange事件来绑定到了state状态当中:
<script type="text/babel">
// 创建组件
class Login extends React.Component{
// 初始化状态
state = {
username:'',
password:''
}
saveUsername = (event)=>{
this.setState({username : this.username.value})
}
savePassword = (event)=>{
this.setState({password:this.password.value})
}
handlerSubmit = (event)=>{
// 阻止form表单提交
event.preventDefault() //组织form表单默认事件。
const {username,password} = this.state
console.log(`${username},${password}`)
}
render() {
return (
<div>
<form action="http://www.itholmes.com" onSubmit={this.handlerSubmit}>
用户名:<input onChange={this.saveUsername} ref={c => this.username = c} type="text" name="username"/>
密码:<input onChange={this.savePassword} ref={c => this.password = c} type="password" name="password"/>
<button>登录</button>
</form>
</div>
);
}
}
// 渲染组件
ReactDOM.render(<Login/>,document.getElementById('test'))
</script>
推荐使用受控组件,受控组件很少用到ref属性,而且方便。
像Promise、setTimeout、arr.map()等等接受的参数都是函数,因此他们都是高阶函数!
注意:事件下面的两个形式是不同的!
因为上面的原因,所以往后可以通过return函数的方式来赋予事件,并且简化代码:
<script type="text/babel">
// 创建组件
class Login extends React.Component{
// 初始化状态
state = {
username:'',
password:''
}
// 通过return函数来赋值给onChange事件,
saveFormData = (dataType)=>{
console.log(dataType)
return (event)=>{
// fixme [dataType] 读取对象dataType的值,对象的基本用法!!
this.setState({[dataType]:event.target.value})
console.log('dataType',dataType)
console.log('value',event.target.value)
}
}
handlerSubmit = (event)=>{
// 阻止form表单提交
event.preventDefault() //组织form表单默认事件。
const {username,password} = this.state
console.log(`${username},${password}`)
}
render() {
return (
<div>
<form action="http://www.itholmes.com" onSubmit={this.handlerSubmit}>
用户名:<input onChange={this.saveFormData('username')} type="text" name="username"/>
密码:<input onChange={this.saveFormData('password')} type="password" name="password"/>
<button>登录</button>
</form>
</div>
);
}
}
// 渲染组件
ReactDOM.render(<Login/>,document.getElementById('test'))
</script>