React

栏目: IOS · Android · 发布时间: 8个月前

来源: segmentfault.com

本文转载自:https://segmentfault.com/a/1190000018181685,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

网页总是一个 链接 着另一个的, React 一大优势在于每次 链接 到另一个页面上去的时候,不需要向传统页面一样,得 销毁 所有代码, 重新渲染 新页面的代码,而只在一个页面上展现新的内容—— 单页页面

React 另一个优势是,以往的 单页页面 你需要考虑哪个元素要被删除、哪个元素的行为要被修改,而我们只需要告诉 React 我们想要的最终页面的效果, React 会自动帮我们处理页面上的元素,做删除、修改等操作。

而我只知道 React 有自己的 虚拟DOM ,它会对比 虚拟DOM和真实DOM的差别 ,然后在适当的时机更新页面。至于它怎么对比的?怎么知道差别的?怎么进行修改的?我不知道,不过,对于我们,谁在乎呢?

必须首先知道的关于 React 的术语

  • JSX 语法: React 特有语法,用来搭建 虚拟DOM
  • 组件( Component ):一个个代码块,用来封装各种功能,可以类比于函数( function
  • props & status :组件的所有静态属性 & 所有动态属性

引入 React

想要使用 React ,你需要先引入:

<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> 引入了 React 的核心库 ,最后一句 <script> 引入 jsx 语法编译器 ,因为浏览器不懂 jsx 只知道 javascript ,所以,引入编译器转换为浏览器能懂的 javascript 语言

请参考 React 官方文档以获取最新版本 React 的引入: https://reactjs.org/docs/add-...

初步使用 React

并没有什么特别的技巧,先看代码,再做解释:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>React First Try</title>
    <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>
</head>
<body>
    <div id="container"></div>

    <script type="text/babel">
        var container = document.querySelector("#container");

        ReactDOM.render(
            <div>
                <p>Batman</p>
                <p>catwoman</p>
            </div>,
            container
        );
    </script>
</body>
</html>

解释:

  • 首先引入了三个 <script>
  • 新建一个元素 <div id="container"></div>
  • 我们必须在一个 <scripr type="text/babel"> 中使用 React ,请注意 <script>type
  • 像一般的 javascript 语法一样,我们先获取页面元素

    var container = document.querySelector("#container");
  • 修改 虚拟DOM ,并渲染 真实DOM

    其中, ReactDOM.render(); 就是在渲染,其含义是将第一个参数渲染到第二个参数下。而第一个参数 <div>...</div> 就是新的 虚拟DOM 的内容,可更改为我们想要的 真实DOM 结构。

    ReactDOM.render(
        <div>
            <p>Batman</p>
            <p>catwoman</p>
        </div>,
        container
    );
  • 效果、页面结构

React

React

  • 我们看到,页面中已经添加了包含两个 <p> 元素的 <div>React.render() 函数的第一个参数只能是一个标签,不能是并列的两个标签。不过一个标签里的子标签可以随便的添加,所以最好的方法就是,在外面添加一个 <div></div>

使用组件( Component

上面的方法是直接将你想要的写在 React.render() 里,通常的做法是引用组件

  • 定义一个组件

    class 组件名 extends React.Component(
        //your code
    );
  • 组件里可以添加很多功能,比如想要添加一个按钮,你只需直接写你想要的DOM结构,而不需要使用 javascript 语法: createElement()appendChild()

    class 组件名 extends React.Component(
        render(){
            return (<button>Batman</button>);
        }
    );
  • 在组件里写好你想要的东西,使用 React.render() 进行渲染

    React.render(
        <组件名/>,
        想要渲染的位置
    )
  • 完整代码可以如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>React First Try</title>
        <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>
    </head>
    <body>
        <div id="container"></div>
    
        <script type="text/babel">
            var container = document.querySelector("#container");
            
            class Myname extends React.Component{
                render(){
                    return (<button>Batman</button>);
                }
            };
    
            ReactDOM.render(
                <Myname/>,
                container
            );
        </script>
    </body>
    </html>
  • 效果、页面结构

React

React

  • 我们看到,页面上出现了我们想要的按钮,页面结构里也成功添加了 <button> 标签。 注意!!!组件名首字母必须大写!!!引用组件注意代码 <组件名/> ,一个符号都不能错的!!!

使用 props

props 用来获取组件的静态属性,可以先看下面的一个小例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>React First Try</title>
    <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>
</head>
<body>
    <div id="container"></div>

    <script type="text/babel">
        var container = document.querySelector("#container");

        class Myname extends React.Component{
            render(){
                return (<button type={this.props.buttontype}>{this.props.children}</button>);
            }
        };

        ReactDOM.render(
            <Myname buttontype="submit">Batman</Myname>
            ,
            container
        );
    </script>
</body>
</html>

不必惊慌,修改的地方只有组件的 render() 和实际渲染的 render() 两个函数。

  • 第一个 render() 添加了 <button>type 属性,该属性值指向 {this.props.buttontype} ,意思是该组件名为 buttontype 的静态属性。这个 render() 还将 <button> 的显示文字指向 {this.props.children} ,意思是该组件的子元素这个静态属性
  • 第二个 render() 函数添加了 <Myname> 的静态属性 buttontype ,和一个 text 类型的子元素 Batman
  • 结论就是: 在渲染真实DOM的时候,会创建一个 <button></button> 标签,它的 type 属性值为 submit ,文字显示为 Batman
  • 效果、页面结构,哈哈哈,没啥区别,没区别就对了:

React

React

props 的传递性

props 只能从父元素向下传递给子元素:

React

当有多个属性你想传递的时候,你的代码可能就会是这样的,会重复很多遍 {this.props.propsName}

<script>
class Me extends React.Component{
    render(){
        return (
            <div>
                <p>{this.props.props1}</p>
                <p>{this.props.props2}</p>
                <p>{this.props.props3}</p>
            </div>
        );
    }
};

class Father extends React.Component{
    render(){
        return (
            <Me props1={this.props.props1} props2={this.props.props2} props3={this.props.props3}/>
        );
    }
};

ReactDOM.render(
    <Father props1="a" props2="b" props3="c"/>,container
);
</script>

如果你不想重复很多遍繁琐的 {this.props.propsName} ,那你可以使用 扩展运算符 ... 表示取到所有的静态属性并且都使等于 {this.props.propsName} ,所以我们的代码可以稍作简化:

<script>
class Me extends React.Component{
    render(){
        return (
            <div>
                <p>{this.props.props1}</p>
                <p>{this.props.props2}</p>
                <p>{this.props.props3}</p>
            </div>
        );
    }
};

class Father extends React.Component{
    render(){
        return (
            <Me {...props}/>      //:point_left::point_left:使用扩展运算符进行简化{...props}
        );
    }
};

ReactDOM.render(
    <Father props1="a" props2="b" props3="c"/>,container
);
</script>

React 操作 CSS

此方法可以使你在 <script> 里更改、渲染 CSS 。不过使用 ReactJSX语法 会和 CSS语法 有一点点不同,就一点点┑( ̄Д  ̄)┍

因为刚开始接触,代码不难,所以直接先看示例代码吧;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>React First Try</title>
    <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>
</head>
<body>
    <div id="container"></div>

    <script type="text/babel">
        var container = document.querySelector("#container");

        class Mycss extends React.Component{
            render(){
                var letterColor = {
                    padding: 10,
                    margin: 10,
                    backgroundColor: this.props.thiscolor,
                    color: "#333",
                    display: "inline-block",
                    fontFamily: "monospace",
                    fontSize: 32,
                    textAlign: "center",
                };
                return (<div style={letterColor}>{this.props.children}</div>);
            }
        };

        ReactDOM.render(
            <div>
                <Mycss thiscolor="#58B3FF">B</Mycss>
                <Mycss thiscolor="#FF605F">a</Mycss>
                <Mycss thiscolor="#FFD52E">t</Mycss>
                <Mycss thiscolor="#49DD8E">m</Mycss>
                <Mycss thiscolor="#AE99FF">a</Mycss>
                <Mycss thiscolor="#FF6633">n</Mycss>
            </div>
            ,
            container
        );
    </script>
</body>
</html>
  • 哇!!代码怎么看上去又有这么多的改动啊!!别慌张别慌张!其实和上一小节一样,只改动了一些内容在组件的 render() 和真实渲染的 render() 两个函数里
  • 组件 render() 里首先定义了一个 虚拟CSS类 ,看上去符合 CSS语法 ,但其实呢,他是一个 JSX语法 ,仔细看,它就是一个用 JSX语法 写的神似 CSS对象 。其中的一些区别如下:

    • 它不应该有 pxpx 这种东西 JSX 会自动补充
      React
    • 它不应该有分号 ; 来表示这个属性结束了,请使用逗号 ,
      React
    • 它应该把 除了纯数字外的所有属性值 都加上引号 ""
      React
    • 它应该使用 驼峰命名法 来表示 CSS 使用连接号 - 的属性名: backgroundColor
      React
  • 所以,在遵循了所有使用 JSX语法 描述 CSS 状态的规则之后,你就可以成功的定义一个 虚拟CSS 。接着,在组件的 render() 里调用它,像这样 <div style={letterColor}>style={虚拟CSS名}
  • 在这里另一个知识点是,在定义 虚拟CSSbackgroundColor 时,它的参数值是一个变量 this.props.thiscolor ,同上一小节一样,在真实渲染 render() 的第一个参数里定义这个静态变量 <Mycss thiscolor="#58B3FF"> 。这样,就成功在 CSS (虚拟的)里调用了其它地方的变量来确定属性值。
  • 效果、页面结构:值得注意的是, React 处理的 CSS 是通过内联方式(标签中插入 style 属性)实现的

React

React

小结

这个时候,我们需要做一个小例子,来巩固下关于 组件CSS引入props 的概念

我们想要实现的效果

我们想要实现的效果就是,当你输入颜色代码,上面就能正确的展示颜色:

React

分离组件

React 的世界,一切都是组件,页面上所有的内容都是由一个个组件搭建起来的。你可以将结构划分为很小的组件,这样实现的功能就很详细。你也可以将结构划分为稍大的组件,功能就更集中。

所以,像我们这样的小应用,下面的组件划分方法就足以满足要求:

React

编写程序

在分析完结构需要分成多少组件之后,可以开始构造代码~

  • 首先,我们编写组件框架。其中每一个 class 就代表了我们分成的组件。在这里 class ColorName 表示文字部分, class Color 表示颜色显示区, class Board 表示用来承载这个应用的底板。每个组件都有一个 render() 函数用来之后渲染组件到DOM上。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Color</title>
        <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>
    </head>
    <body>
        <div id="container"></div>
    
        <script type="text/babel">
            var container = document.querySelector("#container");
    
            class ColorName extends React.Component{
                render(){
                 
                }
            };
    
            class Color extends React.Component{
                render(){
    
                }
            };
    
            class Board extends React.Component{
                render(){
    
                }
            };
    
            ReactDOM.render(
                <Board/>,container
            );
        </script>
    </body>
    </html>
  • 上述步骤等于搭完了骨架,我们需要填充肌肉。写下,最终需要每个组件分别返回什么标签:

    ColorName 组件返回一个 <p> 标签,用以展现颜色的色号

    Color 组件返回一个 <div> 标签,用来显示颜色

    Board 组件返回一个 <div> 标签,并且把上两个组件包在一起

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Color</title>
        <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>
    </head>
    <body>
        <div id="container"></div>
    
        <script type="text/babel">
            var container = document.querySelector("#container");
    
            class ColorName extends React.Component{
                render(){
                    return (<p>{this.props.colorName}</p>);
                }
            };
    
            class Color extends React.Component{
                render(){
                    return (<div id="color"></div>);
                }
            };
    
            class Board extends React.Component{
                render(){
                    return (
                        <div>
                            <Color colorName = {this.props.colorName}/>
                            <ColorName colorName = {this.props.colorName}/>
                        </div>
                    );
                }
            };
    
            ReactDOM.render(
                <Board colorName="#f7a87d"/>,container
            );
        </script>
    </body>
    </html>
  • 接下来我们只需要添加你想要的 CSS 就OK了,不过在添加 CSS 之前,我想对上一步骤简单解释:我们在渲染 真实DOM 时定义了一个静态属性 colorName="#f7a87d" ,经由组件 Board 传入组件 ColorNameColor 。最后通过每个组件各自的 render() 函数的 return 渲染在页面上。
  • 最后我们需要添加一些 CSS 帮页面穿点衣服,其中对 CSS 的引入使用了两种方法,使用 React 引入和引入外部 CSS 文件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Color</title>
        <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>
        <style>
            #board{
                width: 300px;
                height: 400px;
                /* border: 1px solid red; */
                border-radius: 3%;
                box-shadow: 3px 5px 7px 1px rgba(128,128,128,1);
            }
    
            #color{
                height: 80%;
                border-radius: 3%;
                box-shadow: 1px 1px 6px 1px rgba(128,128,128,1);
            }
        </style>
    </head>
    <body>
        <div id="container"></div>
    
        <script type="text/babel">
            var container = document.querySelector("#container");
    
            class ColorName extends React.Component{
                render(){
                    var ColorNameStyle = {
                        fontSize: "2.5em",
                        fontFamily: "sans-serif",
                        fontWeight: "bold",
                        textAlign: "center",
                        margin: 17,
                    };
    
                    return (<p style={ColorNameStyle}>{this.props.colorName}</p>);
                }
            };
    
            class Color extends React.Component{
                render(){
                    var colorStyle = {
                        backgroundColor: this.props.colorName,
                    };
    
                    return (<div style={colorStyle} id="color"></div>);
                }
            };
    
            class Board extends React.Component{
                render(){
                    return (
                        <div id="board">
                            <Color colorName = {this.props.colorName}/>
                            <ColorName colorName = {this.props.colorName}/>
                        </div>
                    );
                }
            };
    
            ReactDOM.render(
                <Board colorName="#f7a87d"/>,container
            );
        </script>
    </body>
    </html>

