美文网首页
React初印象

React初印象

作者: zhengxiaolang | 来源:发表于2024-09-10 15:34 被阅读0次

    听过哪些与React相关的名词:


    dom5.png

    今天主要介绍:React 18.3
    以下分享源码在此

    1、虚拟 DOM(Virtual DOM):

    React 使用虚拟 DOM 渲染流程。


    dom1.png
     <body>
      <div id="root"></div>
      <!-- 引入React.js -->
      <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
      <!-- 引入ReactDOM.js -->
      <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    
      <script src="https://unpkg.com/babel-standalone/babel.min.js"></script>
    
      <script type="text/babel">
    
        function handleClick() {
          alert('Div element clicked!');
        }
    
         //React.createElement是React官方提供创建虚拟dom的一个api.
        const element = React.createElement(
          'div',
          { className: 'redBg', onClick: handleClick },
          'Item 1'
        );
    
    //JSX语法,经过Babel编译器,转化成React.createElement()
       const element2 = (
          <div className="redBg" onClick={handleClick}>
            Item 1
          </div>
        );
    
        //将虚拟 DOM(React 元素)渲染到真实 DOM 的过程: 1.获取页面元素-->2.创建容器-->3.将虚拟元素渲染到容器内
    
        const root = ReactDOM.createRoot(document.getElementById('root'));
        root.render(element);
    
        const realDom = document.getElementById('realDom');
    
        console.log('virtualDom', element);
        console.log('realDom', realDom);
    
      </script>
    </body>
    
    dom3.png
    虚拟dom总结:
    - 本质:JS对象,相对真实dom,相对真实dom是一个轻量级的对象。
    
    - 优点:
    1、最小化真实dom操作,减少重绘(Repaint)和重排(Reflow)次数。
    
       重排:受DOM的布局、尺寸、位置等发生变化时影响
       重绘:受DOM的外观(如颜色、边框、背景)发生变化时影响
    
    2、快速开发,组件复用。
    
    - 缺点:多一份虚拟dom内存开销。
    

    2、JSX:

    JSX是一种用于描述 UI 的JavaScript 语法扩展,允许在 JavaScript 中编写类似 HTML 的代码。
    编译器Babel将jsx代码编译成React.createElement。


    dom4.png
    • 单行写法
    const element = <h1>Hello, world!</h1>;
    
    • 多行写法
    
    const element2 = (
        <div className="redBg" onClick={handleClick}>
            muplti line
          </div>
       );
    
    • 传参,可用插入表达式
    const itemName = 'Item 2';
    const element3 = (
        <div className="redBg" onClick={handleClick}>
            {itemName}
          </div>
       );
    
    • 复杂点的写法,多写点JS方法
    const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
    const element = (
      <div className="fruit-list">
        <h1>Fruit List</h1>
        <ul>
          {items.map((item, index) => (
            <li key={index} className="fruit-item">
              {item}
            </li>
          ))}
        </ul>
        <footer>
          <p>Total items: {items.length}</p>
        </footer>
      </div>
    );
    // 渲染到页面
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(element);
    
    • 根元素
      如何不增加额外 DOM 节点
    错误写法:
    const element = (
        <h1>Hello</h1>
        <p>This is a paragraph.</p>
       );
    纠正写法:
    const element = (
      <React.Fragment>
        <h1>Hello</h1>
        <p>This is a paragraph.</p>
      </React.Fragment>
    );
    简易写法:
    const element = (
      <React.Fragment>
        <h1>Hello</h1>
        <p>This is a paragraph.</p>
      </React.Fragment>
    );
    总结:
    <> ... </> = <React.Fragment>... </React.Fragment>
    

    而在angular中,刚好相反,是在HTML 的代码编写js代码

    <div>
      <p>{{ message }}</p>
      <button (click)="updateMessage()">Click me</button>
    </div>
    

    3、组件(Component):

    React 的核心概念,UI 的构建块。组件可以是函数组件或类组件

    • 类组件
    class ClassComponent extends Component {
        constructor(props) {
            super(props);
            // 初始化 state
            this.state = {
                count: 0,
            };
        }
    
        componentDidMount() {
            // 组件挂载后调用
            console.log('Component did mount');
        }
    
        shouldComponentUpdate(nextProps, nextState) {
            // 控制组件是否需要重新渲染
            return nextState.count !== this.state.count;
        }
    
        componentDidUpdate(prevProps, prevState) {
            // 组件更新后调用
            console.log('Component did update');
        }
    
        componentWillUnmount() {
            // 组件卸载之前调用
            console.log('Component will unmount');
        }
    
        render() {
            return (
                <div>
                    <p>Count: {this.state.count}</p>
                    <button onClick={this.handleClick}>Increment</button>
                </div>
            );
        }
    }
    
    ClassComponent.propTypes = {
        name: PropTypes.string.isRequired,
        age: PropTypes.number,
        onValueChange: PropTypes.func,
    };
    
    export default ClassComponent;
    
    • 函数组件
    import React from 'react'
    import './Style.css';
    function FCComponent() {
      return (
        <div className='bg-yellow center'>这是函数组件</div>
      )
    }
    
    export default FCComponent
    

    3、状态(State):

    1.是组件内部的状态。
    2.可变,通常在组件内部管理和更新。
    3.用于管理组件自身的数据和状态。

    • 类组件的state
    constructor(props) {
        super(props);
        // 初始化 state
        this.state = {
              count: 0,
               name: '',
               age: 0
            };
    }
    
    • 函数组件的state
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    const [age, setAge] = useState(0);
    

    4、属性(Props):

    1.是组件的属性,用于从父组件传递数据和回调函数。
    2.不可变,子组件不能直接修改。
    3.用于将数据和功能从父组件传递到子组件。

    function Welcome(props) {
      return <h1>Hello, {props.name}!</h1>;
    }
    

    5、生命周期方法(Lifecycle Methods):

    类组件中特定的钩子函数,用于在组件的不同阶段执行代码,如 componentDidMount、componentDidUpdate 和 componentWillUnmount。

    class ComponentA extends Component {
      constructor(props) {
        super(props);
        this.state = {
          // 初始化 state
        };
      }
    
      static getDerivedStateFromProps(nextProps, prevState) {
        // 用于根据新的 props 更新 state
        return null;
      }
    
      componentDidMount() {
        // 组件挂载后调用
      }
    
      shouldComponentUpdate(nextProps, nextState) {
        // 控制组件是否需要重新渲染
        return true;
      }
    
      static getSnapshotBeforeUpdate(prevProps, prevState) {
        // 在更新之前获取快照
        return null;
      }
    
      componentDidUpdate(prevProps, prevState, snapshot) {
        // 组件更新后调用
      }
    
      componentWillUnmount() {
        // 组件卸载之前调用
      }
    
      render() {
        return (
          <div>
            {/* 组件内容 */}
          </div>
        );
      }
    }
    ComponentA .propTypes = {
      // 定义 prop 类型
    };
    
    export default Second;
    

    6、Hooks:

    React 16.8 引入的特性,允许在函数组件中使用状态和其他 React 特性,如 useState 和 useEffect。


    dom6.png

    7、组件通讯:

    dom7.png
    pubsub使用:
    安装
    (1) npm install pubsub-js --save
    导入
    (2) import PubSub from "pubsub-js"
    
    
    class Publisher extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            num: 0
          };
        }
        componentDidMount() {  
          // 假设我们在组件挂载后发布一个事件
          setInterval(() => {
            PubSub.publish('someChannel', { message: 'Hello from Publisher!'+ this.state.num }); 
            this.setState({
              num: this.state.num + 1
            });
      
          }, 1000);
        } 
        
        render() {  
          return <div>Publisher Component</div>;  
        }  
      }  
        
      class Subscriber extends React.Component {  
        componentDidMount() {  
          // 订阅事件  
          this.token = PubSub.subscribe('someChannel', (msg, data) => {  
            console.log(data.message, msg); // 输出: Hello from Publisher!  
          });  
        }  
        
        componentWillUnmount() {  
          // 组件卸载时取消订阅,防止内存泄漏  
          PubSub.unsubscribe(this.token);
        }  
        
        render() {  
          return <div>Subscriber Component</div>;  
        }  
      }  
    

    8、上下文(Context):

    用于在组件树中传递数据,而不需要通过每层组件手动传递 props

    import React, { createContext, Component } from 'react';
    
    // 创建一个 Context 对象
    const MyContext = createContext();
    
    // 创建一个提供 Context 的组件
    class MyProvider extends Component {
        state = {
            user: {
                name: 'Alice',
                age: 30
            }
        };
    
        setUser = (name, age) => {
            this.setState({
                user: { name, age }
            });
        };
    
        render() {
            return (
                <MyContext.Provider value={{ 
                    user: this.state.user,
                    setUser: this.setUser
                }}>
                    {this.props.children}
                </MyContext.Provider>
            );
        }
    }
    
    import React, { Component } from 'react';
    
    // 创建一个消费 Context 的组件
    class ChildComponent extends Component {
        static contextType = MyContext;
    
        handleChangeUser = () => {
            const { setUser } = this.context;
            setUser('Bob', 25);
        };
    
        render() {
            const { user } = this.context;
            return (
                <div>
                    <p>User Name: {user.name}</p>
                    <p>User Age: {user.age}</p>
                    <button onClick={this.handleChangeUser}>Change User</button>
                </div>
            );
        }
    }
    
    // 创建一个消费 Context 的组件
    class Child2Component extends Component {
        static contextType = MyContext;
    
        handleChangeUser = () => {
            const { setUser } = this.context;
            setUser('Bob--22', 250);
        };
    
        render() {
            const { user } = this.context;
            return (
                <div>
                    <p>User Name: {user.name}</p>
                    <p>User Age: {user.age}</p>
                    <button onClick={this.handleChangeUser}>Change User</button>
                </div>
            );
        }
    }
    
    // 创建一个顶层父组件
    class ParentContextComponent extends Component {
        render() {
            return (
                <MyProvider>
                    <div className='center'>
                        <h1>上下文Context Component</h1>
                        <ChildComponent />
                        <br/>
                        <Child2Component />
                    </div>
                </MyProvider>
            );
        }
    }
    
    export default ParentContextComponent;
    

    9、Redux:

    一个流行的状态管理库,常与 React 一起使用,帮助管理应用的全局状态。
    由于内容比较多,下次再专门做个分享会。

    10、插槽:

    先来看一段angular的代码

    先定义一个包含插槽的组件container.component:

    <div class="parent">
      <h1>Parent Component</h1>
      <!-- 第一个插槽 -->
      <ng-content select="[header]"></ng-content>
      <hr/>
      <!-- 第二个插槽 -->
      <ng-content select="[body]"></ng-content>
      <hr/>
      <!-- 第三个插槽 -->
      <ng-content select="[footer]"></ng-content>
    </div>
    

    调用container.component,插入需要不同位置的代码

    <!-- app.component.html -->
    <app-parent>
      <div header>
        <h2>This is the Header Content</h2>
      </div>
      <div body>
        <p>This is the Body Content</p>
      </div>
      <div footer>
        <p>This is the Footer Content</p>
      </div>
    </app-parent>
    
    下面再看一下React的代码

    先定义一个包含插槽的组件container.component:

    import React, { Component } from 'react';
    
    class ParentComponent extends Component {
      render() {
        const { header, body, footer } = this.props;
        return (
          <div className="parent">
            <h1>Parent Component</h1>
            {/* 渲染不同的插槽内容 */}
            <div className="header">{header}</div>
            <hr/>
            <div className="body">{body}</div>
            <hr/>
            <div className="footer">{footer}</div>
          </div>
        );
      }
    }
    
    export default ParentComponent;
    

    将内容作为 props 传递给 ParentComponent 的不同插槽

    import React, { Component } from 'react';
    import ParentComponent from './ParentComponent';
    
    class App extends Component {
      render() {
        return (
          <ParentComponent
            header={<h2>This is the Header Content</h2>}
            body={<p>This is the Body Content</p>}
            footer={<p>This is the Footer Content</p>}
          />
        );
      }
    }
    
    export default App;
    
    

    以上是本次分享,谢谢大家。

    相关文章

      网友评论

          本文标题:React初印象

          本文链接:https://www.haomeiwen.com/subject/uwluljtx.html