第四阶段笔记 React

  • Post author:
  • Post category:其他


1.通过dom向页面添加一个div

<body>

<div id="root"></div>

<script>
    /*
    *   React就是用来代替DOM的
    * */

    // 通过DOM向页面中添加一个div
    // 创建一个div
    const div = document.createElement('div'); // 创建一个dom元素
    //向div中设置内容
    div.innerText = '我是一个div';
    //获取root
    const root = document.getElementById('root');
    //将div添加到页面中
    root.appendChild(div);
</script>

</body>

2.通过React向页面添加一个div

// 使用函数创建react-dom对象


<body>
<div id='root'></div>
<script>
 // 通过React向页面中添加一个div
    /*
    *   React.createElement()
    *       - 用来创建一个React元素
    *       - 参数:
    *           1. 元素名(组件名)
    *           2. 元素中的属性
    *           3. 元素的子元素(内容)
    * */

    // 创建元素 用核心包
    // 第一个是标签名 第二个是标签上的属性 第三个是标签体
    const div = React.createElement('div', {}, '我是React创建的div'); // 创建一个React元素,然后通过虚拟dom去转换
  // 若此处 createElement 第三个参数是一个数组的话,需要给元素添加 key 属性
  // key 属性是一个唯一值 不重复即可
  // React.createElement('span', {key: '2'}, 'hello world')

// react元素要和react元素一起,不能和dom对象一起,要进行转换
// 错误 let root=document.getElementById('root')

    // 用reactdom包来获取根元素对应的react元素
    // 获取根元素对应的React元素
    //ReactDOM.createRoot() 用来创建React根元素,需要一个DOM元素作为参数
   const root = ReactDOM.createRoot(document.getElementById('root'));

    // 将div渲染到根元素中
    root.render(div);



</script>
</body>

3.三个API

<body>
<button id="btn">我是按钮</button>
<div id="root"></div>

<script>
    /*
    * React.createElement()
    *   - 用来创建一个React元素
    *   - 参数:
    *        1.元素的名称(html标签必须小写),大写当组件处理,dom里document.时是可以大写的
    *        2.标签中的属性
    *           - class属性需要使用className来设置
    *           - 在设置事件时,属性名需要修改为驼峰命名法
    *       3.元素的内容(子元素)
    *   - 注意点:
    *       React元素最终会通过虚拟DOM转换为真实的DOM元素(native是转换为原生)
    *       React元素一旦创建就无法修改,只能通过新创建的元素进行替换
    *
    *
    * */

    // 创建一个React元素
    const button = React.createElement('button', {
        type: 'button',
        className: 'hello',
        //驼峰命名法  绑定事件, 后面是一个函数
        onClick: () => {
            alert('你点我干嘛')
        }
    }, '点我一下');

    // 创建第一个div
    const div = React.createElement('div', {}, '我是一个div', button);

    // 获取根元素
    const root = ReactDOM.createRoot(document.getElementById('root'));

    // 将元素在根元素中显示
    root.render(div);

    // 获取按钮对象
    const btn = document.getElementById('btn');
    btn.addEventListener('click', ()=>{
        // 点击按钮后,修改div中button的文字为click me
        const button = React.createElement('button', {
            type: 'button',
            className: 'hello',
            onClick: () => {
                alert('你点我干嘛')
            }
        }, 'click me');

        // 创建一个div
        const div = React.createElement('div', {}, '我是一个div', button);

        // 修改React元素后,必须重新对根元素进行渲染
        // 当调用render渲染页面时,React会自动比较两次渲染的元素,只在真实DOM中更新发生变化的部分
        //      没发生变化的保持不变
        root.render(div);

    // 将元素在根元素中显示
    /*
    *   root.render()
    *       - 用来将React元素渲染到根元素(空标签)中
    *       - 根元素中所有的内容都会被删除,被React元素所替换
    *       - 当重复调用render()时,React会将两次的渲染结果进行比较,
    *           它会确保只修改那些发生变化的元素,对DOM做最少的修改(不会动根节点,只会动它里面的子元素不同的地方)
    *
    * */
    });
</script>

</body>

4.两种方式

使用JSX创建React对象

两种方式:
       JSX
 
       JSX就是React.createElement()的语法糖(等价)

       JSX在执行之前都会被babel转换为js代码

    //第一种:
    // 创建一个React元素 <button>我是按钮</button>
    // 命令式编程(告诉他一步一步去怎么买水)
    // const button = React.createElement('button', {}, '我是按钮');

    //第二种:
    // 声明式编程,结果导向的编程((直接要孩子去买水,怎么买水不管)
    // 在React中可以通过JSX(JS扩展)来创建React元素,JSX需要被翻译为JS代码,才能被React执行
    // 要在React中使用JSX,必须引入babel来完成“翻译”工作
    // const button = <button>我是按钮</button>; // React.createElement('button', {}, '我是按钮');

