您的位置:首页 > 文旅 > 旅游 > 东莞制作公司网站的公司_英文网站建设方案详细方案_百度seo关键词排名 s_百度怎么推广自己的作品

东莞制作公司网站的公司_英文网站建设方案详细方案_百度seo关键词排名 s_百度怎么推广自己的作品

2024/12/25 22:39:16 来源:https://blog.csdn.net/weixin_45179978/article/details/144670721  浏览:    关键词:东莞制作公司网站的公司_英文网站建设方案详细方案_百度seo关键词排名 s_百度怎么推广自己的作品
东莞制作公司网站的公司_英文网站建设方案详细方案_百度seo关键词排名 s_百度怎么推广自己的作品

【React 基础及高级用法】

  • React 基础
    • React 浅析
      • 传统的方式下,前端是如何构建用户界面的?
      • 按照这种逻辑,可以写一个 createElement
      • 回头看一下 react
      • React 到底是什么?
      • 前端在干什么?
      • React 的灵活性
    • 创建 react 工程
    • React 的基础能力
      • 子父组件
    • State 和 Props
        • 类组件
        • 函数组件
        • 子父组件传值的 props
    • 条件与列表
  • React 高级
    • 一些 use API
        • useState
        • useEffect
        • useLayoutEffect
        • useInsertionEffect
        • useEffect 如何模拟生命周期
    • Ref
        • Ref 的创建
        • 类组件 - createRef
        • 函数式组件 - useRef
        • Ref 的常见使用方式
    • Context
        • 类组件—context
        • 函数组件—useContext
    • Hoc
    • 优化相关 - useCallBack, useMemo, React.Memo
    • React 的更新逻辑

React 基础

React 浅析

传统的方式下,前端是如何构建用户界面的?

在这里插入图片描述
• JS:叫做 浏览器脚本
○ 本质上我就是在前端的 html 页面上去操作 DOM 的。
○ JS 是一种可以操作 DOM,对 DOM 进行增删改查的语言。

按照这种逻辑,可以写一个 createElement


