React---day3

React

2.5 jsx的本质

jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖。所有的jsx最终都会被转换成React.createElement的函数调用。

createElement需要传递三个参数:

  • 参数一:type

    当前ReactElement的类型;

    如果是标签元素,那么就使用字符串表示 "div";

    如果是组件元素,那么就直接使用组件的名称;

  • 参数二:config

    所有jsx中的属性都在config中以对象的属性和值的形式存储

  • 参数三:children

    存放在标签中的内容,以children数组的方式进行存储;

    当然,如果是多个元素呢?React内部有对它们进行处理,处理的源码在下方

我们知道默认jsx是通过babel帮我们进行语法转换的,所以我们之前写的jsx代码都需要依赖babel。 可以在babel的官网中快速查看转换的过程:https://babeljs.io/repl/#?presets=react

值得说明的是,type何config是一一对应的,children则是通过for循环(从滴2个开始)依次存储到一个数组当中的。

2.6 虚拟DOM

jsx的本质是createElemen t函数,而createElement函数会利用ReactElement对象 创建JavaScript的对象树->通过ReactDOM.render进行渲染成为真实的DOM

为什么要采用虚拟DOM,而不是直接修改真实的DOM呢

  • 很难跟踪状态发生的改变:原有的开发模式,我们很难跟踪到状态发生的改变,不方便针对我们应用程序进行调试;
  • 操作真实DOM性能较低:传统的开发模式会进行频繁的DOM操作 ,而这一的做法性能非常的低

为什么操作真实DOM性能较低?

  • 首先,document.createElement本身创建出来的就是一个非常复杂的对象;
  • 其次,DOM操作会引起浏览器的回流和重绘,所以在开发中应该避免频繁的DOM操作;

2.7 阶段性案例

需求:展示书籍数据,算出总价格,数量可以点击增加和减少,选择移除可以移除

技术难点1:渲染数据

map渲染就可以啦

复制代码
  <tbody>
                  {this.state.books.map((item, index) => (
                    <tr key={item.id}>
                      <td>{index + 1}</td>
                      <td>{item.name}</td>
                      <td>{item.date}</td>
                      <td>{formatPrice(item.price)}</td>
                      <td>
                        <button onClick={() => {this.changeBookNum(index , -1)}}>-</button>
                        <span className="count">{item.count}</span>
                        <button onClick={() => {this.changeBookNum(index , 1)}}>+</button>
                      </td>
                      <td>
                        <button onClick={() => {this.removeItem(index)}}>移除</button>
                      </td>
                    </tr>
                  ))}
                </tbody>

**算出总价格:**使用reduce函数

复制代码
        getTotalPrice = () => {
          return this.state.books.reduce((total, book) => {
            return total + book.count * book.price;
          }, 0);
        };

数量可以点击增加和减少:需要一个新的数组,因为setState是不允许改变state里面的数据的

复制代码
                changeBookNum = (index , count) => {
          // 因为不能违背setState不能改变数据本身
          let newArr = [...this.state.books];
          newArr[index].count += count;
          this.setState({
            books:newArr
          })

       }

**选择移除可以移除:**使用fiolter函数。可以返回一个满足条件的鑫数组

复制代码
        removeItem = (index) => {
          this.setState ({
            books: this.state.books.filter((item, idx) => index !== idx),
          });
        };

**选择渲染:**如果是存在数据就渲染数据,如果数据全部都没有了就渲染"数据为空"

复制代码
       renderBooks(){
            const totalPrice = this.getTotalPrice();
          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, index) => (
                    <tr key={item.id}>
                      <td>{index + 1}</td>
                      <td>{item.name}</td>
                      <td>{item.date}</td>
                      <td>{formatPrice(item.price)}</td>
                      <td>
                        <button onClick={() => {this.changeBookNum(index , -1)}}>-</button>
                        <span className="count">{item.count}</span>
                        <button onClick={() => {this.changeBookNum(index , 1)}}>+</button>
                      </td>
                      <td>
                        <button onClick={() => {this.removeItem(index)}}>移除</button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              <h2>总价格:{formatPrice(totalPrice)}</h2>
            </div>
          );
        }
        renderEmpty(){
          return <h2>购物车为空</h2>
        }

        render() {
          return this.state.books.length ? this.renderBooks() : this.renderEmpty();
        }