五.基本脚手架

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>JSX</title>
    <!-- react核心库 -->
    <script src="script/react.development.js"></script>
    <!--  -->
    <script src="script/react-dom.development.js"></script>
<!-- 引入babel 翻译jsx成js-->
    <script src="script/babel.min.js"></script>
</head>
<body>
<div id="root"></div>

<!--设置js代码被babel处理-->
<script type="text/babel">
 // jsx 使用 圆括号 声明多行的 react-dom 对象
    const div = (<div>
        我是一个div
        <button>我是按钮</button>
    </div>)
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(div);

</script>
</body>
</html>

六.JSX的注意事项

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>JSX的注意</title>
    <script src="script/react.development.js"></script>
    <script src="script/react-dom.development.js"></script>
    <!-- 引入babel -->
    <script src="script/babel.min.js"></script>
</head>
<body>
<div id="root"></div>

<script type="text/babel">
    /*
    *   JSX的注意事项
    *       1. JSX不是字符串,不要加引号
    *       2. JSX中html标签应该小写,React组件应该大写开头
    *       3. JSX中有且只有一个根标签(最外层只能有一个div)
    *       4. JSX的标签必须正确结束(自结束标签必须写/)
    * <input/>
    *       5. 在JSX中可以使用{}嵌入表达式
    *              - 有值的语句的就是表达式
    *       6. 如果表达式是空值、布尔值、undefined,将不会显示
    *       7. 在JSX中,属性可以直接在标签中设置
    *           注意:
    *               在设置事件时,属性名需要修改为驼峰命名法
    *               class需要使用className代替
    *               style中必须使用对象设置
    *                   style={{background:'red'}}
    // 定义样式对象
     *          let myStyle = {
    *           width: '100px',
    *           height: '100px',
    *           backgroundColor: '#f00'
    *           }
    *           <div style={myStyle}></div>
    *
    * */
{/*style必须使用对象{}*/}
    function fn() {
        return 'hello';
    }

    const name = '孙悟空';

    const div = <div
        id="box"

        onClick={() => {
            alert('哈哈')
        }} className="box1"

        style={{backgroundColor: "yellowgreen", border: '10px red solid'}}
    >
        我是一个div
        <ul>
            <li>列表项</li>
        </ul>

        <input type="text"/>
{/*有值就能用花括号*/}
        <div>
            // {name} <br/>shi 
            {1 + 1} <br/>
            {fn()} <br/>
            {/* 如果表达式是空值、布尔值、undefined,将不会显示*/}
            {NaN} <br/>
            {/*{if(){...}}这里就是个语句但没有值*/}

            
        </div>
    </div>;

    // alert(div);


    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(div);

</script>
</body>
</html>

7.渲染列表

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>渲染列表</title>
    <script src="script/react.development.js"></script>
    <script src="script/react-dom.development.js"></script>
    <!-- 引入babel -->
    <script src="script/babel.min.js"></script>
</head>
<body>
<div id="root"></div>

<script type="text/babel">

    const name = '孙悟空';
    const lang = 'cn';

    /*
    *   {} 只能用来放js表达式,而不能放语句(if for)
    *       在语句中是可以去操作JSX
    * */
    // const div = <div>Hello {name}</div>;

    let div;

    if(lang === 'en'){
        div = <div>hello {name}</div>;
    }else if(lang === 'cn'){
        div = <div>你好 {name}</div>;
    }

    const data = ['孙悟空', '猪八戒', '沙和尚'];

    /*
        <ul>
             <li>孙悟空</li>
             <li>猪八戒</li>
            ...
        </ul>

        // 新数组
        [<li>孙悟空</li>, <li>猪八戒</li>, <li>沙和尚</li>]
    * */


    // 第一种。
    // 为了保留原数组创建一个新数组
    // const arr = [];

    // 遍历data
    // for(let i=0; i<data.length; i++){
    //     arr.push(<li>{data[i]}</li>);
    // }



    // 第二种:直接用map方法返回一个新数组
    // map()
    //     *       - 可以根据原有数组返回一个新数组
    //     *       - 需要一个回调函数作为参数,回调函数的返回值会成为新数组中的元素
    //     *       - 回调函数中有三个参数:
    //     *           第一个参数:当前元素
    //     *           第二个参数:当前元素的索引
    //     *           第三个参数:当前数组
    // const arr = data.map(item => <li>{item}</li>);


    // 将arr渲染为一个列表在网页中显示
    // jsx中会自动将数组中的元素在页面中显示
    // const list = <ul>{arr}</ul>;

    const list = <ul>{data.map(item => <li>{item}</li>)}</ul>;

    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(list);

</script>
</body>
</html>

8.虚拟dom

// 发生变化的会变颜色,两两对比,改变的在原生dom里变

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>虚拟DOM</title>
    <script src="script/react.development.js"></script>
    <script src="script/react-dom.development.js"></script>
    <script src="script/babel.min.js"></script>