使用 state

以上的各个步骤可以创建一个基本的静态页面,如果想要创建一个有点动态,看上不是死气沉沉的页面,那就一定需要 state 。正如之前提到的, props 包含了所有的静态属性, state 则包含了所有用于动态展示的属性。

这时,我们需要一个例子

我们的目标

React

分离组件

外面一个黑的长方形边框;内部一个黑色的底板; #5dffff 的动态数字;三行文字

编写代码

  • 编写代码框架: Times 类表示变化的数字; Words 表示三行灰色的文字; BlackBoard 表示黑色的底板; Board 表示最外面一圈黑边框

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Lightning</title>
        <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>
    </head>
    <body>
        <div id="container"></div>
    
        <script type="text/babel">
            var container = document.querySelector("#container");
    
            class Times extends React.Component{
                render(){
                    return ();
                }
            };
    
            class Words extends React.Component{
                render(){
                    return ();
                }
            };
    
            class BlackBoard extends React.Component{
                render(){
                    return ();
                }
            };
    
            class Board extends React.Component{
                render(){
                    return ();
                }
            };
    
            ReactDOM.render(
                <Board/>
                ,container
            );
        </script>
    </body>
    </html>
  • 然后我们需要添上返回的内容,我们就只看 React 的内容

    <script type="text/babel">
        var container = document.querySelector("#container");
    
        class Times extends React.Component{
            render(){
                return (<h1>Strike Times</h1>);
            }
        };
    
        class Words extends React.Component{
            render(){
                return (
                    <div>
                        <p>lightning strike</p>
                        <p>worldwide</p>
                        <p>(since you loaded this outstanding)</p>
                    </div>
                );
            }
        };
    
        class BlackBoard extends React.Component{
            render(){
                return (
                    <div>
                        <Times/>
                        <Words/>
                    </div>
                );
            }
        };
    
        class Board extends React.Component{
            render(){
                return (
                    <div>
                        <BlackBoard/>
                    </div>
                );
            }
        };
    
        ReactDOM.render(
            <Board/>
            ,container
        );
    </script>

    React

  • Strike Times 变成动态,我们只需改变 Times 类:

    • 首先需要定义 state :必须在 constructor 内定义 this.state={}

      constructor(props){
          super(props);
          this.state = {
              strike: 0,
          };
      }
    • 使用 生命周期钩子componentDidMount 钩子里的内容会在页面渲染完成后被调用.

      在本例中,页面渲染完成后会调用一个计时器 setInterval() ,计时器中调用的函数请使用箭头函数,这样被调用的函数里的 this 才会被正确的指向当前类,其它调用方法会指向 window

      componentDidMount() {
          setInterval(() => this.addNumber(),1000);
      }
    • 定义你想调用的函数

      注意!!!如果你想修改 state 中的值,请必须使用 this.setState() 来修改!!

      addNumber(){
          this.setState({
              strike: this.state.strike + 100,
          });
      }
    • 最后,设定返回值,显示的内容为 state 中的 strike

      render(){
          return (<h1>{this.state.strike}</h1>);
      }

