day1--react基础语法

这篇博客详细介绍了React的基础知识,包括React的起源、特点、开发依赖和jsx语法。讲解了React如何通过组件化、虚拟DOM和声明式编程提高开发效率。还涉及到ES6的class关键字和在VSCode中设置用户片段以提升编码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、react简介

1.起源

  • React是2013年,Facebook开源的JavaScript框架,那么当时为什么Facebook要推出这样一款框架呢?

    • 这个源于一个需求,所产生的bug:
    • 该功能上线之后,总是出现bug;
    • 三个消息的数字在发生变化时,过多的操作很容易产生bug;
  • bug是否可以修复呢?当然可以修复,但是Facebook的工程师并不满足于此;

    • 他们开始思考为什么会产生这样的问题;
    • 在传统的开发模式中,我们过多的去操作界面的细节;(前端、iOS、Android)
    • 并且需要掌握和使用大量DOM的API,当然我们可以通过jQuery来简化和适配一些API的使用;
    • 另外关于数据(状态),往往会分散到各个地方,不方便管理和维护;
  • 他们就去思考,是否有一种新的模式来解决上面的问题:

    • 1.以组件的方式去划分一个个功能模块
    • 2.组件内以jsx来描述UI的样子,以state来存储组件内的状态
    • 3.当应用的状态发生改变时,通过setState来修改状态,状态发生变化时,UI会自动发生更新

2.特点:

1.采用组件化模式,声明式编程,提高开发效率及组件复用率(多平台适配)

  • 命令式编程:每一个操作都是给浏览器或者计算机一步步命令
  • 声明式编程:

2.在react native中可以使用react语法进行移动端开发

3.使用虚拟dom和diff算法进行

3.react开发依赖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W4qxn2lS-1649341100264)(img/在这里插入图片描述
.png)]

4.引入react依赖

方式一:直接CDN引入

方式二:下载后,添加本地依赖

方式三:通过npm管理(后续脚手架再使用)

体验react实现更改内容

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">app</div>
  <!-- 添加react依赖 -->
  <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <!-- 开始开发 -->
  <!-- 注意事项:使用jsx,并且希望javascript中的·jsx代码得到正确编译,需要给script标签添加type属性 -->
  <script type="text/babel">
    // ReactDOM.render(渲染的内容, 挂载的对象)
    // 渲染内容中应该写jsx代码
    let message = 'hello world'
    function btnClick() {
      message = 'hello react'
      console.log(message);
      render()
    }
    // 与vue一样,最外层只能有一个标签
    function render() {
      ReactDOM.render(
      <div>
        <h2>{message}</h2>
        <button onClick={btnClick}>更改</button>
      </div>,
      document.getElementById('app'))
    }
    render()
  </script>
</body>

</html>

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-78GoJTyh-1649341100266)(img/hello-world.png)]

二、补充

1.es6中的class关键字

  • 在ES6之前,我们通过function来定义类,但是这种模式一直被很多从其他编程语言(比如Java、C++、OC等等)转到

JavaScript的人所不适应。

  • 原因是,大多数面向对象的语言,都是使用class关键字来定义类的。

  • 而JavaScript也从ES6开始引入了class关键字,用于定义一个类。

  • 转换成ES6中的类如何定义呢?

    • 类中有一个constructor构造方法,当我们通过new关键字调用时,就会默认执行这个构造方法
    • 构造方法中可以给当前对象添加属性
    • 类中也可以定义其他方法,这些方法会被放到Person类的prototype上
  • 另外,属性也可以直接定义在类中:

    • height和address是直接定义在类中
  • 继承是面向对象的一大特性,可以减少我们重复代码的编写,方便公共内容的抽取(也是很多面向对象语言中,多态的前提)。

  • ES6中增加了extends关键字来作为类的继承。

  • 注意:在constructor中,子类必须通过super来调用父类的构造方法,对父类进行初始化,否则会报错。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // es5中定义类
    // function Parent(name, age) {
    //   this.name = name
    //   this.age = age
    // }
    class Parent {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this);
        console.log(this.name, this.age);
      }
      name1 = 'nihao'
    }

    class Child extends Parent {
      constructor(name, age, rate) {
        super(name, age)
        this.rate = rate
      }
    }
    // es5中的function和es6中的类两者等价
    let p = new Parent('sasha', 18)
    let c = new Child('66', 12, 1)
    console.log(p);
    console.log(c);
    // p.running()
  </script>