</head>
<body>
<button id="btn">点我一下</button>
<hr>
<div id="root"></div>

<script type="text/babel">

    //创建一个数据
    const data = ['孙悟空', '猪八戒', '沙和尚'];

    // 创建列表
    const list = <ul>
        {/*data.map(item => <li key={item}>{item}</li>)*/}
        {/*map最后返回的数组*/}
        {data.map((item, index) => <li key={index}>{item}</li>)}
    </ul>;

    // 获取根元素
    const root = ReactDOM.createRoot(document.getElementById('root'));
    // 渲染元素
    root.render(list);

    /*
    *   在React我们操作的元素被称为React元素,并不是真正的原生DOM元素,
    *       React通过虚拟DOM 将React元素 和 原生DOM,进行映射,虽然操作的React元素,但是这些操作最终都会在真实DOM中体现出来
    *       虚拟DOM的好处:
    *           1.降低API复杂度
    *           2.解决兼容问题
    *           3.提升性能(减少DOM的不必要操作)
    *
    *   每当我们调用root.render()时,页面就会发生重新渲染
    *       React会通过diffing算法,将新的元素和旧的元素进行比较
    *       通过比较找到发生变化的元素,并且只对变化的元素进行修改,没有发生的变化不予处理
    * */
    document.getElementById('btn').onclick = function (){
        // 重新渲染页面
        //创建一个数据
        const data = ['唐僧', '孙悟空', '猪八戒', '沙和尚'];
        // 创建列表
        const list = <ul>
            {/*data.map(item => <li key={item}>{item}</li>)*/}
            {data.map((item, index) => <li key={index}>{item}</li>)}
        </ul>;
        // 渲染元素
        root.render(list);

        /*
        *   旧数据
        *       ul
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *  新数据
        *       ul
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *   比较两次数据时,React会先比较父元素,父元素如果不同,直接所有元素全部替换
        *       父元素一致,在去逐个比较子元素,直到找到所有发生变化的元素为止
        *   上例中,新旧两组数据完全一致,所以没有任何DOM对象被修改
        *
        *
        * 旧数据
        *       ul
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *  新数据
        *       ul
        *           li>tom
        *           li>猪八戒
        *           li>沙和尚
        *
        *  上例中,只有第一个li发生变化,所以只有第一个li被修改,其他元素不变
        *
        *  当我们在JSX中显示数组中,数组中每一个元素都需要设置一个唯一key,否则控制台会显示红色警告
        *       重新渲染页面时,React会按照顺序依次比较对应的元素,当渲染一个列表时如果不指定key,同样也会按照顺序进行比较,
        *       如果列表的顺序永远不会发生变化,这么做当然没有问题,但是如果列表的顺序会发生变化,这可能会导致性能问题出现
        *
        *
        *   旧数据
        *       ul
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *   新数据
        *       ul
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *           li>唐僧
        *
        *   上例中,在列表的最后添加了一个新元素,并没有改变其他的元素的顺序,所以这种操作不会带来性能问题
        *
        *
        *
        *   旧数据
        *       ul
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *   新数据
        *       ul
        *           li>唐僧
        *           li>孙悟空
        *           li>猪八戒
        *           li>沙和尚
        *
        *   上例中,在列表的最前边插入了一个新元素,其他元素内容并没有发生变化,
        *       但是由于新元素插入到了开始位置,其余元素的位置全都发生变化,而React默认是根据位置比较元素
        *       所以 此时,所有元素都会被修改
        *
        *   为了解决这个问题,React为列表设计了一个key属性,
        *       key的作用相当于ID,只是无法在页面中查看,当设置key以后,再比较元素时,
        *       就会比较相同key的元素,而不是按照顺序进行比较
        *   在渲染一个列表时,通常会给列表项设置一个唯一的key!!!!!!!!!!来避免上述问题
        *       (这个key在当前列表中唯一即可)
        *       注意:
        *           1.开发中一般会采用数据的id作为key
        *           2.尽量不要使用元素的index作为key
        *               索引会跟着元素顺序的改变而改变,所以使用索引做key跟没有key是一样的
        *                   唯一的不同就是,控制台的警告没了
        *               当元素的顺序不会发生变化时,用索引做key也没有什么问题
        *   旧数据
        *       ul
        *           li(key=孙悟空)>孙悟空
        *           li(key=猪八戒)>猪八戒
        *           li(key=沙和尚)>沙和尚
        *   新数据
        *       ul
        *           li(key=唐僧)>唐僧
        *           li(key=孙悟空)>孙悟空
        *           li(key=猪八戒)>猪八戒
        *           li(key=沙和尚)>沙和尚
        * */
    };



</script>
</body>
</html>



版权声明:本文为weixin_44777648原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。