React

  • 加上点样式

    <script type="text/babel">
        var container = document.querySelector("#container");
    
        class Times extends React.Component{
           constructor(props){
               super(props);
               this.state = {
                   strike: 0,
               };
           }
    
            componentDidMount() {
                setInterval(() => this.addNumber(),1000);
            }
    
            addNumber(){
                this.setState({
                    strike: this.state.strike + 100,
                });
            }
    
            render(){
                var strikeStyle = {
                    margin: 0,
                    padding: "55px",
                    color: "#5dffff",
                    fontSize: "60px",
                }
            
                return (<h1 style={strikeStyle}>{this.state.strike}</h1>);
            }
        };
    
        class Words extends React.Component{
            render(){
                var words = {
                    fontFamily: "sans-serif",
                    margin: 0,
                    padding: 0,
                };
                var wordStyle = {
                    wordNormal: {
                        ...words,
                        color: "#999999",
                        fontSize: 33,
                    },
                    wordBig: {
                        ...words,
                        color: "#999999",
                        fontSize: 50,
                    },
                    wordSmall: {
                        ...words,
                        color: "#4d4d4d",
                    },
                }
    
                return (
                    <div>
                        <p style = {wordStyle.wordNormal}>lightning strike</p>
                        <p style = {wordStyle.wordBig}>worldwide</p>
                        <p style = {wordStyle.wordSmall}>(since you loaded this outstanding)</p>
                    </div>
                );
            }
        };
    
        class BlackBoard extends React.Component{
            render(){
                return (
                    <div style = {this.props.style}>
                        <Times/>
                        <Words/>
                    </div>
                );
            }
        };
    
        class Board extends React.Component{
            render(){
                var boardStyle = {
                    board: {
                        width: 300,
                        height: 400,
                        padding: 13,
                        backgroundColor: "white",
                        border: "2px solid black",
                    },
                    blackboard: {
                        height: "100%",
                        backgroundColor: "black",
                        borderRadius: "7%",
                        textAlign: "center",
                        lineHeight: "50px",
                    }
                };
    
                return (
                    <div style={boardStyle.board}>
                        <BlackBoard style = {boardStyle.blackboard}/>
                    </div>
                );
            }
        };
    
        ReactDOM.render(
            <Board/>
            ,container
        );
    </script>