<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- 有一段 dom --><div id="root"><div class="title">你好</div><button>click me</button></div><!-- JavaScript 可以 操作 DOM,所以对于我这段 html, 我是不是可以只用 JavaScript 来实现 --></body>
<style>.title {font-size: 24px;font-weight: 700;}
</style>
<script>const div = document.createElement('div');const body = document.getElementsByTagName('body')[0];div.innerText = '你好';div.setAttribute('id', 'app');div.setAttribute('class', 'title')body.appendChild(div);document.getElementById('app').addEventListener('click', () => {console.log('hello luyi')});/**这样的话,我们尝试实现一个函数假如 我要书写一段这样的 HTML (DOM tree)<div id="root"><div class="title">你好</div><button>click me</button></div>// 理论上,我就可以用一段 createElement 的嵌套来表达。createElement('div', { id: 'root' }, createElement('div', {'class': 'title','textContext': '你好'}), createElement('button', {'style': 'background-color: blue','textContext': 'click me','onclick': '() => {}'}))*/function createElement(type, params, ...children) {// 1. 构建元素let ele;if(type.toLowerCase() === 'div') {ele = document.createElement('div')};if(type.toLowerCase() === 'button') {ele = document.createElement('button')};if(type.toLowerCase() === 'script') {// ....};// 2. 设置属性for(let key in params) {if(key === 'textContent') {ele[key] = params[key];} else if( ['onClick', 'onMouseDown'].includes(key) ) {// ... 事件的处理const method = key.toLowerCase().split('on')[1];ele.addEventListener(method, params[key]);} else {ele.setAttribute(key, params[key])}};// 3. 处理递归逻辑children.forEach(child => ele.appendChild(child));return ele;};const divRoot = createElement('div', {id: 'root'}, createElement('div', {class: 'title',textContent: '你好'}), createElement('button', {style: 'background-color: blue',textContent: 'click me',onClick: () => { console.log('hello luyi') }}));body.appendChild(divRoot)// *******  react babel 编译结果function App() {return React.createElement("div", {id: "root"}, React.createElement("div", {"class": "title"}, "\u4F60\u597D"), React.createElement("button", null, "click me"));}</script>
</html>

在这里插入图片描述

回头看一下 react

• 为什么 JSX 可以返回 HTML?
• 为什么说 React 是一个运行时框架?和 vue 对比 , vue 是一个编译型框架?
○ 编译是我去转化代码,AST,编译完了,我才能丢到引擎(V8)里去执行。

tips:
我们学习框架,一定要立体,要从多个维度去认识。
深度,不止是源码,还有发展历程和设计思想。

Babel ->
○ @babel/preset-react
○ @babel/preset-typescipt
○ @babel/preset-env

React 到底是什么?

function App() {return <div><div className="title">你好</div><button>click me</button><Submodule name={'xxx'} /></div>
};function Submodule ({ name }) {return <div>submodule--{name}</div>
}在 函数的情况下
- 支持使用 hooks 来表达,函数组件的状态和更新方式;
- jsx 足够的灵活,能够提供更好的动态化能力;class Submodule {render() {return <div>submodule</div>}
}在 类组件的情况下
- 支持生命周期,和状态表达,让我们更新界面。

前端在干什么?

在这里插入图片描述

React 的灵活性

template><div><div v-for="item of list" key="item">{{ item.name }}</div></div>
</template><div>{[...list].map(item => ({...item})).map(item => <div>{item.name}</div>)}
</div><div>{(() => {for(item of list) {}return results})()}
</div>// React 是不知道当前的改变,到底会有什么副作用的...this.setState -> callback 
useEffect
unbatchedUpdate

创建 react 工程

npx create-react-app demo-app
npx create-react-app demo-app-ts --template typescript

React 的基础能力

子父组件

在这里插入图片描述
• 从 UI 的视角看
○ Class 组件渲染的是 render 函数中返回的内容;
○ Function 组件渲染的是,函数本身返回的内容;

State 和 Props

在 react 中,有一个概念叫做 state
• 如果我有一个数据,并且这个数据改变时,我需要触发界面更新。
○ 我要把这个数据定义成 state
○ 我要使用特殊的方法,去更新这个 state

类组件

setState 的方法。
类组件上,要用 setState
• State 的值,互相不影响
• setState 第二个参数是 一个 callback, 能拿到最新的 state 的值

import React, { Component } from 'react'const SubModule = () => <div>submodule</div>export default class ClassCom extends Component {constructor(props) {super(props);this.state = {number: 0,msg: 'hello luyi'}this.title = '类组件: state 的用法'}handleClick = (type) => {this.setState({number: this.state.number + (type === 'plus' ? 1 : -1)})};handleChange = (e) => {this.setState({msg: e.target.value})}handleAddFn = () => {this.setState({number: this.state.number + 1})}handleMinusFn = function() {this.setState({number: this.state.number - 1})}// 生命周期render() {const { number, msg } = this.state;return (<div><h2>{this.title}</h2><div>this is the number: {number}</div>{/* bind, call, apply */}<button onClick={this.handleClick.bind(this, 'plus')}>+</button><button onClick={() => this.handleClick('minus')}>-</button>{/* this 绑定的问题 */}<button onClick={this.handleAddFn}>+</button><button onClick={this.handleMinusFn.bind(this)}>-</button>{/* 受控组件的问题 */}<input value={msg} onChange={this.handleChange} /><input /><hr/><SubModule /></div>)}
}
函数组件

useState

[state, dispatch] = useState(initState);

• State 作为组件的状态,提供给UI 渲染视图
• Dispatch, 用户修改state 的方法,同时触发更新
○ Dispatch 的参数可以是函数,可以不是,如果是函数,就更新为函数执行的结果,如果不是,直接更新为值;
○ initState :初始值
可以是函数,可以不是,如果是函数,就更新为函数执行的结果,如果不是,直接是值;

import React, { useState } from 'react'export default function FunCom( {name }) {const title = '函数组件: state 的用法';const [number, setNumber ] = useState(0);const [msg, setMsg] = useState('hello ');const handleClick = (type) => {setNumber(number + (type === "plus"?1:-1))}const handleChange = (e) => {setMsg(e.target.value)}return (<div><h2>{title}</h2> <div>{number}</div><input value={msg} onChange={handleChange} /><button onClick={() => handleClick('plus')}>+</button><button onClick={handleClick.bind(null, 'minus')}>-</button></div>)
}
子父组件传值的 props

传值: 父到子
传函数: 子到父

条件与列表

import React, { useState } from 'react'const Hide = () => <div>to title</div>const Title = ({title}) => title.length ? <h3>{title}</h3> : <Hide />export default function Other() {const list = ['luyi', 'yunyin', 'xianzao'];const [show, setShow] = useState(false);return (<div><h2>条件与列表</h2><Title title={show? "数据管理": ''} /><button onClick={() => setShow(!show)}>{show?"setHide":"setShow"}</button><ul>{list.map(item => <li key={item}>{item}</li>)}</ul><ol>{(() => {let res = [];for(let item of list) {res.push(<li key={item}>{item}</li>)}return res})()}</ol></div>)
}

React 高级

在这里插入图片描述

一些 use API

useState
useEffect

useEffect(() => destory, deps)

  • Callback: () => destory,是第一个参数,是一个 callback 函数
    ○ Destory:作为这个 callback 的返回值,会在callback 执行之前调用,用于清除上一次 callback 的副作用;
    ○ deps:第二个参数,是一个数组,数组中的值发生变化的话,会执行这个 callback 返回的 destory,然后再执行这个 callback 函数。
useLayoutEffect
  • 同步执行
  • useLayoutEffect 是在 DOM 更新之后,浏览器绘制之前执行的,可以方便的修改DOM
  • 如何选择:如果修改DOM,就用 useLayoutEffect,否则就用 useEffect
useInsertionEffect

是在 DOM 更新之前执行的,那么 对于 css-in-js 的场景,可以解决性能问题。

import React, { useEffect, useInsertionEffect, useState } from 'react'const getBookList = () => new Promise((resolve, reject) => {setTimeout(() => {resolve(['React 开发实战', 'Vue 原理解析', 'Webpack 从入门到精通']);}, 1000)
});const useBookList = () => {const [list, setList] = useState([]);useAsyncEffect(async () => {const _list = await getBookList();setList(_list);})return [list, setList];
};const useAsyncEffect = (cb) => {async function fetchData() {await cb();}fetchData();
}export default function Effect() {const [num, setNum] = useState(0);const [list, setList] = useState([]);useEffect(() => {setNum(list.length);},[list]);// 相当于是 mounted, componentDidMount 生命周期useEffect(() => {getBookList().then(res => {setList(res);})},[])useInsertionEffect(() => {const style = document.createElement("style");style.innerHTML = `.xxx {color: blue}`;document.head.appendChild(style);})return (<div><h3>the length is {num}</h3><ul>{list.map((item) => <li key={item}>{item}</li>)}</ul><button onClick={() => setList(['1','2','3'])}>setList</button></div>)
}
useEffect 如何模拟生命周期
import React, { useEffect, useState } from 'react'export default function LifeCycleMock(props) {const [state, dispatch] = useState(() => {console.log('getDerivedStateFromProps')return ''});useEffect(() => {console.log('componentDidMount');// 数据请求new Promise((resolve) => {setTimeout(() => {resolve('luyi')}, 300)}).then(res => {dispatch(res);});return () => {// 做一些监听器的销毁console.log('componentWillUnmount')};// deps 没有任何依赖,也就意味着,我只在初始化的时候,执行一次,destory 函数,只在销毁的时候执行一次}, []);useEffect(() => {console.log('componentDidUpdate')});useEffect(() => {console.log('componentWillReceiveProps');// 外面会传过来一个数据,同时我内部会想要自己可以处理}, [props]);return (<div>LifeCycleMock</div>)
}

Ref

Ref 的创建
类组件 - createRef

import React, { Component, createRef } from 'react';export default class ClassRef extends Component {constructor(props) {super(props);// 用来拿到某一个元素,组件的“句柄”/“实例”this.eleRef = createRef();this.inputRef = createRef();}handleFocus = () => {this.inputRef.current.focus()}handleClick = () => {console.log(this.eleRef.current)}render() {return (<div> <h3>Class Ref</h3><div id='usingRef' ref={this.eleRef} >eleRef</div><input ref={this.inputRef} /><button onClick={this.handleFocus}>focus</button><button onClick={this.handleClick}>click</button></div>);}
}
函数式组件 - useRef

import React, { useRef } from 'react'export default function FuncRef() {const inputRef = useRef(null);const eleRef = useRef(null);const handleClick = () => {inputRef.current.focus()}return (<div><h3>function Ref</h3><input ref={inputRef} /><button onClick={handleClick}>focus</button></div>)
}
Ref 的常见使用方式
  • 解决闭包陷阱问题;
  • 组件封装;
    在这里插入图片描述
    Visible 是谁的属性
    • 是弹窗的属性
    • 提供一种能力,让外面可以调用我的方法。
    • forwardRef, 本质是处理子父组件之间的 ref 传递。

import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'export default function VisibleApi() {const modalRef = useRef(null);const inputRef = useRef(null);return (<div><button onClick={() => modalRef.current.setVisible(true)}  >显示</button><button onClick={() => inputRef.current.focus()}  >focus</button><FancyModal ref={modalRef} /><FancyInput ref={inputRef} /></div>)
}const Modal = (props, ref) => {const [vis, setVis] = useState(true);const setVisible = (val) => setVis(val);const getData = () => "hello"useImperativeHandle(ref, () => ({setVisible,getData}))return <divstyle={{ display: vis?'block':'none', position:'relative', height: '200px',background: '#ffeedd' }}><button style={{ position: 'absolute', right: '10px', top: '10px'}} onClick={() => setVis(false)}>close</button><div>我是一个模拟弹窗</div></div>
}const Input = (props, ref) => {return <input ref={ref} />
}const FancyModal = forwardRef(Modal);const FancyInput = forwardRef(Input);

Context

类组件—context
函数组件—useContext

import React, { createContext, useContext } from 'react'// 组件使用一个 withRouter 的函数包裹了以后,props 上面就能拿到 history 对象。
// 就是把 history 通过 context 传递了下去,并且使用 context 封装了一个高阶组件。const NavContext = createContext(null);
const history = window.history;export default function FuncContext() {return (<NavContext.Provider value={history}><Parent /></NavContext.Provider>)
};const Parent = () =>  <><Child1 /><WithRouterChild2 name={'luyi'} /></>const Child1 = (props) => {// 我通过 useContext, 是能拿到 最外层传入的 context 的值的。const his = useContext(NavContext);return <button onClick={() => his.pushState({}, undefined, 'hello')}>nav to hello</button>
}const Child2 = ({ name, his}) => {return <button onClick={() => his.pushState({}, undefined, 'hello')}>nav to hello -- {name}</button>
}const withRouter = (Component) => {return (props) => {const his = useContext(NavContext);return <Component {...props} his={his}/>}
};
// WithRouterChild2 是一个组件。Child2 也是一个组件。那么:
// withRouter 这个函数,接收一个组件,并且返回一个组件。
// 高阶函数:参数可以是函数,返回值也可以是函数
// 高阶组件:参数可以是组件,返回值也可以是组件
const WithRouterChild2 = withRouter(Child2);

Hoc

• 属性代理 – withRouter
• 反向继承 – LogProps

优化相关 - useCallBack, useMemo, React.Memo

React 的更新逻辑


// App -> FunctionComponent 
// Fiber -> momezied -> Hook 链表 -> 为什么 useApi 不能有条件判断,const Demo = {Foo: Submodule
}function App() {useMemouseCallbackreturn <div><div className="title">你好</div><button>click me</button><Submodule name={'xxx'} /></div>
};// React.Memo
function Submodule ({ name }) {// 一定会执行,但是不代表 dom 会更新console.log('一定会执行')return <div>submodule--{name}</div>
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com