</body>

</html>

2.在vscode中添加用户片段,提高代码效率

使用https://snippet-generator.app/来生成具有json格式的代码片段

"react base code": {
  "prefix": "reactapp",
  "body": [
    "<!DOCTYPE html>",
    "<html lang=\"en\">",
    "",
    "<head>",
    "  <meta charset=\"UTF-8\">",
    "  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">",
    "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
    "  <title>Document</title>",
    "</head>",
    "",
    "<body>",
    "  <div id=\"app\">app</div>",
    "  <!-- 添加react依赖 -->",
    "  <script crossorigin src=\"https://unpkg.com/react@16/umd/react.development.js\"></script>",
    "  <script crossorigin src=\"https://unpkg.com/react-dom@16/umd/react-dom.development.js\"></script>",
    "  <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>",
    "  <script type=\"text/babel\">",
    "    class App extends React.Component {",
    "      constructor(props) {",
    "        super(props)",
    "      }",
    "      render() {",
    "        return (",
    "          <div>",
    "            hello world",
    "          </div>",
    "        )",
    "      }",
    "    }",
    "    ReactDOM.render(<App />, document.getElementById('app'))",
    "  </script>",
    "</body>",
    "",
    "</html>"
  ],
  "description": "react base code"
}

三、认识jsx的语法

1.认识jsx

jsx语法,将一个标签赋值给一个变量,这就是jsx语法,必须给script标签加上type属性才不会报错
在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MkB4a3Rd-1649341100267)(img/认识jsx语法.png)]

2.书写规范

JSX的顶层只能有一个根元素,所以我们很多时候会在外层包裹一个div原生(或者使用后面我们学习的Fragment);

为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写;如果不用小括号的话,必须在一行

jSX中的标签可以是单标签,也可以是双标签;

注意:如果是单标签,必须以/>结尾;

3.jsx使用

3.1注释(花括号里面+注释符号)

      render() {
        return (
          <div>
            {/*这是一段注释*/}
            hello world
          </div>
        )
      }

3.2嵌入数据和表达式,都需要花括号包裹

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">app</div>
  <!-- 添加react依赖 -->
  <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          // 在大括号中能够正常显示的内容
          counter: 0, // number
          name: 'sasha', // string
          friends: ['kobe', '66s', 'coderwhy'], // array

          // 不能正常显示的内容
          test1: null,
          test2: undefined,
          test3: true, // Boolean
          friend: {
            name: 'shasha'
          }
        }
      }
      getFriend() {
        console.log(this);
        return this.state.friends[0]
      }
      // 这是一段注释
      render() {
        return (
          <div>
            {/*这是一段注释*/}
            <h2>{this.state.counter}</h2>
            {/*1.三元表达式*/}
            <h2>{this.state.test3 ?'成功':'失败'}</h2>
            {/*2.运算符表达式*/}
            <h2>{this.state.test3 + ''}</h2>
            {/*3.函数调用*/}
            <h2>{this.getFriend()}</h2>
            {/*以下不可以正常显示*/}
            <h2>{this.state.test1}</h2>
            <h2>{this.state.test2}</h2>
            <h2>{this.state.test3}</h2>
            {/*会报错,因为jsx不支持对象成为子类*/}
            {/*<h2>{this.state.friend}</h2>*/}
          </div>
        )
      }
    }
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>
</body>

</html>

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGAiKdP3-1649341100268)(img/jsx使用.png)]

3.3绑定属性

  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          title: '我是标题',
          imgUrl: '../../../南充学而思/冰激凌.jpg'
        }
      }
      render() {
        const {active} = this.state
        return (
          <div>
            {/*1.绑定普通属性*/}
            <h2 title={this.state.title}>我是标题</h2>
            <img src={this.state.imgUrl} alt="" width="140px" />
            {/*2.绑定class属性*/}
            <div className="box">绑定class属性</div>
            <div className={"box " + (active ? 'active' : '')}>绑定class属性</div>
            {/*3.绑定style*/}
            <div style={{color: 'red'}}>绑定style属性</div>
          </div>
        )
      }
    }
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>

3.4绑定事件

