3、React-----组件(实例)的三大核心属性

一、组件(实例)的三大核心属性1:state

1、初始化 state

1.1 理解

1)state 是组件对象最重要的属性,值是对象(可以包含多个 key- value 的组合)

2)组件被称为 “状态机” ,通过更新组件的 state 来更新对应的页面显示(重新渲染组件)

1.2 强烈注意

1)组件中 render 方法中的 this 为组件实例对象

2)组件自定义方法中的 this 为 undefined ,如何解决?—

     a、强制绑定 this ,通过函数对象中的 bind()

     b、箭头函数

3)状态数据,不能直接修改或者更新。

1.3 例子

1)例子 1

//1.创建组件
class Weather extends React.Component{
	constructor(props){
		super(props)
		//初始化状态
		this.state = {isHot:true}
	}
	render(){
		//读取状态
		console.log(this)
		return <h1>今天天气很{this.state.isHot?"炎热":"凉爽"}</h1>
	}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));
2)例子 2
//1.创建组件
class Weather extends React.Component{
	constructor(props){
		super(props)
		//初始化状态
		this.state = {isHot:true}
	}
	render(){
		//读取状态
		const {isHot} = this.state
		return 

今天天气很{isHot?"炎热":"凉爽"}

} } //2.渲染组件到页面 ReactDom.render(, document.getElementById("test"));

3)例子 3


//1.创建组件
class Weather extends React.Component{
	constructor(props){
		super(props)
		//初始化状态
		this.state = {isHot:true}
	}
	render(){
		//读取状态
		const {isHot} = this.state
        //注意 : 1、react 中的绑定点击事件必须是onClick 不能是 onclick
        //2、不能写带有括号的这种赋值 onClick={Demo()},只需要把 函数名称 给事件就好,react 会帮你调用
		return <h1 onClick={demo}>今天天气很{isHot?"炎热":"凉爽"}</h1>
	}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));

function demo(){
    // 无法获取到 this
	console.log("标题被点击了");
}

4)例子4

//1.创建组件
class Weather extends React.Component{
	constructor(props){
		super(props)
		//初始化状态
		this.state = {isHot:true}
	}
	render(){
		//读取状态
		const {isHot} = this.state
		return <h1 onClick={this.changeWeather}>今天天气很{isHot?"炎热":"凉爽"}</h1>
	}
    changeWeather(){
    // changeWeather 放在了哪里?---Weather 的原型对象上,供 Weather 的实例使用
     // 通过 Weather 实例调用 changeWeather 时, changeWeather 中的 this 就是 Weather 实例
        // 由于 changeWeather 是作为 onClick 的回调,所以不是通过实例调用的,是直接调用
        //类中的方法默认开启了局部的严格模式, 所以 changeWeather 中的 this 为 undefined
		console.log(this);
	}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));

5)例子5---->类中方法的 this 指向

//1.创建组件
class Weather extends React.Component{
//构造器调用几次?---->1次
	constructor(props){
		super(props)
		//初始化状态
		this.state = {isHot:true}
		//解决 changeWeather 中的 this 指向问题
        this.changeWeather = this.changeWeather.bind(this)
	}
	//render 调用几次?---->1+n 次,1 是初始化的那一次,n 是状态更新的次数
	render(){
		//读取状态
		const {isHot} = this.state
		return <h1 onClick={this.changeWeather}>今天天气很{isHot?"炎热":"凉爽"}</h1>
	}
	//changeWeather 调用几次?----> 点击几次就调用几次
    changeWeather(){
    // changeWeather 放在了哪里?---Weather 的原型对象上,供 Weather 的实例使用
     // 通过 Weather 实例调用 changeWeather 时, changeWeather 中的 this 就是 Weather 实例
        // 由于 changeWeather 是作为 onClick 的回调,所以不是通过实例调用的,是直接调用
        //类中的方法默认开启了局部的严格模式, 所以 changeWeather 中的 this 为 undefined
		//console.log(this);
		//获取原来的 isHot 的值,下面两行代码可以正常更改值,但是 react 的 状态不可以直接更改
		const isHot = this.state.isHot;
		//严重注意, 状态{state} 不可直接更改,下面这行就是直接更改
		//this.state.isHot = !isHot; //这是错误的写法
		console.log(this); // Weather 的实例对象
		//严重注意:状态必须经过 setState 进行更改,且更新是一种合并,不是替换
		this.setState({isHot:!isHot});
		
	}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));

