基础知识 - 图1

刚开始不会直接使用组件化进行开发,因此需要引入在线的几个js库

  1. <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  2. <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
  3. <script crossorigin src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
  4. <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

基础知识

虚拟DOM

由于React使用jsx的语法,因此我们编写的代码需要通过babel的翻译成js,因此type要写成text/babel

  1. <script type="text/babel"></script>

比如,我们可以这样创建一个虚拟的DOM

  1. const VDOM = <h1>Hello,React</h1>
  2. ReactDOM.render(VDOM, document.getElementById("app"))

当我们的虚拟DOM有多层结构的时候,需要统一由一个父标签所包裹,如下所示:

  1. const VDOM = (<div>
  2. <div>Hello</div>
  3. <div>World</div>
  4. </div>)
  5. ReactDOM.render(VDOM,document.querySelector('.test'))

JSX语法

  1. 定义虚拟DOM的时候,不能使用""进行包裹(创建的是虚拟DOM而不是字符串)
  2. 标签中如果需要混入js表达式,那么需要使用{}包裹
  3. 样式的类名指定不能使用class,而要用className
  4. 元素的style样式要使用{{}}包裹
  5. 对于一个虚拟DOM来说,有且仅有一个根标签
  6. 标签必须闭合,自闭合也可以
  7. 如果标签是小写字母开头,那么就转化为原生html中的同名元素,如果找不到,则报错;如果是大写字母开头,则去找对应的组件,找不到就报错

    JSX小练习

    根据动态数据渲染列表(对数据使用map函数)
    1. const data = ['A','B','C']
    2. const VDOM = (
    3. <div>
    4. <ul>
    5. {
    6. data.map((item,index)=>{
    7. return <li key={index}>{item}</li>
    8. })
    9. }
    10. </ul>
    11. </div>
    12. )
    13. ReactDOM.render(VDOM,document.querySelector('.test'))

    组件化

    Vue一样,React中也是可以将某个部分拆分成某个独立的组件,进行组件化开发

    函数式组件

    定义一个函数,并且接收一个可选的**props**参数

    不是所有的组件都会从外界接受参数,因此props参数是可选的

  1. function MyList(props) {
  2. return <div>name: {props.name}</div>
  3. }
  4. ReactDOM.Render(<Welcom name="yxr" />,document.getElementById("app"));

类式组件

如果使用类式组件,那么对JavaScript的运用本领提出了一定的要求,主要是this的指向问题

基础知识 - 图2
最后的优化结果如下

  1. class MyList extends React.Component {
  2. state = {
  3. isHot: false
  4. }
  5. render() {
  6. const {isHot} = this.state;
  7. return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉快'}</h1>
  8. }
  9. changeWeather = () => {
  10. const {isHot} = this.state;
  11. this.setState({
  12. isHot: !isHot
  13. })
  14. }
  15. }

在学习的过程中,发现这一块涉及到js面向对象的部分还是蛮多的,并且有些复杂

  1. 第一版本:对state的使用出错

image.png
打开浏览器,发现控制台报错,不能直接对state中的值进行修改
image.png
而是要用React给我们提供的方法进行修改:
image.png

  1. 第二版本:方法绑定出错

这一部分,由于涉及到this指向的问题,稍微有些难度
现在假设我们有如下所示的代码

  1. class Person {
  2. constructor(name) {
  3. this.name = name;
  4. }
  5. say() {
  6. // console.log("Hello,World");
  7. console.log(this);
  8. }
  9. }
  10. let p = new Person('Tom');
  11. let fun = p.say;
  12. p.say();
  13. fun();

我们将实例P上的say()方法赋值给了fun变量,并进行调用,在js的严格模式下,输出如下结果:
image.png
也就是说,只有当我们通过某个类的实例调用类中的方法时,this的指向才指向实例本身
如果通过上述这种方式进行调用,则this的指向为undefined
同理,我们现在将代码修改成如下图片所示
image.png

相当于将click方法赋值给了某个变量,并交由onClick调用

如果看明白上面的描述,那么你应该知道,这种写法会出错,并报undefined异常
image.png
原因是我们的click方法中,调用了this
如何处理这种this指向的问题?有如下两种方式

  • 绑定this

在我们的构造函数中,调用bind方法,绑定this的指向
image.png
但假如我们有很多的方法,那么就需要很多个绑定处理,不够优雅

  • 使用箭头函数

与普通函数不同的是,箭头函数本身不具有this,因此他会找到外面一级,并将this指向它
我们修改上述示例js中的代码,如下所示:
image.png
由于箭头函数的特性,我们不难分析到,两次函数调用输出的结果应该是一样的,都是指向实例本身:
image.png
因此,我们可以将上述React代码改写:
image.png

  1. 第三版本:没有分清楚赋值和调用

如下所示,上面的是将函数的返回值绑定给onClick,而下面是将函数本身绑定给onClick
image.png
但假如我们想使用调用的那种方式,就需要使用高阶函数,如下所示:
image.png

受控组件和非受控组件

React中,数据是单向的,而不是像vue中的双向数据绑定 因此组件也分成了:受控组件和非受控组件两种

  • 受控组件:表单组件的输入组件随着输入的变化,将内容存储到状态中
  • 非受控组件:表单组件的输入组件的内容在有需求的时候,才存储到状态中

    受控组件

    监听输入类组件的数据变化,并不断存储到状态中
    image.png

    非受控组件

    只有在需要的时候,才写入到状态中
    image.png
    React中,更推荐使用受控组件

    组件实例的三大属性

    state

    React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。 React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。

对写法进行简化,我们不再在构造函数中初始化状态,而是直接作为属性写入
image.png
并且,在React中,并不能直接修改state中的值来重新渲染页面中的内容,而是要用给我们提供好的setState方法

  1. this.setState(partialState, [callback]);

有如下两种写法:
写法1:

  1. this.setState({
  2. weather: "凉爽"
  3. })

写法2:

  1. this.setState((state) => {
  2. return {
  3. count: state.count + 1,
  4. };
  5. });
  • setState操作是合并操作,而不是替换操作
  • render()的执行次数是1+n(每一次的setState都会自动调用一次render

    props

    state不同的是,state是组件自身自带的状态,而props是外界传递给组件的值
    image.png
    1. 通过在组件标签上传递值,在组件中就可以获取到所传递的值
    2. 在构造器里的props参数里可以获取到 props
    3. 可以分别设置 propTypes 和 defaultProps 两个属性来分别操作 props的规范和默认值,两者都是直接添加在类式组件的原型对象上的(所以需要添加 static)
    4. 同时可以通过…运算符来简化

image.png
在函数式组件中,props是作为参数传递进到组件中的
image.png

refs

vue中的refs一样,React提供了一种方式,允许我们访问DOM节点或者在render方法中创建的React元素

不用再使用document.getElementById()这样的方法来获取的DOM节点了

一共有三种创建refs的方法,分别是:

  • 字符串形式
  • 回调形式
  • createRef形式

字符串形式
image.png
虽然目前这种方法因为性能问题已经被废弃,但是临时使用一下还是很方便的

回调形式
image.png

createRef形式
image.png