React项目的入口文件(create-react-app):index.js
1、React.StrictMode:检测工具,检查React项目是否存在潜在风险。不会渲染任何真是的DOM。可以用在任何地方:
(1)识别不具备生命周期的组件
(2)检查旧式字符串的用法
(3)检查弃用的方法
什么是组件:是视图的抽象
(1)函数组件:推荐使用
(2)类组件:必须继承自React.Component类,并且必须有render方法,在render方法中用return语句来定义要渲染的视图。
a、组件文件的扩展名可以是.js,也可以是.jsx
b、等价于<>>
c、在return中必须要有一个根标签
组件间的通信:是单向数据流设计,即数据只能从父级向子级一层一层向下传递
(1)父级向子级通信:在父组件中调用子组件时,只需要将想要传递的数据加在子组件的属性上,然后子组件内部通过props属性来接收。
☀️举个例子:
创建data目录,再创建一个子文件index.js文件
let data = {
famliy:{
title:'家人',
list:[
{name:'爸爸'},
{name:'妈妈'}
]
},
friend:{
title:'朋友',
list:[
{name:'郭靖'},
{name:'黄蓉'},
{name:'老顽童'}
]
},
customer:{
title:'客户',
list:[
{name:'阿里'},
{name:'腾讯'},
{name:'小米'}
]
}
}
export default data
App.js父组件:
import logo from './logo.svg';
import './App.css';
import First from "./components/First"
import data from './data/index'
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
</header>
{
Object.keys(data).map((itemName)=>{
return <First key ={itemName} dlData={ data[itemName] } />
})
}
</div>
);
}
export default App;
First.jsx子组件:
import React,{ Component } from "react";
class First extends Component {
render() {
let {dlData} = this.props
return (
<>
<dl className="first-group">
<dt>{dlData.title}</dt>
{
dlData.list.map((item, index) => {
return <dd key={index}> {item.name} </dd>
})
}
</dl>
</>
)
}
}
export default First;
效果展示:
(2)子组件向父组件传递数据:React是单向数据流,无法从子组件直接将数据传递给父组件。可以在父组件中定义好回调函数,把回调函数传递给子组件,利用回调函数向父组件传递数据。
☀️举个例子:
Father.jsx父组件:
import React,{Component} from "react";
import Son from "./Son"
class Father extends Component{
constructor(props) {
super(props);
}
showInfo(name){//回调函数
console.log('子组件的Name:'+name)
}
render(){
return(
<Son openShow = {this.showInfo}/>//将回调函数传递给子组件
)
}
}
export default Father
Son.jsx子组件:
import React,{Component } from "react";
class Son extends Component{
constructor(props) {
super(props);
}
render(){
let { openShow } = this.props
return (
<button onClick={()=>{
openShow('刘备')
}}>我是子组件</button>
)
}
}
export default Son;
效果显示:
点击按钮:
(3)同级组件之间的传递:React是单向数据流,同级组件之间无法直接传递数据。可以通过父组件来完成同级组件之间的数据传递。
注意:组件的状态state的使用
a、在React中,组件就是一种状态机,组件会根据状态的不同输出不同的UI。需要交互时,只需要把交互和状态关联起来。
b、定义state:state是组件实例的一个属性,它的值是一个对象在类组件的构造方法中定义
this.state = {}
c、更新state:调用setState方法。因为视图和state是绑定的,所以当state更新后,视图也会重新渲染。
过程:调用setState方法后,会根据setState传入的值,对state进行修改,根据修改后的state生成新的虚拟的DOM,将新的虚拟DOM和老的虚拟的DOM进行对比,找到修改点对象视图进行更新
注意:组件的函数绑定this的方法:组件中的普通函数是没有绑定this的(如下例子中的changeName函数要用箭头函数)
a、使用bind()函数绑定this:在构造函数中定义以下语句
this.函数名 = this.函数名.bind(this)
b、使用箭头函数
☀️举个例子:
Counter.jsx代码段:
import React,{ Component } from "react";
import Counter1 from "./Counter1";
import Counter2 from "./Counter2";
class Counter extends Component{
constructor(props) {
super(props);
this.state = { //组件的状态属性
name: '西游',
age : 50,
counter1Name:''
}
this.changeName = this.changeName.bind(this);//绑定this
}
changeName(sonName){ //没有使用箭头函数:找到this
this.setState({
counter1Name: sonName
})
}
render() {
let { name,age } = this.state
return (
<>
<p>姓名:{ name }</p>
<p>年龄:{ age }</p>
<button onClick={()=>{
this.setState({
age: ++age
})
}}>过了一年</button>
<br/><br/>
<Counter1 modifyName={ this.changeName }/>
<Counter2 counter1Name={this.state.counter1Name }/>
</>
)
}
}
export default Counter;
Counter1.jsx代码段:
import React,{Component} from "react";
export default class Counter1 extends Component{
constructor(props) {
super(props);
this.state = {
name: '张良'
}
}
render() {
let { modifyName } = this.props
return (
<div className="div1">
<button onClick={()=>{
modifyName(this.state.name)
}
}>我是Counter1</button>
<br/><br/>
<p>姓名:{ this.state.name }</p>
</div>
)
}
}
Counter2.jsx代码段:
import React,{ Component } from "react";
export default class Counter2 extends Component{
render() {
let { counter1Name } = this.props
return (
<div className="div2">
<button>我是Counter2</button>
<br/><br/>
<p>
来自Counter1的Name: { counter1Name }
</p>
</div>
)
}
}
App.js代码段:
import './App.css';
import Counter from './components/Counter'
import CounterTwo from "./components/CounterTwo";
import CounterOne from "./components/CounterOne";
function App() {
return (
<div className="App">
<Counter/>
<CounterOne/>
<CounterTwo/>
</div>
)
}
export default App;
index.css代码段:
.div1{
width:100px;
height:100px;
background-color: red;
margin-left: 100px;
}
.div2{
width:300px;
height:100px;
background-color: blue;
margin-left: 200px;
color:white;
}