flag倒王来了!挑战3个月转岗前端开发!

175 阅读8分钟

大家好👋,我是一个工作了一年的PPT工具人和项目催命丸,坐标上海,现在打算辞职转岗前端开发😝。

从4月底开始,在B站跟着尚硅谷的男神天禹老师学习React,目前学到了第58节,发现很多知识都没有好好去理解,内化。所以,暂时停止看视频学习,回头来总结复习一下。 写博客是一个很好的督促自己坚持学习、坚持复盘的方法,今天我就在这里立一个flag!在未来3个月内,每周更新一篇前端学习的帖子!如果我没有按时更新,欢迎大家来评论区砸场子,随便批评!

Ps: 强烈推荐B站天禹老师的【尚硅谷React技术全家桶完整版】教程。保姆式教学,讲课细致,幽默风趣。听着上头,学到痴迷~ 特别适合小白~

前言

React是用于构建用户界面的JavaScript库,起源于Facebook的内部项目。 React框架做的本质工作就是吃入数据,吐出UI,把声明式的代码转换为命令式的 DOM 操作,把数据层面的描述映射到用户可见的 UI 变化中去。

一、React相关js库

前期先写html代码引入库,后续用脚手架后即开始使用import进行导入

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>

二、组件实例的三大属性

1. state

常用于通过状态中的数据驱动页面的更新/显示。 state的初始值支持各种数据类型,包括null,string或者object对象,只要是javascript允许的都可以。

<body>
    <div id="test"></div>
    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">
        //1.创建组件
        class Weather extends React.Component{
            //初始化状态
            state = {isHot:false,wind:'微风'}
            //render调用几次? ———— 1+n次, 初始化1次,状态更新n次数
            render(){
                const {isHot,wind} = this.state
                return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
            }
            //用类创建组件时,组件中所有的自定义方法 ———— 都要用赋值语句的形式+箭头函数
            //箭头函数没有自己的this,若在箭头函数中使用了this关键字,不会报错,会寻找外层函数的this作为箭头函数的this
            //changeWeather调用几次? ———— 点几次,调几次
            changeWeather = ()=>{
            const isHot = this.state.isHot
            //要借助一个内置的API(setState)去更改状态,且更新是一种合并,不是替换
            this.setState({isHot:!isHot})
            }
        }
        //2.渲染组件到页面
        ReactDOM.render(<Weather/>,document.getElementById('test'))
    </script>
</body>

2. props

props是一个从外部传进组件的参数,主要用于从父组件向子组件传递数据,它具有可读性和不变性。

(1)每个组件对象都会有props(properties的简写)属性

当需要向一个组件传递数据的时候,我们使用props,比如<FunctionalComponent name="Shiori" />,name就是Component的一个props属性。

(2)组件标签的所有属性都保存在props中

(3)内部读取某个属性值:this.props.propertyName

(4)作用:通过标签属性从组件外 向组件内传递数据(只读 read only)

(5)用propTypes对props中的属性值进行类型限制和必要性限制

//对标签属性进行类型、必要性的限制
Person.propTypes = {
    name:PropTypes.string.isRequired, //限制name必传,且为字符串
    sex:PropTypes.string, //限制sex为字符串
    age:PropTypes.number, //限制age为数值
    speak:PropTypes.func, //限制speak为函数
}

3. refs

简介: 访问 DOM 节点 / 访问在render方法中创建的React元素;组件内的标签可以定义ref属性来标识自己;调用React.createRef后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的。

注:元素是构成 React 应用的最小单位,它用于描述屏幕上输出的内容。组件由元素构成。

1)字符串形式的ref

<input ref="input1" type="text" placeholder="点击按钮提示数据"/>

2)函数形式的ref

<input ref={(currentNode)=>{this.input1 = currentNode}} type="text" placeholder="点击按钮提示数据"/>

三、React两大组件

1. 函数式组件

也称无状态组件(可使用React Hooks:useState改变state),一般用于静态没有交互事件内容的组件页面,没有this困扰且代码简洁,便于逻辑的拆分复用。函数组件是面向过程编程思维方式。

sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/babel">
        // 1.创建函数式组件
        function MyComponent(){
            console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式
            return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
        }
        // 2.渲染组件到页面 (将组件MyComponent渲染到id为test的标签中)
        ReactDOM.render(<MyComponent/>,document.getElementById('test'))
        /*
            1) React解析组件标签,找到了MyComponent组件
            2) 发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
        */
   </script>
</body>

2. 类式组件

类式组件又称为动态组件,一般用于有交互事件或数据修改的组件页面。类组件是面向对象编程思维方式。