6)例子6—>state 的简写方式

//1.创建组件
class Weather extends React.Component{
//构造器调用几次?---->1次
	constructor(props){
		super(props)
		this.state = {isHot:true}
        this.changeWeather = this.changeWeather.bind(this)
	}
	//render 调用几次?---->1+n 次,1 是初始化的那一次,n 是状态更新的次数
	render(){
		//读取状态
		const {isHot} = this.state
		return <h1 onClick={this.changeWeather}>今天天气很{isHot?"炎热":"凉爽"}</h1>
	}
	//changeWeather 调用几次?----> 点击几次就调用几次
    changeWeather(){		
    	const isHot = this.state.isHot;
		this.setState({isHot:!isHot});
	}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));

二、组件(实例)的三大核心属性2:props

1、理解

1)每个组件对象都会有 props(properties 的简写)属性;
2)组件标签的所有属性都保存在 props 中

class Person extends React.Components {
	render(){
		return (
			<ul>
				<li>姓名:tome</li>
				<li>性别:女</li>
				<li>年龄:18</li>
			</ul>
		)
	}
}
//2.渲染组件到页面
ReactDom.render(<Person/>, document.getElementById("test"));
class Person extends React.Components {
	render(){
		return (
			<ul>
				<li>姓名:{this.props.name}</li>
				<li>性别:{this.props.gender}</li>
				<li>年龄:{this.props.age}</li>
			</ul>
		)
	}
}
//2.渲染组件到页面
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));
class Person extends React.Components {
	render(){
		const {name,gender,age} = this.props
		return (
			<ul>
				<li>姓名:{name}</li>
				<li>性别:{gender}</li>
				<li>年龄:{age}</li>
			</ul>
		)
	}
}
//2.渲染组件到页面
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));

3)批量传入 props 值,需要所有的字段都是一样的

class Person extends React.Components {
	render(){
		const {name,gender,age} = this.props
		return (
			<ul>
				<li>姓名:{name}</li>
				<li>性别:{gender}</li>
				<li>年龄:{age}</li>
			</ul>
		)
	}
}
//2.渲染组件到页面
const p = {name="tome", gender="女", age="18"}
ReactDom.render(<Person {...p}/>, document.getElementById("test"));

4) … 展开运算符

<script type="text/javascript">
	let arr1 = [1,3,5,7,9];
	let arr2 = [2,4,6,8,10];
	console.log(...arr1);//展开一个数组
	let arr3 = [...arr1,...arr2];//连接两个数组
	console.log(arr3)
	//在函数中使用
	function sum (...numbers){
		return numbers.reduce((preVal,curVal)>{
			return preVal+curVal;
		})
	}
	console.log(sum(1,2,3,4))
	// ... 运算符不可以展开一个对象,但是在最外层加一个 花括号 可以复制一个对象(不会影响原对象---深克隆)
	let person = {name:"tom",age:18}
	let person2 = {...person}
	person.name ="jerry";
	console.log(person)
	console.log(person2)
</script>
class Person extends React.Components {
	render(){
		const {name,gender,age} = this.props
		return (
			<ul>
				<li>姓名:{name}</li>
				<li>性别:{gender}</li>
				<li>年龄:{age}</li>
			</ul>
		)
	}
}
//2.渲染组件到页面
//加规则---需要引入 prop-type 用于对组件标签属性进行(类型,必要性)限制
Person.propType = {
	name:PropTypes.string // name  name:PropTypes.string必须是字符串类型 ,name:PropTypes.string.isRequired 必传name 值。
}
Person.defaultProps = {
	name:"大黄" //名字不传的时候 ,默认值
}
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));
class Person extends React.Components {
	static propType = {
		name:PropTypes.string // name  name:PropTypes.string必须是字符串类型 ,name:PropTypes.string.isRequired 必传name 值。
	}
	static defaultProps = {
		name:"大黄" //名字不传的时候 ,默认值
	}
	