React

使用 JSX

即使我们在之前的文章中已经开始使用了 JSX 这种 React 特别的语法,但是,我们还是应该为它专门开辟一个新的章节,因为, JSX 组件组件生命周期React 的三大奠基核心(哈哈哈,当然是我的个人见解)。

说到 JSX ,令人印象深刻的就是各种在 js 里添加 html 标签 和出现在各个地方的 {}

js 里添加 html 标签

在提倡 css样式js行为html标签 分离的时代,这样的设计别出心裁。主要是因为 React 的基础设施不是传统的 html标签 ,而是各个 组件 。一个组件里包含了构成页面某一部分所需要的所有的 css样式js行为html标签 。 所以,遵循这样的思路,在 js 里添加 html 标签 没什么稀奇的。

像这样:

var myname = <h1>Batman</h1>;
function functionName(){
    // your codes
    return <h1>Batman</h1>;
}
const me = (
  <div>
    <h1>Batman</h1>
    <h2>hello gotham</h2>
  </div>
);

注意!!! JSX 不能够将 多个 html 标签 直接赋给一个变量或者直接返回,需要将 多个html标签 包括在一个父元素中,就像上例第三个例子一样。

{}

js 里添加 html 标签 对我们来说已经见怪不怪了,大括号 {} 的使用才是精髓。哈哈哈~~

