零零碎碎React
有状态组件和无状态组件组件的设计思路React合成事件组件名称大小写双向数据绑定父子组件传值模拟插槽Slot异步加载组件
有状态组件和无状态组件
React中组件根据自身状态可分为有状态组件和无状态组件。有状态组件内部主要涉及繁杂的业务逻辑,无状态组件接受一个props参数,主要用来渲染数据。
有状态组件
// 通过this.setState改变状态
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
title: "有状态组件"
}
}
}
无状态组件
function App(props) {
return <h1>{props.title}</h1>
}
render(<App title="无状态组件" />, document.querySelector('#root'))
组件的设计思路
定义少数有状态组件管理整个应用的状态变化,有状态组件将状态通过props传递给其余无状态组件,无状态组件接收props完成页面绝大部分UI的渲染。
React合成事件
在 React 底层,主要对合成事件做了两件事:事件委派和自动绑定。
事件委派
React 它并不会把事件处理函数直接绑定到真实的节点上,而是把所有事件绑定到结构的最外层,使用一个统一的事件监听器。
这个事件监听器上维持了一个映射来保存所有组件内部的事件监听和处理函数。
当组件挂载或卸载时,只是在这个统一的事件监听器上插入或删除一些对象.
当事件发生时,首先被这个统一的事件监听器处理,然后在映射里找到真正的事件处理函数并调用。
自动绑定
在 React 组件中,每个方法的上下文都会指向该组件的实例,即自动绑定 this 为当前组件。
React 会对这种引用进行缓存,以达到 CPU 和内存的最优化。
在使用 ES6 class 或者纯函数时,需要手动实现 this 的绑定。
组件名称大小写
在react的jsx语法中,大写的标签名会被识别为组件,小写的被识别为原生html标签,两者对单双标签都支持。<div/>,这样也是可以的,等同于<div></div>
双向数据绑定
如果你学过vue或者angular,应该熟悉什么是双向数据绑定。输入框值改变,状态变。状态变,输入框的值也同步变化。在React中需要手动实现,此时的输入框是受控输入框,其value和useState的状态val绑定,且监听onChange事件,将输入框的值设置为状态值,从而实现双向数据绑定。
import React, { useState } from 'react'
import { render } from 'react-dom'
function App() {
const [val, setVal] = useState("hello")
return (
<div>
<input value={val} onChange={(e)=>setVal(e.target.value)} />
<p>{val}</p>
</div>
)
}
render(<App />, document.querySelector('#root'))

父子组件传值
React中是单向数据流,这也就意味着是父组件到子组件传值。大部分都是情况都是如此,但有时我们也需要子组件给父组件传值。父组件定义一个方法,传递给子组件,子组件再去调用即可。
父-->子
import React from 'react'
import { render } from 'react-dom'
function App() {
return <Child name="冷月心" />
}
function Child({ name }) {
return name
}
render(<App />, document.querySelector('#root'))
子-->父
import React from 'react'
import { render } from 'react-dom'
function App() {
const getNameFromChild = name => name
return <Child getNameFromChild={getNameFromChild} />
}
function Child({ getNameFromChild }) {
return getNameFromChild("冷月心")
}
render(<App />, document.querySelector('#root'))
模拟插槽Slot
vue里边是有插槽的,可以直接塞东西进去。React中props传递组件进去可以模拟类似效果
import React from 'react'
import { render } from 'react-dom'
function App({ Header, Main, Footer }) {
return <div><Header /><Main /><Footer /></div>
}
const Header = () => <p>Header</p>
const Main = () => <p>Main</p>
const Footer = () => <p>Footer</p>
render(<App
Header={Header}
Main={Main}
Footer={Footer} />,
document.querySelector('#demo')
)

异步加载组件
//A.js
import React from 'react';
export default function(){
return <p>A</p>
}
//B.js
import React from 'react';
export default function(){
return <p>B</p>
}
import React ,{Suspense}from 'react';
import { render } from 'react-dom';
const A = React.lazy(() => import('./A'));
const B = React.lazy(() => import('./B'));
const Loading=()=>{
return <div>Loading...</div>
}
function App() {
return (
<div>
<Suspense fallback={<Loading/>}>
<A/>
<B/>
</Suspense>
</div>
);
}
render(<App/>,document.getElementById("root"))