在构造函数和render函数中,this可以正常使用
在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H1AQkcXk-1649341100269)(img/react事件绑定时的this指向问题.png)]

  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          counter: 0
        }
        this.btnClick = this.btnClick.bind(this)
      }
      render() {
        return (
          <div>
            <button onClick={this.btnClick}>事件绑定</button>
            <button onClick={this.add}>+1</button>
            <button onClick={() => {
              this.sub() // 这里的this就是当前类
            }}>-1</button>
          </div>
        )
      }
      // 方案一: 显式绑定this
      btnClick() {
        console.log('click');
        console.log(this); // undefined
        // 如果没用类里面的属性,那么不用显式绑定this
        // 但是如果用了就需要在render函数里面显式绑定this
        console.log(this.state.counter);
      }
      // 方式二: 使用箭头函数
      add = () => {
        // 箭头函数里面没有绑定this
        console.log(this); // 当前类 
        this.state.counter++
      }
      // 方案三 在调用的时候使用箭头函数调用
      sub() {
        console.log(this);
        this.state.counter--
      }
    }
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>

3.5事件传递参数

箭头函数传参

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">app</div>
  <button class="btn">原生传递参数</button>
  <script>
    document.getElementsByClassName('btn')[0].addEventListener('click', (e) => {
      console.log(e);
    })
  </script>
  <!-- 添加react依赖 -->
  <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          movies: ['星际穿越', '大话西游', '盗梦空间', '少年派']
        }
      }
      render() {
        return (
          <div>
            <button onClick={this.btnClick}>react事件绑定--传递参数</button>
            <ul>
              {
                this.state.movies.map((item, i) => {
                  return <li onClick={(e) => {this.liClick(item, i, e)}}>{item}</li>
                })
              }
            </ul>
          </div>
        )
      }
      liClick(movie, index, e) {
        console.log(movie, index);
      }
      btnClick(e) {
        console.log(e);
      }
    }
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>
</body>

</html>

3.6 react条件渲染

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JoCQDbHz-1649341100270)(img/react条件渲染.png)]

  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          isLogin: true
        }
      }
      render() {
        let welcome = null
        let btnText = null
        // 条件渲染方法一:条件判断
        if (this.state.isLogin) {
          welcome = <h2>欢迎回来</h2>
        } else {
          welcome = <h2>请先登录</h2>
        }
        return (
          <div>
            {welcome}
            {/*方法二: 三元运算符*/}
            <button onClick={() => { this.changeLogin() }}>{this.state.isLogin ? '退出' : "登录"}</button>
            {/*方法三: 逻辑与*/}
            {/*逻辑与:一个条件不成立,那么后面的条件都不会进行判断了*/}
            <h2>{this.state.isLogin && '你好呀, saSha'}</h2>
          </div>
        )
      }
      changeLogin() {
        this.setState({
          isLogin: !this.state.isLogin
        })
      }
    }
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>

v-show效果(改变style属性控制display)
<h2 style={{display: isLogin ? 'block' : 'none'}}>你好呀, saSha</h2>

3.7列表渲染

使用高阶函数
在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bxp9tWJo-1649341100270)(img/列表渲染.png)]

4.jsx的本质

React.creatElement()与vue的h函数类似

  <script type="text/babel">
    const message1 = <h2>hello world</h2>
    // jsx语法其实是React.createElement()的语法糖
    // 所以render中message1和message2的效果一样
    const message2 = React.createElement('h2', null, 'hello world')
    ReactDOM.render(message2, document.getElementById('app'))
  </script>

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fBb9v9BC-1649341100271)(img/jsx的本质.png)]

5.虚拟DOM

  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
      }
      // render() {
      //   return (
      //     <div>
      //       <h2>我是标题</h2>
      //       <button>按钮</button>
      //       <div class="content">
      //         <p>我是页面内容</p>
      //       </div>
      //       <div class="footer">
      //         <p>我是尾部内容</p>
      //       </div>
      //     </div>
      //   )
      // }
      // 上面的代码实质上是下面的代码,经过babel转换的
      render() {
        let eleObject = /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h2", null, "\u6211\u662F\u6807\u9898"), /*#__PURE__*/React.createElement("button", null, "\u6309\u94AE"), /*#__PURE__*/React.createElement("div", {
          className: "content"
        }, /*#__PURE__*/React.createElement("p", null, "\u6211\u662F\u9875\u9762\u5185\u5BB9")), /*#__PURE__*/React.createElement("div", {
          className: "footer"
        }, /*#__PURE__*/React.createElement("p", null, "\u6211\u662F\u5C3E\u90E8\u5185\u5BB9")));

        // 本质是一个对象树,这个对象树就是虚拟dom
        console.log(eleObject);
        return eleObject
      }
    }
    // ReactDOM.render()这个函数将虚拟dom树变成真实dom
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-73c0Miwi-1649341100271)(img/虚拟Dom.png)]