{} 用于在 React 中的各个地方引用各种 合理的JS表达式(valid JavaScript expression) 。大括号里可以是变量 user.username 、表达式 2+2 、函数调用 functionName(user) 等。

像这样:

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
const element = <img src={user.avatarUrl}></img>;
const element = <h1>2+2={2+2}</h1>;
function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

另外,还有双括号 {{}} 的写法,这种表达方式用于在 JSX 里内联样式。

{{}} 内的内容:

  • 对象的写法,将css里的 ; 变成 ,
  • 属性名使用驼峰写法,css里 - 后面的第一个字母大写
  • 只会生效最后一个 style ,下例中只会生效 style={gothamStyle}

    var myName = <h1 style={{color:"black"}} style={{fontSize:"25px"}} style={gothamStyle}>Batman</h1>;

像这样:

const myName = <h1 style={{color:"black",fontSize:"25px"}}>Batman</h1>;

关于更多 React 中操作 CSS ,你还可以浏览这篇文章: https://www.jianshu.com/p/850...

JSX 的优势

  • 防止 XSS (cross-site-scripting) 攻击。因为所有内容在被 React 渲染到页面上前都会先转成字符串
  • 小巧灵活。 JSX 本质就是 Javascript ,所以, JSX 可以被放在任何一个地方。再加上 JSX 里的内容非常丰富。结合 React 的设计思想, JSX 非常好用。
  • 当然 JSX 还可以撰写 css 内容,详细可以参见之前章节: React 操作 CSS

