zoukankan      html  css  js  c++  java
  • React框架

    React框架

    img

    React 起源于 Facebook 的内部项目,起初facebook在建设instagram(图片分享)的时候,因为牵扯到一个东西叫数据流,那为了处理数据流并且还要考虑好性能方面的问题。对市场上的各种前端MVC框架进行了研究。然后对市场上所有JavaScript MVC框架,都不满意,就决定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

    React框架特点

    image-20200831162027241

    我们以前操作dom的方式是通过document.getElementById()的方式,这样的过程实际上是先去读取html的dom结构,将结构转换成变量,再进行操作。
    而reactjs定义了一套变量形式的dom模型,一切操作和换算直接在变量中,这样减少了操作真实dom,性能真实相当的高,和主流MVC框架有本质的区别,并不和dom打交道
    React与传统MVC的关系
    React不是一个完整的MVC框架,最多可以认为是MVC中的V(View),甚至React并不非常认可MVC开发模式;React 构建页面 UI 的库。可以简单地理解为,React 将将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,就成了我们的页面。
    React Fiber

    react 16.x版本之后搞出来一个Fiber协调引擎,是为了解决浏览器渲染组件,因为是同步进行的,造成浏览器卡顿问题。

    React Fiber的方法其实很简单——分片。把一个耗时长的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。
    就比如有一桌菜,之前是你只能吃完一份才去吃另一份,用fiber算法之后,你可以同时吃几份菜,时间虽然是一样的,凡是线程不会被独占

    构建React环境

    react开发需要引入多个依赖文件:react.js、react-dom.js,babel-standalone分别又有开发版本和生产版本

    react.js:中有React对象,帮助我们创建组件等功能

    react-dom.js:中有ReactDOM对象,渲染组件的虚拟dom为真实dom的爆发功能

    babel-standalone:在编写react代码的时候会大量的使用到jsx代码,但是编译需要借助babel

    安装环境

    官网提供了很多安装方式:

    • 直接下载

    1)进入项目文件夹,在控制台运行

    npm init -y
        npm i react react-dom babel-standalone

    2)下载完成后在下面的路径中找到依赖文件,引入到html文件中

    (react/umd/react.development.js)
    (react-dom/umd/react-dom.development.js)
    (babel-standalone/babel.min.js)

    • 引用网上的链接
    <!-- 注意: 部署时,将 "development.js" 替换为 "production.min.js"。-->
    <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>

    核心概念

    元素渲染

    <!DOCTYPE html>
    <html>
      <head>
        <script src="./js/react.development.js"></script>
        <script src="./js/react-dom.development.js"></script>
        <script src="./js/babel.min.js"></script>
      </head>
      <body>
        <div id="app"></div>
          <!-- 这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel" -->
             <!-- 这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel" -->
        <script type="text/babel">
           ReactDOM.render(<div>
                    <p>Hello, world!</p>
                </div>,document.getElementById("app"))
        </script>
      </body>
    </html>

    上面代码将一个 p 标题,插入 app 节点,运行结果如下。

    image-20200831163709494

    jsx

    jsx背后的原理?
    jsx-->babel(React.createElement)--->虚拟dom(js内存对象)---> ReactDOM.render() 将虚拟dom渲染成真实dom

    jsx内部借鉴了xml一些语法规范,标签必须是闭合的、只能有一个根元素

    jsx中注释需要 {/jsx代码/}

    Babel会把jsx代码转译成一个名字React.createElement()方法进行调用

    <body>
        
        <div id="app">
        </div>
        <script type="text/babel">
            //写法一比较麻烦
            // const a = React.createElement(
            //             'div',
            //             {},
            //             React.createElement('h2',{className:'abc'},"我是h2"),
            //             React.createElement('p',{},"我是p"),
            //         );
            
            //声明变量方式
            const a = <div><h2 className='abc'>我是h2</h2><p>我是P标签</p></div>
            ReactDOM.render(a,document.getElementById("app"))
        </script>
    </body>
    渲染变量

    react中通过{}来渲染变量 (只要写js代码了,就需要通过引入{}语法)

    null | undefined | boolean 都不会在{}中进行渲染

    数组会渲染成字符串

    注意: {}中不能直接放入对象类型! json对象不能扔进去,报错!

    下列的写法是ok的

    const a = 10
            ReactDOM.render(<div>
                <p>{a}</p>
                <p>{"hello".substr(0,2)}</p>
                <p>{[1,2,3]}</p>
                <p>{function(){alert(2)}()}</p>
            </div>,document.getElementById("app"))
    事件处理
    • React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
    • 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
    <script type="text/babel">
            const app = <div><button id="btn" onClick={()=>alert('点击成功')}>点击</p>
    <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button></div> 
            ReactDOM.render(<div>{app}</div>,document.getElementById("app"))
        </script>
    Map数组

    react中遍历数组采用数组的map迭代

    注意:在map中要加key

    key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识
    虚拟dom对比的时候,加key可以避免出错。 如果不加key,当一个元素添加的时候,后面的元素就会经历卸载与重新装载的过程。
    为了避免出错。所以我们在开发中应该尽量避免用index作为key值,除非我知道index是不变的。

    <body>    
        <div id="app">
        </div>
        <script type="text/babel">  
            const arr = ["a","b","c","d"]
            ReactDOM.render(<div>
                <ul>
                    {
                        arr.map((item,index)=>{
                            return <li key={index}>{item}</li>
                        }) 
                    }
                </ul> 
            </div>,document.getElementById("app"))
        </script>
    </body>

    如果有2个数组的话,重复写上述代码代码的复用性就不好,这时我们可以进行函数封装

    <body>  
        <div id="app"></div>
        <script type="text/babel">
            var arr = ["a","b","c"]
            var arr2 = ["d","e","f"]
            //封装成函数的话,记得内部需要加return关键字!
            function showList(arr){
                return arr.map((item,index)=>{
                    return <p key={index}>{item}</p>
                })
            }
            ReactDOM.render(<div>
                    {
                        showList(arr)
                    }
                    {
                        showList(arr2)
                    }
                </div>,document.getElementById("app"))
        </script>
    </body>

    一个点击变颜色的小案例

    image-20200831170846228

    <body>
        <div id="app"></div>
        <script type="text/babel">
            //return 后面返回一段jsx代码的时候,最好加(),为了避免问题
            //需求:让第一项默认添加红色,后续点击每一项,每一项变红
            //需要我们手动的去执行render函数!
            var arr = ["a","b","c"]
            //设置一个状态变量
            var currentIndex = 0
            function showList(arr){
                return (
                    <ul>
                        {
                            arr.map((item,index)=>{
                                return <li 
                                    key={index} 
                                    onClick={()=>{currentIndex=index;render();console.log(currentIndex)}}
                                    style={{color:index===currentIndex?"red":''}}
                                >{item}</li>
                            })
                        }    
                    </ul>
                )
            }
            
            render()
            function render(){
                ReactDOM.render(<div>
                  {showList(arr)}
                </div>,document.getElementById("app"))
            }
        </script>
    </body>

    Map遍历对象

    react中不能直接遍历对象,使用 Object.keys(obj)取出数组的键再去遍历

    image-20200831171326794

    <body>  
        <div id="app"></div>
        <script type="text/babel">
            let obj = {a:1,b:2}  //Object.keys(obj)之后变成["a","b"]形式
            class App extends React.Component{
                render(){
                    return (
                        <div>
                            {
                                Object.keys(obj).map((item,index)=>{
                                    return <p key={index}>{item} : {obj[item]}</p>
                                })
                            }
                        </div>
                    )
                }
            }        ReactDOM.render(<App/>,document.getElementById("app"))
        </script>
    </body>
    设置style样式

    在jsx代码中class属性变成==》 className

    在jsx代码中style属性 ===》 style={{属性名驼峰式:属性值}}

    <style>
            .red{
                color:red;
            }
        </style>
    </head>
    <body>  
        <div id="app"></div>
        <script type="text/babel">
            const style = {backgroundColor:"yellow",transform:"rotate(30deg)"}
            ReactDOM.render(<div>
                    <p className="red" style={ style }>我是p标签...</p>
                </div>,document.getElementById("app"))
        </script>
    </body>

    组件

    如果代码多了之后,不可能一直在render方法里写,所以就需要把里面的代码提出来,定义一个变量,像这样:

    const app = <h1>欢迎进入React的世界</h1>
    ReactDOM.render(
      <div>
        { app }
      </div>
      document.getElementById('root')
    )
    函数式

    这里我们定义的方法实际上也是react定义组件的第一种方式-定义函数式组件,这也是无状态组件。

    方式一:函数式组件

    ​ const 组件名(首字母大写)=(props)=>{

    ​ return jsx表达式

    ​ }

    const App = (props) => {
        return (
        	<h1>函数组件</h1>
        )
    }
    ReactDOM.render(
      // React组件的调用方式
      <App/>,
      document.getElementById('root')
    )

    image-20200831193758701

    这样一个完整的函数式组件就定义好了。但要注意!注意!注意!组件名必须大写,否则报错。

    class组件

    ES6的加入让JavaScript直接支持使用class来定义一个类,react的第二种创建组件的方式就是使用的类的继承ES6 class是目前官方推荐的使用方式,它使用了ES6标准语法来构建,看以下代码:

    class 组件名 extends React.Component {
    render(){ //render是必不可少的钩子函数
    return jsx表达式
    }
    }

    <body>
            <div id="app">
            </div>
            <script type="text/babel">
                class App extends React.Component{
                    render(){
                        return (
                            <h1>class组件</h1>
                        )
                    }
                }
                ReactDOM.render(
        <App/>,document.getElementById("app")
                )
            </script>
        </body>

    react中数据承载

    props
    函数组件

    函数式组件中:
    通过参数props.xxx获取外部传入的属性值

    <body>    
        <div id="app"></div>
        <script type="text/babel">           
            const App = function(props){
                return (
                    <div>
                        我是app组件! --- { props.username }  --- { props.age+1 } --- {props.sex} --- {props.address}
                    </div>
                )
            }
            let obj = {
                sex:"女"
            }
            let other = {
                address:"贫民窟"
            }
            ReactDOM.render(<App {...other} sex={obj.sex} username={"张三"}  age={10} />,document.getElementById("app"))
        </script>
    </body>
    类组件

    类组件中:
    通过this.props.xxx获取外部传入的属性值

    <body>    
        <div id="app"></div>
        <script type="text/babel">      
            class App extends React.Component{
            render(){
              let {sex,username,age} = this.props;
                     return (
                         <div>
                            我是app组件! --- { username }  --- { age+1 } --- {sex} --- {this.props.address}
                        </div>
                    )
                }
             }        
            let obj = {
                sex:"女"
            }
            let other = {
                address:"贫民窟"
            }
            ReactDOM.render(<App {...other} sex={obj.sex} username={"张三"}  age={10} />,document.getElementById("app"))
        </script>
    </body>
    请用今天的努力,让明天没有遗憾。
  • 相关阅读:
    leetcode 1140. Stone Game II
    主席树
    Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)
    UVALive 3942 Remember the Word
    UVA 11235 Frequent values (RMQ )
    CodeForces
    hdu 2955 Robberies (01背包好题)
    hdu 1054 Strategic Game (简单树形DP)
    hdu 5532 Almost Sorted Array (水题)
    hdu 2089 不要62 (数位dp基础题)
  • 原文地址:https://www.cnblogs.com/cupid10/p/15617679.html
Copyright © 2011-2022 走看看