5.1为什么使用虚拟dom

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfyX9Cuv-1649341100272)(img/为什么使用虚拟dom.png)]

5.2频繁操作dom的问题

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uBZNjBD4-1649341100273)(img/频繁操作dom的问题.png)]

5.3声明式编程

  • 虚拟DOM帮助我们从命令式编程转到了声明式编程的模式

  • **React官方的说法:**Virtual DOM 是一种编程理念。

    • 在这个理念中,UI以一种理想化或者说虚拟化的方式保存在内存中,并且它是一个相对简单的JavaScript对象
    • 我们可以通过ReactDOM.render让 虚拟DOM 和 真实DOM同步起来,这个过程中叫做协调(Reconciliation);
  • 这种编程的方式赋予了React声明式的API:

  • 你只需要告诉React希望让UI是什么状态;

  • React来确保DOM和这些状态是匹配的;

  • 你不需要直接进行DOM操作,只可以从手动更改DOM、属性操作、事件处理中解放出来;

四、以上所学可以做的案例

  • reduce的使用

  • filter的使用

  • 条件渲染

  • 列表渲染(map的使用)

  • 在这里插入图片描述

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9YuIlUSq-1649341100273)(img/gouwucheanli.png)]

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    table {
      border: 1px solid #ddd;
      border-collapse: collapse;
      text-align: center;
    }

    td,
    th {
      border: 1px solid #ddd;
      padding: 10px 16px;
    }

    th {
      background-color: #ccc;
      border: 1px solid #ccc;
    }
  </style>
</head>

<body>
  <div id="app">app</div>
  <!-- 添加react依赖 -->
  <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <script src="./fomat-price.js"></script>
  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          books: [
            {
              id: 1,
              name: '《算法导论》',
              date: '2006-9',
              price: 85.00,
              count: 1
            },
            {
              id: 2,
              name: '《UNIX编程艺术》',
              date: '2006-2',
              price: 59.00,
              count: 1
            },
            {
              id: 3,
              name: '《编程珠玑》',
              date: '2008-10',
              price: 39.00,
              count: 1
            },
            {
              id: 4,
              name: '《代码大全》',
              date: '2006-3',
              price: 128.00,
              count: 1
            },
          ]
        }
      }
      renderBooks() {
        return (
          <div>
            <table>
              <thead>
                <tr>
                  <th>#</th>
                  <th>书籍名称</th>
                  <th>出版日期</th>
                  <th>价格</th>
                  <th>购买数量</th>
                  <th>操作</th>
                </tr>
              </thead>
              <tbody>
                {
                  this.state.books.map((item, i) => {
                    return (
                      <tr>
                        <td>{i + 1}</td>
                        <td>{item.name}</td>
                        <td>{item.date}</td>
                        <td>{item.price}</td>
                        <td>
                          <button disabled={item.count <= 1} onClick={() => { this.changeBookCount(i, -1) }}>-</button>
                          <span>{item.count}</span>
                          <button onClick={() => { this.changeBookCount(i, +1) }}>+</button>
                        </td>
                        <td><button onClick={() => {
                          this.subBook(i)
                        }}>移除</button></td>
                      </tr>
                    )
                  })
                }
              </tbody>
            </table>
            <h2>总价格: {this.getTotalPrice()}</h2>
          </div>
        )
      }
      render() {
        return this.state.books.length !== 0 ? this.renderBooks() : <h2>购物车为空~</h2>
      }
      getTotalPrice() {
        // let sum = 0;
        // for(let item of this.state.books) {
        //   sum += item.count * item.price
        // }
        // return formatPrice(sum)
        // 回调函数的参数
        // 参数一: 上一次回调函数的结果(没有回调就使用初始值)
        const totalPrice = this.state.books.reduce((preValue, item) => {
          return preValue + item.count * item.price
        }, 0)
        return formatPrice(totalPrice)
      }
      subBook(i) {
        let newBooks = this.state.books.filter((item, index) => {
          return index != i
        })
        this.setState({
          books: newBooks
        })
      }
      changeBookCount(i, count) {
        let newBooks = [...this.state.books]
        newBooks[i].count += count
        this.setState({
          books: newBooks
        })
      }
    }
    ReactDOM.render(<App />, document.getElementById('app'))
  </script>
</body>

</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值