使用 JSX 的一个例子

只要使用 React 搭建网站必然需要用到 JSX ,额,虽然官方是这样表示的:

React

Well~我们还是快速的过一遍这个例子

我们要实现的目标

几个圆圈过1秒就变颜色,颜色随机从颜色库里选取

React

完整代码

其实很简单, Circle 组件负责改变颜色的行为, CreateCircle 组件负责定义样式并渲染这些圆圈。

然后因为一直是动态的,所以,使用 Circle 组件的 state ,每个一段时间 setInterval 都会调用 changeColor 函数,来改变 state 里的内容,改变之后 React 会重新渲染页面被改动的部分。

值得注意的是,在这个例子中, JSX 被运用在任何一个位置,

  • 可以被压到数组中去

    colorarray.push(<CreateCircle bgColor={colors[random]} key={i}/>)
  • 被渲染

    render(){
        return (<div>{this.state.colorArray}</div>);
    };
  • 撰写、引用 css

    class CreateCircle extends React.Component{
        render(){
            var circleStyle = {
                padding: 10,
                margin: 20,
                display: "inline-block",
                backgroundColor: this.props.bgColor,
                borderRadius: "50%",
                width: 100,
                height: 100,
            };
    
            return (<div style={circleStyle}></div>);
        }
    };

注意!!!在 React 中使用 key={} 属性来唯一标识一个组件 <CreateCircle key={i}/>

完整代码:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Lightning</title>
    <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>
</head>

<body>
    <div id="container"></div>

    <script type="text/babel">
        var container = document.getElementById("container");
        var colors = ["#393E41","#E94F37","#1C89BF","#A1D363","#85FFC7","#297373","#FF8552","#A40E4C"];

        class Circle extends React.Component{
            constructor(props){
                super(props);
                this.state = {
                    colorArray: [],
                };
            };

            changeColor(){
                var colorarray = [];
                this.setState({
                    colorArray: [],
                });
                for(var i=0;i < colors.length;i++){
                    var random = Math.floor(Math.random()*colors.length);
                    colorarray.push(<CreateCircle bgColor={colors[random]} key={i}/>)
                    this.setState({
                        colorArray: colorarray,
                    });
                }
            };

            componentDidMount(){
                setInterval(() => this.changeColor(),1000);
            };

            render(){
                return (<div>{this.state.colorArray}</div>);
            };
        };

        class CreateCircle extends React.Component{
            render(){
                var circleStyle = {
                    padding: 10,
                    margin: 20,
                    display: "inline-block",
                    backgroundColor: this.props.bgColor,
                    borderRadius: "50%",
                    width: 100,
                    height: 100,
                };

                return (<div style={circleStyle}></div>);
            }
        };
        
        ReactDOM.render(
            <Circle/>
            ,container
        )
        
    </script>