总体代码如下:

复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>react</title>
    <style>
      table {
        border: 2px solid #fff;
        border-collapse: collapse;
        padding: 10px;
      }
      th,
      td {
        text-align: center;
        border: 2px solid #ddd;
        padding: 15px;
      }
      thead {
        background-color: #eee;
        font-weight: 800;
      }
      .count {
        margin: 0 10px;
      }
      tfoot {
        margin-top: 10px;
        font-size: 20px;
        color: black;
        font-weight: 800;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
    <script
      src="https://unpkg.com/react@16/umd/react.development.js"
      crossorigin
    ></script>
    <script
      src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
      crossorigin
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script src="./format.js"></script>
    <script type="text/babel">
      class App extends React.Component {
        constructor() {
          super();
          this.state = {
            books: [
              {
                id: 1,
                name: "《算法导论》",
                date: "2006-9",
                price: 85.0,
                count: 1,
              },
              {
                id: 2,
                name: "《UNIX编程艺术》",
                date: "2006-2",
                price: 59.0,
                count: 1,
              },
              {
                id: 3,
                name: "《编程珠玑》",
                date: "2008-10",
                price: 39.0,
                count: 1,
              },
              {
                id: 4,
                name: "《代码大全》",
                date: "2006-3",
                price: 128.0,
                count: 1,
              },
            ],
          };
        }
        getTotalPrice = () => {
          return this.state.books.reduce((total, book) => {
            return total + book.count * book.price;
          }, 0);
        };
        removeItem = (index) => {
          this.setState ({
            books: this.state.books.filter((item, idx) => index !== idx),
          });
        };
        renderBooks(){
            const totalPrice = this.getTotalPrice();
          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, index) => (
                    <tr key={item.id}>
                      <td>{index + 1}</td>
                      <td>{item.name}</td>
                      <td>{item.date}</td>
                      <td>{formatPrice(item.price)}</td>
                      <td>
                        <button onClick={() => {this.changeBookNum(index , -1)}}>-</button>
                        <span className="count">{item.count}</span>
                        <button onClick={() => {this.changeBookNum(index , 1)}}>+</button>
                      </td>
                      <td>
                        <button onClick={() => {this.removeItem(index)}}>移除</button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              <h2>总价格:{formatPrice(totalPrice)}</h2>
            </div>
          );
        }
        renderEmpty(){
          return <h2>购物车为空</h2>
        }

        render() {
          return this.state.books.length ? this.renderBooks() : this.renderEmpty();

        
        }
                changeBookNum = (index , count) => {
          // 因为不能违背setState不能改变数据本身
          let newArr = [...this.state.books];
          newArr[index].count += count;
          this.setState({
            books:newArr
          })

       }
      }
      ReactDOM.render(<App />, document.getElementById("app"));
      // state数据具有不可变性,filter不会修改原来的数组,而是返回应该数组
    </script>
  </body>
</html>
相关推荐
kyriewen1 小时前
写组件文档写到吐?我用AI自动生成Storybook,同事以后直接抄
前端·javascript·面试
五点六六六2 小时前
你敢信这是非Native页面写出来的渐变效果吗🌝(底层原理解析
前端·javascript·面试
吃西瓜的年年3 小时前
TypeScript
javascript·ubuntu·typescript
熊猫_豆豆5 小时前
一个模拟四轴飞行器在随机气流扰动下悬停飞行的交互式3D仿真网页,包含飞行器建模与PID控制算法
javascript·3d·html·四轴无人机模拟飞行
来恩10037 小时前
jQuery选择器
前端·javascript·jquery
前端繁华如梦7 小时前
树上挂苹果还是挂玻璃球?Three.js 程序化果实的完整实现指南
前端·javascript
CDwenhuohuo7 小时前
优惠券组件直接用 uview plus
前端·javascript·vue.js
川冰ICE8 小时前
TypeScript装饰器与元编程实战
前端·javascript·typescript
AI砖家8 小时前
Vue3组件传参大全,各种传参方式的对比
前端·javascript·vue.js
希望永不加班8 小时前
var局部变量类型推断的利弊
java·服务器·前端·javascript·html