<body>
    <div id="test"></div>
    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/babel">
        // 1.创建类式组件
        class MyComponet extends React.Component {
            console.log('render中的this:',this); //this指向的是当前组件的实例对象
            return <h2>我是用类定义的组件(适用于【复杂组件】的定义</h2>
            }
        }
        // 2.渲染组件到页面
        ReactDOM.render(<MyComponent/>,document.getElementById('test'))
        /*
            1) React解析组件标签,找到了MyComponent组件;
            2) 发现组件是使用类定义的,随后【new出该类的实例】,并【通过该实例调用】到原型上的render方法;
            3) 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
        */
   </script>
</body>

3. 函数组件和类式组件对比总结:

区别函数组件类组件
生命周期
this
state
改变stateReact Hooks:useStatethis.setState()
性能高(不用实例化)低(需要实例化)

四、事件处理

  1. 通过onXxx属性指定事件处理函数(注意大小写,小驼峰,如onClick)

    1) React使用的是自定义(合成)事件, 而不是使用的原生DOM事件(更好的兼容性)

    2) React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)(高效)

  1. 通过event.target得到发生事件的DOM元素对象(当发生事件的元素和操作的元素是同一个时,可以借助事件对象event.target拿到值,尽量避免使用ref,注意不要过度使用ref)

五、收集表单数据

1. 非受控组件

页面中所有输入类DOM,现用现取,即为非受控组件。例如:input框的输入值是当点击登录按钮时才被获取到。

<Input defaultValue={x} ref={input}/>

2. 受控组件

页面中所有输入类DOM,随时输、随时就把值维护到状态中,需要用的时候直接从状态中取出来,即为非受控组件。

<Input value={x} onChange={fn}/>

3. 对比

区别非受控组件受控组件
一次性取值(例如:提交时)
提交时验证
即时现场验证×
有条件地禁用提交按钮×
强制输入格式×
一个数据的多个输入×
动态输入×

六、高阶函数_函数柯里化

高阶函数:如果有一个函数符合下面2个规范中的任何一个,就为高阶函数。

1.若A函数,接收的参数是一个函数,那么A即为高阶函数

2.若A函数,调用的返回值依然是一个函数,那么A即为高阶函数

常见的高阶函数有:Promise、setTimeout、arr.map()等等

函数柯里化:通过函数调用,继续返回函数的方式,实现多次按接收参数,最后统一处理的函数编码形式。

七、组件的生命周期

生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期钩子 <=> 生命周期函数

ComponentWillMount() 组件将要挂载的钩子

componentDidMount() 组件挂载完毕的钩子,组件挂载页面完毕后调用,只调用一次

shouldComponentUpdate() 控制组件更新的“阀门”

componentWillUpdate() 组件将要更新的钩子

render()

componentDidUpdate() 组件更新完毕的钩子

componentWillReceiveProps(props) 组件将要接收新的props的钩子

static getDerivedStateFromProps(props,state) 从Props得到一个派生的状态。如果state的值在任何时候都取决于props,可以使用该方法。派生状态会导致代码冗余,并使组件难以维护。

getSnapshotBeforeUpdate() 在更新之前获取快照

最核心最常用的三个钩子:render()、componentDidMount()、componentWillUpdate()

旧生命周期图: 2_react生命周期(旧).png 新生命周期图: 3_react生命周期(新).png

八、DOM的Diffing算法

1. Diffing算法

React首先生成虚拟DOM,再转换为页面的真实DOM。DOM更新时, react 会先与之前的虚拟DOM做对比,和之前一样的节点可复用,不会重新渲染;与之前不同的节点,则重新生成。

2. key的作用

经典面试题:
Q1. react/vue中的key有什么作用?(key的内部原理是什么)
    虚拟DOM中key的作用:
    1)简言之:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。

    2)详细说:当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,
              随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:
                a.旧虚拟DOM中找到了与新虚拟DOM相同的key:
                    ①若新虚拟DOM中内容没变,直接使用之前的真实DOM
                    ②若内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
                b.旧虚拟DOM中没有找到与新虚拟DOM相同的key:
                    根据数据创建新的真实DOM,随后渲染到页面

Q2. 为什么遍历列表时,key最好不用index?
    用index作为key可能会引发的问题:
    1) 若对数据进行:逆序添加、逆序删除等破环顺序操作:
                    会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。
    2)如果结构中还包含输入类DOM:
                    会产生错误DOM更新 ==> 界面有问题

    3)注意!如果不存在对数据的逆序添加、逆序删除等破环顺序操作,
       仅用于渲染列表用于展示,使用index作为key是没有问题的。

Q3. 开发中如何选择key?:
    1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
    2)如果确定只是简单的展示数据,用index也是可以的。

———————————————————————————

暂时就写到这里8,本小白渣第一次写技术博客,写完了我都不想发布了😭,不管这么多,先完成、再完善😳。如果有不对的地方,欢迎各位在评论区指出,谢谢!(^^ゞ

🚩flag来了:本周会继续挤时间学习组件化编程,把todolist的案例做完后,即学完第64课后,下一篇博客将会在5月15日更新。