</body>

</html>

React 中的事件

事件的意义不用多说,事件是页面与用户交互的唯一途径,人机交互大部分还是通过鼠标和键盘吧,当然还有像手写板、麦克风、摄像头等设备,但截至今日前端貌似没有什么权限,不然安全性就太差了。

React 中,事件的绑定大致和原生网页相似,大概也就是 命名方式不同 this 的指向不同 这两点区别。

可以参考: https://reactjs.org/docs/hand...

React 中绑定事件

  • 直接绑定

    class Button extends React.Component{
        render(){
            return (<button onClick="console.log('Hello gotham')">Click me!</button>)
        }
    }

    WHAT??这不是和原生的一模一样吗?是呀,只是在命名上采用的是 React 喜爱的 驼峰Camel-Case 命名法,原生的都是小写。但这种方法多老式。

  • 间接绑定

    class Button extends React.Component{
        consoleLog(){
            console.log("Hello gotham");
        }
    
        render(){
            return (<button onClick={this.consoleLog}>Click me!</button>)
        }
    }

    将函数拿到外面去,然后在元素的事件上绑定这个函数,绑定的时候使用 JSX{} 并且一定加上 this ,表示绑定的是这个组件里的函数。

  • 超级间接绑定

    class Inner extends React.Component{
        render(){
            return (<button onClick={this.props.clickHandler}>Click me!</button>)
        }
    }
    
    class Outer extends React.Component{
        consoleLog(){
            console.log("Hello gotham");
        }
    
        render(){
            return (<Inner clickHandler={this.consoleLog}/>)
        }
    }

    哈哈哈,这是什么鬼?就是利用了 Reactprops ,把函数绑定在一个 props 上,本例中是 clickHandler ,然后渲染了新组件,在新组件中,可以使用 this.props 来调用这个函数。简单来说就是,将函数从 父组件 通过 props 传递到了 子组件

this 的指向

React 中,绝大部分的 this 都指向组件本身。但是,在自定义的函数中, this 是没有指向的,所以会有 this is undefined 的报错,尤其是自定义的函数需要引用函数外组件内的其它资源的时候。

React

像下面这样写是会报错的:

我们想要点击 Hello gotham 按钮调用 greeting 函数, greeting 函数会调用 gotham 函数打印 Hello gotham 字样。但是, greeting 函数里的 this 没有指向,所以会出现上面的报错。

class Welcome extends React.Component{
    gotham(){
        console.log("Hello gotham");
    }    

    greeting(){
        this.gotham();
    }

    render(){
        return (<button onClick={this.greeting}>Hello gotham<button/>)
    }
}

所以,如果想要在自定义函数中调用同组件其它资源,你有下面3中方法来绑定 this

  • constructor 中绑定

    class Welcome extends React.Component{
        constructor(props){
            super(props);
            this.greeting = this.greeting.bind(this);    :point_left:这句是绑定
        }
    
        gotham(){
            console.log("Hello gotham");
        }    
    
        greeting(){
            this.gotham();
        }
    
        render(){
            return (<button onClick={this.greeting}>Hello gotham<button/>)
        }
    }
  • 内联式绑定

    class Welcome extends React.Component{
        gotham(){
            console.log("Hello gotham");
        }    
    
        greeting(){
            this.gotham();
        }
    
        render(){
                                                  :point_down::point_down::point_down::point_down::point_down::point_down:这里是绑定
            return (<button onClick={this.greeting.bind(this)}>Hello gotham<button/>)
        }
    }
  • 内联式箭头函数绑定

    class Welcome extends React.Component{
        gotham(){
            console.log("Hello gotham");
        }    
    
        greeting(){
            this.gotham();
        }
    
        render(){
                                     :point_down::point_down::point_down::point_down::point_down::point_down::point_down::point_down::point_down::point_down::point_down::point_down:这里是绑定
            return (<button onClick={(e) => this.greeting(e)}>Hello gotham<button/>)
        }
    }

