一、网页中添加react
<!-- 引入js文件 -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<body>
<div id="like_button_container"></div>
</body>
<script>
// 渲染 react 元素
// 参数:(元素名称,元素属性,元素的子节点)
let title = React.createElement('h1', null, 'hellow react');
// 参数:(渲染的react元素,挂载点)
ReactDOM.render(title, document.querySelector('#like_button_container'))
</script>
二、react目录介绍
src/App.js
src/index.js
import React from 'react' // 框架核心包
import ReactDom from 'react-dom' // 专门做渲染渲染相关的包
三、脚手架的简单使用(App.js)
import './App.css';
/**
* 1.识别常规变量
* 2.原生js方法调用
* 3.三元运算符
*/
const name = '张三'
const getAge = () => {
return 18
}
const flag = true
function App() {
return (
<div className="App">
{ name }
{ getAge() }
{ flag ? '真棒' : '垃圾' }
</div>
);
}
export default App;
四、react渲染列表
import './App.css';
/**
* react 如何完成列表渲染?
* 技术方案:map
* 注意事项:需要key值,在内部使用,不会出现在真实的dom节点中
*/
let songs = [
{ id: 1, name: '痴心绝对' },
{ id: 2, name: '像我这样的人' },
{ id: 3, name: '南山南' }
]
function App() {
return (
<div className="App">
<ul>
{songs.map(song => <li key={song.id}>{song.name}</li>)}
</ul>
</div>
);
}
export default App;
五、条件渲染
import './App.css';
/**
* react 条件渲染
* 技术方案:三元表达式(常用) 逻辑&&运算
*/
// 1.三元表达式
const flag = true
function App() {
return (
<div className="App">
{flag ? <span>hello</span> : <span>world</span>}
<div>
{/* 逻辑&&运算 */}
{true && <span>this is span</span>}
</div>
</div>
);
}
export default App;
六、复杂的条件渲染
import './App.css';
/**
* 有一个状态 1 2 3
* 1--> h1
* 2--> h2
* 3--> h3
*
* 原则:模板中的逻辑尽量保持精简
* 复杂的多分支逻辑 收敛为一个函数 通过一个专门的函数来写分值逻辑 模板中只负责调用
*/
const getHtag = (type) => {
switch (type) {
case 1:
return <h1>this is h1</h1>
case 2:
return <h2>this is h2</h2>
case 3:
return <h3>this is h3</h3>
}
}
function App() {
return (
<div className="App">
{getHtag(1)}
{getHtag(2)}
{getHtag(3)}
</div>
);
}
export default App;
七、jsx的样式处理
1.jsx行内样式和类名样式基础使用
/**
* jsx 的样式控制
* 1.行内样式
* 在元素身上绑定一个style样式就行
*
* 2.类名样式
* 在元素身上绑定一个className属性即可
*/
const style = {
color: 'blue',
fontSize: '30px'
}
// 导入写好的css样式
import './app.css'
function App() {
return (
<div className="App">
<span style={style}>this is span</span>
{/* 导入的css样式里有active这个类名 */}
<span className='active'>测试类名样式</span>
</div>
);
}
export default App;
2.函数组件的创建和渲染
// 函数组件的创建和渲染
function Hello(){
return <div>hello</div>
}
function App() {
return (
<div className="App">
<div>
{/*渲染hello组件*/}
<Hello></Hello>
</div>
</div>
);
}
export default App;
3.类组件的创建和渲染
import "./App.css";
import React from 'react'
/**
* 类组件的创建和渲染
*/
// 创建
class HelloComponent extends React.Component{
render(){
return <div>this is class Component</div>
}
}
function App() {
return (
<div className="App">
{/* 渲染类组件*/}
<HelloComponent></HelloComponent>
</div>
);
}
export default App;
八、事件绑定
1.绑定事件
import React from 'react'
// 函数组件的事件绑定
function Hello() {
const clickHandle = () => {
console.log('函数组件中的事件被触发了');
}
return <button onClick={clickHandle}>函数组件</button>
}
// 类组件的事件绑定
class HelloComponent extends React.Component {
clickHandler = () =>{
console.log('类组件中的事件被触发了');
}
render() {
return <button onClick={this.clickHandler}>类组件</button>
}
}
function App() {
return (
<div className="App">
{/*渲染函数组件*/}
<Hello></Hello>
{/* 渲染类组件*/}
<div>
<HelloComponent></HelloComponent>
</div>
</div>
);
}
export default App;
2.获取事件对象
import React from 'react'
// 函数组件的事件绑定
function Hello() {
const clickHandle = (e,msg) => {
console.log('函数组件中的事件被触发了',e,msg);
}
return <button onClick={(e) => clickHandle(e,'this is msg')}>函数组件</button>
}
function App() {
return (
<div className="App">
{/*渲染函数组件*/}
<Hello></Hello>
</div>
);
}
export default App;
九、组件状态
import React from 'react'
// 组件状态,类组件作为演示
class TestComponent extends React.Component {
// 1.定义组件状态
state = {
// 这里可以定义各种属性,全都是当前组件的状态
name: '张三'
}
// 事件回调函数
changeName = () => {
// 不可以直接赋值,必须通过一个方法 setState()
this.setState({name:'四哥'})
}
render() {
return (
<div>
this is TestComponent
<p>当前name为{this.state.name}</p>
<button onClick={this.changeName}>修改</button>
</div>
)
}
}
function App() {
return (
<div className="App">
<TestComponent></TestComponent>
</div>
);
}
export default App;
十、react状态不可变
import React from 'react'
// 组件状态,类组件作为演示
class Counter extends React.Component {
// 定义组件状态
state = {
count: 0,
list: [1, 2, 3],
person: {
name: 'jack',
age: 20
}
}
// 事件回调函数
changeCount = () => {
// 数组修改
this.setState({
list: [...this.state.list, 4, 5]
})
// 对象修改
this.setState({
person: {
...this.state.person,
name: 'rose'
}
})
// 删除数组元素
this.setState({
list: this.state.list.filter(item => {
return item !== 2
})
})
}
render() {
console.log(this);
return (
<div>
<ul>
{this.state.list.map((item) => <li key={item}> {item}</li>)}
</ul>
<div>{this.state.person.name}</div>
<button onClick={this.changeCount}>change</button>
</div>
)
}
}
function App() {
return (
<div className="App">
<Counter></Counter>
</div>
);
}
export default App;
十一、表单处理
1.受控表单组件
import React from 'react'
// input组件的状态被react控制
class Counter extends React.Component {
state = {
// 1.用来控制input value的react组件自己的状态
message: 'this is a message'
}
// 回调
inputChange = (e) =>{
console.log('change事件出发了',e);
// 拿到输入框最新的数据,交给state中的message
this.setState({
message:e.target.value
})
}
render() {
return (
<div>
{/*2.给value绑定react的state*/}
{/*3.给input框绑定change事件 为了拿到当前输入框中的数据*/}
<input type="text" value={this.state.message} onChange={this.inputChange}/>
</div>
);
}
}
function App() {
return (
<div className="App">
<Counter></Counter>
</div>
);
}
export default App;
2.非受控表单组件
import React,{createRef} from 'react'
class Counter extends React.Component {
msgRef = createRef()
getValue = () =>{
// 通过msgRef获取input value值
console.log(this.msgRef.current.value)
}
render() {
return (
<div>
{/*2.给value绑定react的state*/}
{/*3.给input框绑定change事件 为了拿到当前输入框中的数据*/}
<input type="text" ref={this.msgRef}/>
<button onClick={this.getValue}>按钮</button>
</div>
);
}
}
function App() {
return (
<div className="App">
<Counter></Counter>
</div>
);
}
export default App;
十二、组件通信
1.父传子
import React from 'react'
// App父组件 Son子组件
// 函数式Son
function Son1(props){
return(
<div>
<p>我是函数子组件</p>
{/* 函数组件通过props参数接收父组件传递的数据*/}
<p>父组件传递的数据:{props.msg}</p>
</div>
)
}
// 类组件的Son
class Son2 extends React.Component{
render(){
console.log(this)
return(
<div>
<p>我是类子组件</p>
{/* 类组件必须通过哦this关键词获取,这里的props是固定的 */}
<p>父组件传递的数据:{this.props.msg}</p>
</div>
)
}
}
// 父组件
class App extends React.Component{
// 准备数据
state = {
message:'this is message'
}
render(){
return(
<div>
<Son1 msg={this.state.message}></Son1>
<hr/>
<Son2 msg={this.state.message}></Son2>
</div>
)
}
}
export default App;
2.子传父
import React from 'react'
/**
react里子组件不能直接操作父组件的数据。
所以要从父组件传递一个方法给子组件,
子组件获取到该方法后,把子数据传入该方法,
父组件才能获取到子数据
*/
// 函数式Son
function Son1(props) {
console.log(props)
const {getSonMsg} = props
// const send = () =>{
// getSonMsg('这是子组件的数据')
// }
return (
<div>
<p>this is son</p>
<div>
<button onClick={() => getSonMsg('这是子组件的数据')}>按钮</button>
</div>
</div>
)
}
// 父组件
class App extends React.Component {
// 准备数据
state = {
list: [1, 2, 3]
}
// 准备一个函数,传递给子组件
getSonMsg = (sonMsg) => {
console.log(sonMsg)
}
render() {
return (
<div>
<Son1 getSonMsg={this.getSonMsg}></Son1>
</div>
)
}
}
export default App;
3.兄弟组件通信
import React from 'react'
/**
* 目标:B组件的数据传给A
* 技术方案:
* 1.先把B中的数据传给App
* 2.再把App接收到的SonB中的数据 通过父传子 传给A
* */
function SonA(props) {
return (
<div>
<p>this is SonA</p>
<p>b组件传递过来的数据是:{props.msg}</p>
</div>
)
}
function SonB({getMsg}) {
const bMsg = 'B组件数据'
return (
<div>
<p>this is SonB</p>
<button onClick={() => {
getMsg(bMsg)
}}>传递
</button>
</div>
)
}
// 父组件
class App extends React.Component {
state = {
msg:''
}
// 声明一个传给b组件的方法
getMsg = (msg) => {
this.setState({
msg
})
}
render() {
return (
<div>
<SonA msg={this.state.msg}></SonA>
<hr/>
<SonB getMsg={this.getMsg}></SonB>
</div>
)
}
}
export default App;
4.跨组件通信context
import React, {createContext} from 'react'
/**
* App --> A --> C
* 目标:App --> C
*
* 1.导入 createContext 方法,并执行
* 2.使用 Provider 包裹根组件,并传入 value 值
* 3.通过 Consumer 使用数据
* */
// 1.
const {Provider, Consumer} = createContext()
function ComA() {
console.log(Provider, Consumer)
return (
<div>
<p>this is comA</p>
<ComC></ComC>
</div>
)
}
function ComC() {
return (
// 3.
<div>
C组件:
<Consumer>
{value => <span>{value}</span>}
</Consumer>
</div>
)
}
// 父组件
class App extends React.Component {
state = {
message: 'this is a message'
}
render() {
return (
// 2.
<Provider value={this.state.message}>
<ComA></ComA>
</Provider>
)
}
}
export default App;
5、练习
import React from 'react'
// 渲染列表
function ListItem({item,delItem}) {
return (
<div>
<h3>{item.name}</h3>
<p>{item.price}</p>
<p>{item.info}</p>
<button onClick={() => delItem(item.id)}>删除</button>
<hr/>
</div>
)
}
// 父组件
class App extends React.Component {
state = {
list: [
{id: 1, name: '超级好吃的棒棒糖', price: 18.8, info: '开业大酬宾'},
{id: 2, name: '超级好吃的大鸡腿', price: 28.8, info: '开业大酬宾'},
{id: 3, name: '超级好吃的三明治', price: 38.8, info: '开业大酬宾'}
]
}
// 定义一个删除事件,传递给子组件
delItem = (id) =>{
this.setState({
list:this.state.list.filter(item => item.id !== id)
})
}
render() {
return (
<div>
{this.state.list.map(item => (
<div key={item.id}>
<ListItem item={item} delItem={this.delItem}></ListItem>
</div>
))}
</div>
)
}
}
export default App;
十三、react进阶
1.
2.props校验
// 安装包 npm i prop-types
import React from 'react'
// 里面有各种各样的内置校验规则
import propTypes from "prop-types";
function Test({list}) {
console.log(propTypes)
return (
<div>
{list.map(item => <p key={item}>{item}</p>)}
</div>
)
}
Test.propTypes = {
// 定义各种规则
list:propTypes.array
}
class App extends React.Component {
render() {
return (
<div>
<Test list={[1,2,3,4,5,6]}></Test>
</div>
)
}
}
export default App;
3.组件生命周期
constructor --> 创建组件是最先执行,初始化是只能执行一次
render --> 每次组件渲染都会触发-->渲染UI
componentDidMount --> 组件挂载(完成dom渲染)后执行,初始化的时候执行一次
componentDidUpdate --> 组件更新后(dom渲染完毕)--> dom操作,可以获取到更新后的dom内容,不要直接调用setState
import React, {createContext} from 'react'
class Test extends React.Component {
// 如果数据是组件的状态需要去影响视图,定义到state中
// 如果我们需要的数据状态不和视图绑定,定义成一个普通的实例属性就可以了
// state中尽量保持精简
timer = null
componentDidMount() {
this.timer = setInterval(()=>{
console.log('定时器开启了')
},1000)
}
componentWillUnmount() {
console.log('componentWillUnmount触发了')
// 清理定时器
clearInterval(this.timer)
}
render() {
return (
<div>test</div>
)
}
}
class App extends React.Component {
constructor() {
super()
console.log('constructor')
}
state = {
count: 0,
flag: true
}
componentDidMount() {
console.log('componentDidMount')
}
componentDidUpdate() {
console.log('componentDidUpdate')
}
render() {
console.log('render触发了')
return (
<div>
<p>{this.state.count}</p>
<p>
{/* 通过一个数据状态切换,让Test数据进行销毁重建,就会发生卸载 */}
{this.state.flag ? <Test/> : ''}
</p>
<button onClick={() => this.setState({count: this.state.count + 1})}>点击增加</button>
<button onClick={() => this.setState({flag: !this.state.flag})}>修改flag状态</button>
</div>
)
}
}
export default App;