	render(){
		const {name,gender,age} = this.props
		return (
			<ul>
				<li>姓名:{name}</li>
				<li>性别:{gender}</li>
				<li>年龄:{age}</li>
			</ul>
		)
	}
}

ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));

2、作用

1)通过标签属性从组件外 向组件内传递变化的数据
2)注意:组件内部不要修改 props 数据

三、组件(实例)的三大核心属性3:refs

1、理解

组件内中的标签可以定义 ref 属性来标识自己

2、编码

1)字符串形式的 ref(最新的react 不推荐使用了,有可能是会被移除)

<script type="text/babel">
//创建组件
 class Demo extends React.Component{
 	showData=()=>{
 		const {input1}=this.refs;
 		alert(input1.value)
 	}
 	showData2=()=>{
 		const {input2}=this.refs;
 		alert(input2.value)
 	}
	render(){
		return {
			<div>
				<input ref='input1' type="text" placeholder="点击按钮提示数据"/>
				<button onClick={this.showData}>点我提示左侧的数据</button>
				<input ref='input2' onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
			</div>
		}
	}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>

2)回调函数形式的ref

<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
<script type="text/babel">
//创建组件
 class Demo extends React.Component{
 	showData=()=>{
 		alert(this.input1.value)
 	}
 	showData2=()=>{
 		alert(this.input2.value)
 	}
	render(){
		return {
			<div>
				<input ref=(currentNode)=>{this.input1 = currentNode} type="text" placeholder="点击按钮提示数据"/>
				<button onClick={this.showData}>点我提示左侧的数据</button>
				<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
			</div>
		}
	}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>

回调形式的ref 中回调的使用次数
关于回调 refs 的说明: 如果 ref 回调函数是 以内联函数的方式定义的,在更新过程中她会被执行两次,第一次是传入参数 null ,然后第二次会传入参数 DOM 元素,这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的,通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。

<script type="text/babel">
//创建组件
 class Demo extends React.Component{
 	state = {isHot:true}
 	changeWeather()=>{
 		const {isHot} = this.state;
 		//更新状态
 		this.setState({isHot:!isHot})
 	}
 	showInfo=()=>{
 		alert(this.input1.value)
 	}
	render(){
		const {isHot} = this.state;
		return {
			<div>
				<h2>今天天气很{isHot?'炎热':'凉爽'}</h2>
				<button onClick={this.changeWeather}>点我切换天气</button>
				<input ref=(currentNode)=>{this.input1 = currentNode;console.log("@",currentNode)} type="text" placeholder="点击按钮提示数据"/>
				<button onClick={this.showInfo}>点我提示输入的数据</button>
			</div>
		}
	}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>

render 中 jsx 的 注释写法:

{/**/}
  1. React.createRef
<script type="text/babel">
//创建组件
 class Demo extends React.Component{
 /*
 React.createRef 调用后可以返回一个容器,该容器可以存储 被 ref 所标识的节点,官方最推荐的一种写法
 */
 	myRef = React.createRef()
 	showData=()=>{
 		alert(this.input1.value)
 	}
 	showData2=()=>{
 		alert(this.input2.value)
 	}
	render(){
		return {
			<div>
				<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
				<button onClick={this.showData}>点我提示左侧的数据</button>
				<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
			</div>
		}
	}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>

3、事件处理

  1. 通过 onXXX 属性指定事件处理函数(注意大小写)
        a、React 使用的是自定义(合成)事件,而不是使用的原生 DOM 事件—为了更好的兼容性
        b、React 中的事件是通过事件委托方式处理的(委托给组件最外层的元素)—为了高效
    3)通过 event.target 得到发生事件的 DOM 元素对象 — 不要过度使用 ref
<script type="text/babel">
//创建组件
 class Demo extends React.Component{
 /*
 React.createRef 调用后可以返回一个容器,该容器可以存储 被 ref 所标识的节点,官方最推荐的一种写法
 */
 	myRef = React.createRef()
 	showData=()=>{
 		alert(this.input1.value)
 	}
 	showData2=()=>{
 		alert(this.input2.value)
 	}
	render(){
		return {
			<div>
				<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
				<button onClick={this.showData}>点我提示左侧的数据</button>
				<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
			</div>
		}
	}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>

你可能感兴趣的:(React,react.js,javascript,前端)