关于绑定 this 还可以参考: https://www.jianshu.com/p/95a...

合成事件 SyntheticEvent

React 中的合成事件可以对应为通常函数中的事件对象 event

function gotham(event){
    // your codes
}

e...这个功能有点多,你可以自己打印出来看看呀,或者看看官方文档: https://reactjs.org/docs/even...

这里只贴出来关于鼠标和键盘事件:

  • 鼠标事件

    boolean   altKey
    boolean   ctrlKey
    boolean   shiftKey
    boolean   metaKey
    number    button
    number    buttons
    number    clientX
    number    clientY
    boolean   getModifierState(key)
    number    pageX
    number    pageY
    DOMEventTarget   relatedTarget
    number    screenX
    number    screenY

    适用于如下事件:

    onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp
  • 键盘事件

    boolean  altKey
    number   charCode
    boolean  ctrlKey
    boolean  getModifierState(key)
    string   key
    number   keyCode
    string   locale
    number   location
    boolean  metaKey
    boolean  repeat
    boolean  shiftKey
    number   which

    适用于如下事件:

    onKeyDown onKeyPress onKeyUp

关于事件的小例子

我们的目标

点击加号按钮数字加1,按住shift点击加号,数字加10

React

实现思路

shift

抛开样式的完整代码

其它的无关紧要,注意 Show 组件内的 increase 函数,我们可以看到 合成事件 e.shiftKey {this.increase.bind(this)} 的使用

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

<head>
    <meta charset="UTF-8">
    <title>react-event</title>
    <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>
</head>

<body>
    <div id="container"></div>

    <script type="text/babel">
        var container = document.querySelector("#container");

        class Button extends React.Component{
            render(){
                return (<button onClick={this.props.clickHandler}>+</button>)
            }
        }

        class Show extends React.Component{
            constructor(props){
                super(props);
                this.state = {
                    number: 0,
                };
            }

            increase(e){
                var num = this.state.number;
                if(e.shiftKey){
                    num += 10;
                }else{
                    num += 1;
                }
                this.setState({
                    number: num,
                });
            }

            render(){
                return (
                    <div>
                        <p>{this.state.number}</p>
                        <Button clickHandler={this.increase.bind(this)}/>
                    </div>
                )
            }
        }

        class Board extends React.Component{
            render(){
                return (
                    <div>
                        <Show/>
                    </div>
                );
            }
        };

        ReactDOM.render(
            <Board/>,
            container
        )
    </script>
</body>

</html>

组件的生命周期 Lifecycle

React 创造出来组件,同时也给组件配上了生命周期,用来更好的控制组件,这也是 React 的一大优势。

组建的生命周期可以参考这个: https://reactjs.org/docs/reac... 。往下多翻翻~~

这个参考资料也非常棒: https://www.w3cplus.com/react...

常用生命周期

componentDidMount()
componentDidUpdate()
componentWillUnmount()

不常用且慎用的生命周期

shouldComponentUpdate()
static getDerivedStateFromProps()
getSnapshotBeforeUpdate()
static getDerivedStateFromError()
componentDidCatch()

消失的生命周期

消失的生命周期不理他。

React Router

官方文档: https://reacttraining.com/rea...

github: https://github.com/ReactTrain...

React Router 就把他看作是一个插件吧,中文名: React 路由


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

关注码农网公众号

关注我们,获取更多IT资讯^_^


为你推荐:

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入React技术栈

深入React技术栈

陈屹 / 人民邮电出版社 / 2016-11-1 / CNY 79.00

全面讲述React技术栈的第一本原创图书,pure render专栏主创倾力打造 覆盖React、Flux、Redux及可视化,帮助开发者在实践中深入理解技术和源码 前端组件化主流解决方案,一本书玩转React“全家桶” 本书讲解了非常多的内容,不仅介绍了面向普通用户的API、应用架构和周边工具,还深入介绍了底层实现。此外,本书非常重视实战,每一节都有实际的例子,细节丰富。我从这......一起来看看 《深入React技术栈》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具