npx create-react-app 项目名
$ yarn start
or
$ npm start
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
// 引入根组件App
import App from './App'
// 通过调用ReactDOM的render方法渲染App根组件到id为root的dom节点上
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
index.js改造如下
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// 去掉严格模式节点
// 会添加useEffect的执行时机
//
<App />
//
);
后续所有代码片段都是在App.js里面写的
// 1.识别常规变量
const name = "萧寂";
// 2.原生js方法调用
const getAge = () => {
return 18;
};
// 3.三元运算符
const flag = true;
function App() {
return (
<div className="App">
<div>{name}</div>
<div>{getAge()}</div>
<div>{flag ? "1234" : "456"}</div>
</div>
);
}
export default App;
// 列表渲染
// 注意事项,遍历列表时,同样需要一个不可重复的key
// key仅仅在内部使用,不会渲染到页面上
const songs = [
{ id: 1, name: "痴心绝对" },
{ id: 2, name: "像我这样的人" },
{ id: 3, name: "南山南" },
];
function App() {
return (
<div className="App">
<ul>
{songs.map((item) => (
<li key={songs.id}>{item.name}</li>
))}
</ul>
</div>
);
}
export default App;
// 条件渲染
// 技术方案:1.三元表达式,2.逻辑运算符
const flag = true
function App() {
return (
<div className="App">
{/* 条件渲染字符串 */}
{flag ? "react真有趣" : "vue真有趣"}
{/* 条件渲染标签/组件 */}
{flag ? <h2>this is span</h2> : null}
{/* 逻辑运算 */}
{true && <h2>this is span</h2>}
</div>
);
}
export default App;
// 样式处理
// 1.类名样式 导入样式
import "./04 app.css";
// 2.内联/行内样式,在元素身上绑定一个style即可
const style = { color: "red", fontSize: "30px" };
// 动态控制类名
const activeflag = true;
function App() {
return (
<div className="App">
{/* 测试类名样式,通过className */}
<span className={activeflag ? "active" : ""}>测试类名样式</span>
<br></br>
{/* 内联/行内样式 */}
<span style={{ color: "red", fontSize: "30px" }}>this is span</span>
<br></br>
<span style={style}>this is span</span>
</div>
);
}
export default App;
样式渲染对应的css文件内容为
.active{
color: blue;
}
import React from "react"
// 函数组件的创建和渲染
// 创建函数组件
// 1. 组件的名称必须首字母大写,react内部会根据这个来判断是组件还是普通的HTML标签
// 2. 函数组件必须有返回值,表示该组件的 UI 结构;如果不需要渲染任何内容,则返回 null
// 3. 组件就像 HTML 标签一样可以被渲染到页面中。组件表示的是一段结构内容,对于函数组件来说,渲染的内容是函数的返回值就是对应的内容
// 4. 使用函数名称作为组件标签名称,可以成对出现也可以自闭合
function Hello () {
return <div>我是函数组件创建的组件</div>
}
// 创建类组件
// 1. 类名称也必须以大写字母开头
// 2. 类组件应该继承 React.Component 父类,从而使用父类中提供的方法或属性
// 3. 类组件必须提供 render 方法render 方法必须有返回值,表示该组件的 UI 结构
class HelloComponent extends React.Component {
render () {
return <div>我是类组件创建的组件</div>
}
}
function App () {
return <div className="App">
{/* 渲染函数组件 */}
<Hello></Hello>
{/* 渲染类组件创建的 */}
<HelloComponent></HelloComponent>
</div>
}
export default App
import React from "react"
function Hello () {
// 事件绑定
// 绑定函数组件的点击事件
const clickHandler = () => { console.log('函数组件的点击事件被触发了') }
return <div onClick={clickHandler}>我是函数组件创建的组件</div>
}
class HelloComponent extends React.Component {
// 绑定类组件的点击事件
// 事件回调函数标准写法,避免this指向问题
// 这样写,回调函数中的this指向的是当前组件实例对象
clickHandler2 = () => { console.log('类组件的点击事件被触发了') }
render () {
return <div onClick={this.clickHandler2}>我是类组件创建的组件</div>
}
}
function App () {
return <div className="App">
{/* 渲染函数组件 */}
<Hello></Hello>
{/* 渲染类组件创建的 */}
<HelloComponent></HelloComponent>
</div>
}
export default App
import React from "react"
function Hello () {
const clickHandler = (e) => {
console.log('函数组件的点击事件被触发了', e)
// 阻止a链接跳转
e.preventDefault()
}
return <div onClick={clickHandler}><a href="http://baidu.com">点击跳转百度</a></div>
}
class HelloComponent extends React.Component {
clickHandler2 = (e) => { console.log('类组件的点击事件被触发了', e) }
render () {
return <div onClick={this.clickHandler2}>我是类组件创建的组件</div>
}
}
function App () {
return <div className="App">
{/* 渲染函数组件 */}
<Hello></Hello>
{/* 渲染类组件创建的 */}
<HelloComponent></HelloComponent>
</div>
}
export default App
import React from "react"
function Hello () {
// 传递额外参数
// 当需要有参数传入并且也需要事件对象时,传参时需要把箭头函数的事件对象传入函数,只需要这样一个额外参数
// 只需要一个额外参数 () => onDel(item.id)
// 既需要事件对象也需要额外参数 (e) => onDel(e,item.id)
const clickHandler = (msg, e) => { console.log('函数组件的点击事件被触发了', msg, e) }
// 传参时候需要使用箭头函数
return <div onClick={(e) => clickHandler("this is msg", e)}>我是函数组件创建的组件</div>
}
class HelloComponent extends React.Component {
clickHandler2 = () => { console.log('类组件的点击事件被触发了') }
render () {
return <div onClick={this.clickHandler2}>我是类组件创建的组件</div>
}
}
function App () {
return <div className="App">
{/* 渲染函数组件 */}
<Hello></Hello>
{/* 渲染类组件创建的 */}
<HelloComponent></HelloComponent>
</div>
}
export default App
// 组件状态 类组件进行演示
import React from "react"
class TextComponent extends React.Component {
// 定义组件状态
state = {
// 这里定义各种属性 全都是当前组件状态
name: "cp teacher",
count: 0
};
changeName = () => {
// 修改state中的状态name
// 注意:不可以直接做复制修改,必须通过一个方法 setState
this.setState({ name: "萧寂" })
};
changeCount = () => {
// 让count的值加1
this.setState({ count: this.state.count + 1 })
};
render () {
return (<div>
{/* 渲染name */}
当前name为:{this.state.name}
{/* 修改name状态 */}
<button onClick={this.changeName}>修改name状态</button>
<button onClick={this.changeCount}>修改count++,当前为{this.count}</button>
</div>)
}
}
function App () {
return <div className="App">
<TextComponent></TextComponent>
</div>
}
export default App
/**
* 总结
* 1. 编写组件其实就是编写原生js类或者函数
* 2. 定义状态必须通过state 实例属性的方法 提供一个对象 名称是固定的就叫做state
* 3. 修改state中的任何属性 都不可以通过直接赋值 必须走setState方法 这个方法来自于继承得到
* 4. 这里的this关键字 很容易出现指向错误的问题 上面的写法是最推荐和最规范的 没有this指向问题
*/
// 表单处理
// 目标任务: 能够使用受控组件的方式获取文本框的值
// 使用React处理表单元素,一般有俩种方式:
// 1. 受控组件 (推荐使用)
// 2. 非受控组件 (了解)
// 什么是受控组件? input框自己的状态被React组件状态控制
// React组件的状态的地方是在state中,input表单元素也有自己的状态是在value中,
// React将state与表单元素的值(value)绑定到一起,由state的值来控制表单元素的值,
// 从而保证单一数据源特性
// 以获取文本框的值为例,受控组件的使用步骤如下:
// 1. 在组件的state中声明一个组件的状态数据
// 2. 将状态数据设置为input标签元素的value属性的值
// 3. 为input添加change事件,在事件处理程序中,通过事件对象e获取到当前文本框的值(即用户当前输入的值)
// 4. 调用setState方法,将文本框的值作为state状态的最新值
import React from 'react'
class InputComponent extends React.Component {
// 声明组件状态
state = {
message: 'this is message',
}
// 声明事件回调函数
changeHandler = (e) => {
this.setState({ message: e.target.value })
}
render () {
return (
<div>
{this.state.message}<br></br>
{/* 绑定value 绑定事件*/}
<input value={this.state.message} onChange={this.changeHandler} />
</div>
)
}
}
function App () {
return (
<div className="App">
<InputComponent />
</div>
)
}
export default App
// 非受控组件
import React, { createRef } from "react"
class Input extends React.Component {
msgRef = createRef() // 创建一个容器
getValue = () => {
// 通过ref获取输入框的值
// this.msgRef.current为绑定的原生dom元素
console.log(this.msgRef.current.value)
}
render () {
return (
<>
<input type="text" ref={this.msgRef} />
<button onClick={this.getValue}>点击获取输入框的值</button>
</>
)
}
}
function App () {
return (
<div className="App">
<Input></Input>
</div>
)
}
export default App
// 组件通信
// 组件是独立且封闭的单元,默认情况下组件只能使用自己的数据(state)
// 组件化开发的过程中,完整的功能会拆分多个组件,在这个过程中不可避免的需要互相传递一些数据
// 为了能让各组件之间可以进行互相沟通,数据传递,这个过程就是组件通信
// 1. 父子关系 - 最重要的
// 2. 兄弟关系 - 自定义事件模式产生技术方法 eventBus / 通过共同的父组件通信
// 3. 其它关系 - mobx / redux / zustand
// 父传子实现
// 1. 父组件提供要传递的数据 - state
// 2. 给子组件标签添加属性值为 state中的数据
// 3. 子组件中通过 props 接收父组件中传过来的数据
// a. 类组件使用this.props获取props对象
// b. 函数式组件直接通过参数获取props对象
import React from "react"
// App父组件(类组件) Son子组件(函数式和类组件)
function SonB (props) {
// props是一个对象 里面存着通过父组件传入的所有数据
// props为只读对象,不能修改
// props可以传递任何类型的数据(数组,对象,字符串,布尔,数字,JSX...)
return (
<div>我是函数子组件,--{props.msg}</div>
)
}
class SonA extends React.Component {
// 在类组件直接使用this.props.属性名拿到父组件传来的数据,这里的prop是固定的
render () {
return (<div>我是类子组件,--{this.props.msg}</div>)
}
}
class App extends React.Component {
state = {
message: "this is message"
}
render () {
return (<div>
{/* 子组件身上绑定属性,属性名可以自定义 保持语义化 */}
<SonA msg={this.state.message}></SonA>
<SonB msg={this.state.message}></SonB>
</div>)
}
}
export default App
// 组件通信
// props是一个对象 里面存着通过父组件传入的所有数据
// props为只读对象,不能修改
// props可以传递任何类型的数据(数组,对象,字符串,布尔,数字,JSX...)
import React from "react"
function SonA (props) {
console.log('props', props)
// 这里也可以将props进行解构赋值取数据,也可以直接在形参那里解构
return (
<div>
{/* 数组 */}
我是函数子组件,--{props.list.map(item => <p key={item}>{item}</p>)}
{/* 对象 */}
{props.userinfo.name}
{/* 函数 */}
<button onClick={props.getMes}>-- 父组件的函数</button><br />
{/* JSX */}
{props.child}
</div>
)
}
class App extends React.Component {
state = {
list: [1, 2, 3],
userinfo: {
name: "cp",
age: 30
},
};
getMes = () => {
console.log('父组件中的函数')
}
render () {
return (<div>
{/* 模拟传入数组,对象,函数和JSX的场景 */}
<SonA list={this.state.list} userinfo={this.state.userinfo} getMes={this.getMes} child={<span>我是传过来的JSX</span>}></SonA>
</div>)
}
}
export default App
// 组件通信
// 父传子 props 函数
// 子传父:子组件调用父组件传递过来的函数,并且把想要传递的数据当成函数的实参
// 传入即可
import React from "react"
function Son (props) {
const { getSonMsg } = props
return (
<div>
this is son
{/* 子组件向父组件传递参数 */}
<button onClick={() => getSonMsg("这里是来自于子组件的数据") }>点击执行</button>
</div>
)
}
class App extends React.Component {
// 准备数据
state = {
list: [1, 2, 3]
};
// 准备一个函数,传给子组件
getSonMsg = (a) => {
console.log('a',a);
}
render () {
return (<div>
<Son getSonMsg={this.getSonMsg}></Son>
</div>)
}
}
export default App
// 组件通信
// 目标,把B的数据传入A
// 技术方案:
// 1.先把B中的数据通过子传父传给App
// 2.再把App接收到的SonB的数据 通过父传子 传给A
import React from "react"
function SonA (props) {
return (
<div>
<div>this is A</div>
<p>B组件传来的值---({props.num})</p>
</div>
)
}
function SonB (props) {
const bMsg = "这是来自于B组件的数据"
return (
<div>
<div>this is B</div>
<button onClick={() => { props.getMsg(bMsg) }}>点击按钮将B组件的数据传给A组件</button>
</div>
)
}
class App extends React.Component {
state = {
num: ""
}
// 声明一个传递给B组件的方法
getMsg = (msg) => {
console.log('msg',msg);
this.setState({
num : msg
})
}
render () {
return (<div>
<SonA num={this.state.num}></SonA>
<SonB getMsg={this.getMsg}></SonB>
</div>)
}
}
export default App
// 组件通信
// 爷孙组件跨组件通信
// app - a - c
// app - c
// 注意事项:上层组件和下层组件关系是相对的,只要存在就可以使用,通常我们会以app作为数据提供方
// 这里涉及的语法都是固定的,有两处,提供的位置value提供位置 获取的位置 {value=>{value}获取
// 步骤:
// 1.导入createContent方法并执行
import React, { createContext } from "react"
// 解构提供者和消费者
const { Provider, Consumer } = createContext()
function SonA (props) {
return (
<div>
<div>这是A组件</div>
<SonC></SonC>
</div>
)
}
function SonC (props) {
return (
<div>
<div>这是C组件</div>
{/* 3. 这里的value接收上层传来的数据 */}
<Consumer>
{value => <span>{value}</span>}
</Consumer>
</div>
)
}
class App extends React.Component {
state = {
message: "this is message"
}
render () {
return (
// 2. 使用包裹Provider根组件,value就是传递的数据
<Provider value={this.state.message}>
<div>
<SonA></SonA>
</div>
</Provider>
)
}
}
export default App
// children属性
import React from "react"
// 渲染列表
function ListItem ({ children }) {
// 这里可以直接解构出children属性,当children内容多时,会形成一个数组,需要那部分可以直接通过索引取得
return (
<div>
ListItem
{children[0]}
<button onClick={children[1]}>点击触发函数</button>
</div>
)
}
class App extends React.Component {
render () {
return (
<div>
<ListItem>
{/* 打开调试工具会发现在props里面多了个children属性,值就是组件内部的值
children的值可以为普通文本,普通标签元素,函数和JSX
*/}
<div>this is children</div>
{() => { console.log('12345') }}
</ListItem>
</div>
)
}
}
export default App
// props校验
// 实现步骤
// 1. 安装属性校验包:npm install prop-types
// 2. 导入prop-types 包
// 3. 使用 组件名.propTypes = {} 给组件添加校验规则
import React from "react"
// 里面有各种各样的内置校验规则
import propTypes from "prop-types"
function Test ({ list }) {
return (
<div>
<div>this is list</div>
{list.map(item => <p key={item}>{item}</p>)}
</div>
)
}
// 定义规则
Test.propTypes = {
list: propTypes.array.isRequired //限定Test组件的prop的list属性类型为array,并且为必传项
}
// 定义默认值(函数组件和类组件不一样)
// 函数组件
// 第一种方式(官方比较推荐的方式)
function List1 ({ pageSize = 10, pageSize2 }) {
return (
<div>
此处展示函数组件props第一种显示的默认值:{pageSize}
此处展示函数组件props第二种显示的默认值:{pageSize2}
</div>
)
}
// 第二种方式,设置pageSize2的默认值为20
List1.defaultProps = {
pageSize2: 20
}
// 类组件
// 第一种传参方式(比较推荐)
class List2 extends React.Component {
static defaultProps = {
pageSize1: 10
}
render () {
return (
<div>
此处展示类组件props第一种显示的默认值:{this.props.pageSize1}
{/* 这里有问题,把传参方式2注释掉第一种方式才能正常显示,如果同时存在只会显示方式2,我也不知道是什么原因 */}
此处展示类组件props第二种显示的默认值:{this.props.pageSize2}
</div>
)
}
}
// 第二种传参方式
List2.defaultProps = {
pageSize2: 30
}
class App extends React.Component {
render () {
return (
<div>
<Test list={[1, 2, 3]}></Test>
<List1></List1>
<List2></List2>
</div>
)
}
}
export default App
// 生命周期
//只有类组件才有生命周期,函数组件无生命周期
// 生命周期图示
// https://cdn.nlark.com/yuque/0/2022/png/274425/1654490729034-d2d80cce-7fab-4dd8-bcbc-29e33bdffb63.png?date=1694351792480
// 钩子函数 触发时机 作用
// constructor 创建组件时,最先执行,初始化的时候只执行一次 1. 初始化state 2. 创建 Ref 3. 使用 bind 解决 this 指向问题等
// render 每次组件渲染都会触发(例如按钮数字自增页面重新变化) 渲染UI(注意: 不能在里面调用setState() )
// componentDidMount 组件挂载(完成DOM渲染)后执行,初始化的时候执行一次 1. 发送网络请求 2.DOM操作
import React from "react"
class App extends React.Component {
constructor() {
super() //这个需要加,不然会报错
console.log('counstructor')
}
componentDidMount () {
// 在这个生命周期里面适合发送网络请求和对DOM操作
console.log('componentDidMount')
}
state = {
count: 0
}
clickHandler = () => {
this.setState({
count: this.state.count + 1
})
}
render () {
console.log('render')
return (
<div>
<button onClick={this.clickHandler}>点击自增加1,当前count为{this.state.count}</button>
</div>
)
}
}
export default App
// 生命周期
//只有类组件才有生命周期,函数组件无生命周期
// 生命周期图示
// https://cdn.nlark.com/yuque/0/2022/png/274425/1654490729034-d2d80cce-7fab-4dd8-bcbc-29e33bdffb63.png?date=1694351792480
// 钩子函数 触发时机 作用
// render 每次组件渲染都会触发 渲染UI(与 挂载阶段 是同一个render)
// componentDidUpdate 组件更新后(DOM渲染完毕) DOM操作,可以获取到更新后的DOM内容,不要直接调用setState
// componentWillUnmount 组件卸载(从页面中消失) 执行清理工作(比如:清理定时器等)
import React from "react"
// 演示组件卸载
class Test extends React.Component {
// 如果数据是组件的状态需要去影响视图,定义到state中
// 而如果我们需要的数据状态,不和视图绑定,定义成一个普通的实例属性就可以啦
// state中尽量保持简洁
timer = null
// 组件挂载开启定时器
componentDidMount () {
this.timer = setInterval(() => {
console.log('定时器开启')
}, 0)
}
componentWillUnmount () {
// 组件卸载时清理定时器
clearInterval(this.timer)
console.log('组件销毁了')
}
render () {
return (<div>Test</div>)
}
}
class App extends React.Component {
componentDidUpdate () {
console.log('页面更新啦')
}
state = {
count: 0,
flag: true
}
clickHandler = () => {
this.setState({
count: this.state.count + 1,
flag: !this.state.flag
})
}
render () {
console.log('render')
return (
<div>
{/* 通过一个数据状态的切换,让test组件销毁重建 */}
<button onClick={this.clickHandler}>点击自增加1,当前count为{this.state.count}</button>
{this.state.flag ? (<Test></Test>) : null}
</div>
)
}
}
export default App
// Hooks函数
// 快速使用
// useState
// 1.导入useState函数
// 2.执行这个函数并且传入初始值 必须在函数组件中
// 3.[数据,修改数据的方法]
// 4.使用数据 修改数据
// 状态的读取和修改
// const [count, setCount] = useState(0)
// 1.useState传过来的参数作为count的初始值
// 2.[count, setCount]这里的写法是一个解构赋值 useState的返回值是一个数组
// 名字可以自定义吗?? 当然可以自定义,保持语义化,第二个参数为set+count的首字母大写
// 这两个参数顺序可以换吗??? 当然不可以 第一个参数就是数据状态,第二个参数就是修改数据的方法
// 3.setCount函数 作用用来修改count 依旧保持不能修改原值还是生成一个新值替换原值
// setCount(基于原值计算得到的新值,还是不能使用++ --)
// 4.count和setCount是一对 是绑在一起的 setCount只能用来修改对应的count值
// 组件的更新过程
// 当调用setCount的时候,更新过程
// 首次渲染
// 首次被渲染的时候 组件内部的代码会被执行一次
// 其中useState也会跟着执行 这里重点注意
// 更新渲染(setCount都会更新)
// 1.app组件会再次渲染 这个函数会再次执行
// 2.useState再次执行 得到的新的count值不是0,而是修改之后的1 模板会用新值渲染
// 重点一句话:useState初始值只在首次渲染生效,后续只要调用setCoun整个app代码都会执行
// 此时count每次拿到的都是最新值
// useState的使用规则
// 1. useState 函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态
// 2. useState 注意事项
// a. 只能出现在函数组件或者其他hook函数中
// b. 不能嵌套在if/for/其它函数中(react按照hooks的调用顺序识别每一个hook) 写到最外层函数中
// 3. 可以通过开发者工具查看hooks状态
import { useState } from 'react'
function App () {
// count:数据状态
// setCount:修改count的函数(专有函数)
const [count, setCount] = useState(0)
return (
<div>
<button onClick={() => setCount(count + 1)}>
{count}
</button>
</div>
)
}
export default App
// Hooks函数
// 什么是副作用
// 副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
// 常见的副作用
// 1. 数据请求 ajax发送
// 2. 手动修改dom
// 3. localstorage操作
// useEffect函数的作用就是为react函数组件提供副作用处理的!
// 在修改数据之后将count值放到页面标题中
// 1.导入useEffect函数
// 2.在函数组件中执行 传入回调 并且定义副作用
// 当我们修改状态更新组件时,副作用也会不断执行
// 依赖项控制副作用的执行时机
// 1.默认状态(无依赖项)组件初始化的时候先执行一次 等到每次数据修改组件更新再次执行
// 2.参数二添加空数组,只会在组件初始化时执行一次,后续不会执行
// 3.添加特定依赖项,组件初始化执行一次,参数二数组内部添加指定数据,代表只有指定数据修改才会执行,数组内部没有的数据不会再次执行(依赖的特定项发生变化才会再次执行)
// 4.注意事项:只要在useEffect回调函数中用到的数据状态就应该出现在依赖项数组中声明 否则可能有bug
// 某种意义上 hook的出现 就是想不用生命周期概念也可以写业务代码
import { useEffect, useState } from 'react'
function App () {
const [count, setCount] = useState(0)
const [name, setName] = useState('')
useEffect(() => {
console.log('副作用执行了')
// 定义副作用
document.title = count
console.log('name', name)
}, [count, name])
return (
<div>
<button onClick={() => setCount(count + 1)}>
{count}
</button>
<button onClick={() => setName("cp")}>
{name}点击
</button>
</div>
)
}
export default App
// Hooks函数
// 清理副作用
import { useEffect, useState } from 'react'
function Text () {
useEffect(() => {
let timer = setInterval(() => {
console.log('定时器执行了')
}, 1000)
return () => {
// 这里写清理副作用的代码(当组件销毁时会清理副作用)
clearInterval(timer)
}
}, [])
return (
<div>
this is Text
</div>
)
}
function App () {
const [flag, setFlag] = useState(true)
return (
<div>
{flag ? (<Text></Text>) : null}
<button onClick={() => setFlag(!flag)}>swith</button>
</div>
)
}
export default App
// Hooks函数
import { func } from "prop-types"
import { useEffect } from "react"
// 发送网络请求
// 类组件 如何发送网络请求
// 生命周期钩子 componentDidMount
// 执行时机?
// 在初始化的时候dom渲染完毕只执行一次
// useEffect
// 1.不加依赖项 -初始化 +重新渲染
// 2.第二个参数加[],初始化执行一次
// 3.加特定依赖项[count,name] - 首次执行+任一变化执行
function App () {
useEffect(() => {
function data () {
fetch("https://api.vvhan.com/api/weather?ip=180.149.130.16").then((response) => response.json()).then((data) => console.log(data))
}
data()
})
return (
<div>
</div>
)
}
export default App
// Hooks函数
import React, { useEffect, useRef } from "react"
// 组件实例(类组件)
// dom对象 标签
class Test extends React.Component {
state={
name:"test name"
}
getName=()=>{
return "this is child Test"
}
render () {
return (<div>我是类组件</div>)
}
}
function App () {
const testRef = useRef(null)
const h1Ref = useRef(null)
useEffect(() => {
console.log('testRef', testRef.current) //组件实例对象
console.log('testRef', testRef.current.state.name) //组件实例对象里面的数据
console.log('testRef', testRef.current.getName()) //组件实例对象里面的方法
console.log('h1Ref', h1Ref.current) //dom对象
}, [])
return (
<div>
<Test ref={testRef}></Test>
<div ref={h1Ref}>this is div</div>
</div>
)
}
export default App
// Hooks函数
import React, { createContext, useContext, useState } from "react"
const Context = createContext()
function ComA () {
// 这里可以接收上层传来的value的数据
const count = useContext(Context)
return (
<div>this is ComA<br></br>
顶层传来的count数据为---{count}
<ComC></ComC>
</div>
)
}
function ComC () {
// 可以嵌套
const count = useContext(Context)
return (
<div>this is ComC<br></br>
顶层传来的count数据为---{count}
</div>
)
}
function App () {
const [count, setCount] = useState(0)
return (
// 这里提供数据给下层使用
//下面这个标签也可以直接包裹index.js里面的 ,相当于在顶层组件传递数据了
<Context.Provider value={count}>
<div>
<ComA></ComA>
<button onClick={() => setCount(count + 1)}>点击修改count数据</button>
</div>
</Context.Provider>
)
}
export default App