React

Reatc

JSX语法

jsx是一种JavaScript语法的拓展言语,在React中官方也引荐运用jsx形貌用户界面,运用起来会比较快速而且易读

jsx不是一门新的言语,可以明白为是一种语法糖,作用就是可以让我们越发直观的在js中建立html标签,jsx终究照样会被编译为JavaScript语法,比方我们看一段jsx代码:

/*jsx*/
ReactDOM.render(
    <div className="wrap">
        <h3>hello world</h3>
    </div>,
    document.querySelector("#root")
)

上面的jsx语法终究会被编译为JavaScript语法,中心就是经由历程一个React.createElement的要领来转化,转换后就是下面这段代码

   ReactDOM.render(
          React.createElement(
              'div',
              {className:'wrap'},
              '',
              React.createElement(
                  'h1',
                  null,
                  'hello world'
              )
          ),
          document.querySelector("#root")
    )

比较两段代码就可以看出来运用js语法来写的话着实不够精练,所以我们一般照样运用jsx的语法

在运用jsx的时刻,须要注重几个点

  1. 在运用jsx的处所,要注重我们的代码不能被JavaScript引擎直接剖析,所以要在为script标签设置迥殊的type属性, 阻挠JavaScript引擎的剖析

    <script type="text/react"></script>
  2. 在jsx中只能有一个根节点,假如存在多个根节点会报错,jsx同时也可以举行标签的嵌套

    ReactDOM.render(
        <div> /*根节点*/
            <p>hello world</p>
        </div>,
        document.querySelector("#root")
    )
  3. 在jsx中,我们虽然写的时刻看起来比较像是直接写html,但现实上照样JavaScript,所以须要运用JavaScript的语法,比方我们在为标签增加class属性时,不能写class,而是要运用JavaScript语法的className,如许才被准确的剖析

    ReactDOM.render(
        <div className="wrap">
        </div>,
        document.querySelector("#root")
    )

    一样的其他一些属性也须要转化为驼峰写法,如tabindex 则对应着 tabIndex

  4. 在jsx中运用单标签,须要在结尾处运用/>,不然不可以被准确的剖析

    ReactDOM.render(
        <div>
            <img src="1.png"/>
        </div>,
        document.querySelector("#root")
    )
  5. 在jsx中可以恣意的运用JavaScript的表达式,然则须要将表达式安排在{}中

    const obj = {
        name: "tom",
        age: (age) => {
            return age;
        }
    }
    ReactDOM.render(
        <div>
            <p>我是{obj.name},岁数是{obj.age(18)},2+2是{3 + 5},0>1的效果是{0 > 1 ? "true" : "false"}</p>
        </div>,
        document.querySelector("#root")
    )
    /*编译效果*/
    //我是tom,岁数是18,2+2是8,0>1的效果是false

    由于jsx自身就是JavaScript,所以我们也可以经由历程前提推断来决议掌握模板的内容

    const obj = {
        name: "tom",
        age: (age) => {
            return age;
        }
    };
    
    function judgment(user) {
    
        let component;
        component = user ?
            <div>
                <p>我是{obj.name},岁数是{obj.age(18)},2+2是{3 + 5},0>1的效果是{0 > 1 ? "true" : "false"}</p>
            </div> :
            <div>
                涌现错误了哦
            </div>
    
        return component;
    }
    ReactDOM.render(
        judgment(true),
        document.querySelector("#root")
    )

掌握款式

React中并没有供应其他框架中的比方ng-show、v-if等敕令,这些都是须要我们本身手动去写的

  1. 掌握元素的显现/隐蔽

    class Control extends React.Component {
        constructor(...args) {
            super(...args);
            
            this.state = {
                flag: "block"
            }
        }
    
        fn() {
            this.setState({
                flag: this.state.flag == "block" ? "none" : "block"
            })
        }
    
        render() {
            return <div onClick={this.fn.bind(this)}>
                <button>显现/隐蔽</button>
                <div className="box" style={{display: this.state.flag}}>
                </div>
            </div>
        }
    }
    
    ReactDOM.render(
        <Control/>,
        document.querySelector("#root")
    )
  2. 掌握class款式

    class Control extends React.Component {
        constructor(...args) {
            super(...args);
    
            this.state = {
                flag: true
            }
        }
    
        fn() {
            this.setState({
                flag:!this.state.flag
            })
        }
    
        render() {
            return <div>
                    <p className={this.state.flag?'red size':'yellow'} onClick={this.fn.bind(this)}>是不是衬着</p>
                </div>
        }
    }
    ReactDOM.render(
        <Control/>,
        document.querySelector("#root")
    )

在现实开辟中上面的要领都不是很直观,引荐运用classnames库

前提推断
class Control extends React.Component {
    constructor(...args) {
        super(...args);

        this.state = {
            flag: false
        }
    }

    fn() {
        this.setState({
            flag:!this.state.flag
        })
    }

    render() {
        return <div onClick={this.fn.bind(this)}>
                <p>是不是衬着</p>
                {
                    this.state.flag
                        ? <div className="box"></div>
                        : null
                }
            </div>

    }
}

ReactDOM.render(
    <Control/>,
    document.querySelector("#root")
)

组件

组件这个观点如今也是异常流行了,假如之前没有运用过其他框架的话可以用一个相对比较浅显的例子来明白组件的观点,Moto之前推出过好几款模块化的手机,该手机包含屏幕,处置惩罚器,内存,电池,摄像优等,都支撑自在替换拼装,然后组装成一个完全的手机

《React》

如今我们一样可以应用框架,将一个页面中分为导航栏,轮播图,列表等差别的模块,然后我们离别写这些模块的代码,在须要运用的页面将须要的模块自在举行拼装,这些模块就是我们说的组件

在React中有两种定义组件的体式格局

  1. 运用函数定义组件

    function Hello() {
        return <div> hello world</div>
    }
    
    ReactDOM.render(
        Hello(),
        document.querySelector("#root")
    )
  2. 运用类定义组件

    class Hello extends React.Component {
        render() {
            return <div>hello world</div>
        }
    }
    
    ReactDOM.render(
        <Hello/>,
        document.querySelector("#root")
    )

    注重,运用组件时,组件称号肯定如果大写字母开首的,不然的话会被认为是一般的html文本举行剖析,同时也须要注重的是组件内只允许有一个根元素

组件的嵌套

在React中,组件之间是可以嵌套运用的

class Hello extends React.Component {
    render() {
        return <div>hello</div>
    }
}

class Wrold extends React.Component {
    render() {
        return <div>
            <Hello />
            <h3>world</h3>
        </div>
    }
}

ReactDOM.render(
    <Wrold/>,
    document.querySelector("#root")
)

容器类组件

这个观点类似于Vue中的插槽,假如没有Vue学问的可以将这个明白为在在运用某个组件时我们在该组件内插进去一些DOM元素,而且要保证这些DOM元素可以被准确衬着

props.children
class FancyBorder extends React.Component {
    render() {
        return (
            <div className="box">
                {this.props.children}
            </div>
        )
    }
}
ReactDOM.render(
    <FancyBorder>
        <p>Lorem ipsum dolor sit amet.</p>
        <p>Lorem ipsum dolor.</p>
    </FancyBorder>,
    document.querySelector("#root")
)

这里就借用一下Vue的观点,我们将组件中设定了{this.props.children} 的部份称为插槽

在须要插进去来自挪用者的DOM的部份写入{props.children},以后挪用者插进去的代码就会在我们写入了{props.children}的位置上被展现

我们此时可以打印一下props.children,可以发明获得的是一个数组的效果

《React》

所以我们可以有别的的一种情势插进去DOM,就是经由历程挪用props.children内差别下标值来对应衬着差别的元素

class FancyBorder extends React.Component {
    handleSlot(){
        console.log(this.props.children)
    }
    render() {
        return (
            <div className="box" onClick={this.handleSlot.bind(this)}>
                <div className="child">
                    {this.props.children[0]}
                </div>
                {this.props.children[1]}
            </div>
        )
    }
}
ReactDOM.render(
    <FancyBorder>
        <p>Lorem ipsum dolor sit amet.</p>
        <p>Lorem ipsum dolor.</p>
    </FancyBorder>,
    document.querySelector("#root")
)
指定进口

假如在组件内有多个插槽而且我们想要指定某一段代码在插进去的时刻插进去到组件的指定的插槽,运用下标值得体式格局能够不是那末轻易,这个时刻须要我们商定一个针对指定插槽的属性

class FancyBorder extends React.Component {
    render() {
        return (
            <div className="box">
                <div className="child">
                    {this.props.one}
                </div>
                {this.props.two}
            </div>
        )
    }
}
ReactDOM.render(
    <FancyBorder
        one={
            <p>Lorem ipsum dolor sit amet.</p>
        }
        two={
            <p>Lorem ipsum dolor.</p>
        }
    />,
    document.querySelector("#root")
)

组件之间的通讯

父组件通报信息到子组件
class Child extends React.Component {
    render() {
        return <div>hello {this.props.name}</div>
    }
}

class Parent extends React.Component {
    render() {
        return <div>
            <Child name="world"/>
        </div>
    }
}

ReactDOM.render(
    <Parent/>,
    document.querySelector("#root")
)

props要领时官方供应的接口,我们在运用组件时,在援用子组件处,将要通报的内容以设置属性的体式格局增加到子组件,在子组件中经由历程this.props[父组件设置的属性名]的花样就可以获取到父组件通报的信息,经由历程props可以通报字符串、数字、对象、数组、函数 ,子组件在可以经由历程this.props来检察当前一切吸收到的值

通报对象
class Child extends React.Component {
    click(e) {
        console.log(this.props.data,"child");
        e.stopPropagation();
    }
    render() {
        return <div className="child" onClick={this.click.bind(this)}>hello {this.props.data.name}</div>
    }
}
class Parent extends React.Component {
    constructor() {
        super();
        this.state = {
            obj: {
                name: "tom",
                age: 18
            }
        }
    }
    click() {
        console.log(this,"parent")
    }
    render() {
        return <div className="parent" onClick={this.click.bind(this)}>
            <Child data={this.state.obj}/>
        </div>
    }
}
ReactDOM.render(
    <Parent/>,
    document.querySelector("#root")
)
通报事宜
class Child extends React.Component {
    render() {
        return <div className="child" onClick={this.props.data.bind(this)}></div>
    }
}

class Parent extends React.Component {
    click(e) {
        console.log(this)
        e.stopPropagation()
    }

    render() {
        return <div className="parent" onClick={this.click.bind(this)}>
            <Child data={this.click}/>
        </div>
    }
}
ReactDOM.render(
    <Parent/>,
    document.querySelector("#root")
)

通报事宜的时刻可以经由历程bind转变我们最初事宜的this的指向,这里我们看打印的效果,this的指向在child中指向的是child组件

状况提拔

状况提拔这个观点实在可以明白为我们在其他框架中运用的姜子组件的信息通报给父组件的一个历程,然则在react中并没有供应直接的要领,须要我们本身举行处置惩罚,完成的代码以下:

class Child extends React.Component {
    click(i,e) {
        i++;
        this.props.P_click(i);
         e.stopPropagation();
    }
    render() {
        return <div className="child" 
        onClick={this.click.bind(this,this.props.index)}>
               </div>
    }
}

class Parent extends React.Component {
    constructor() {
        super();
        this.state = {
            index: 1
        }
        this.P_Click = this.P_Click.bind(this)
    }

    change(data) {
        this.setState({
            index: data
        });
    }
    render() {
        return <div className="parent">
            {this.state.index}
            <Child P_click={this.change} index={this.state.index}/>
        </div>
    }
}

ReactDOM.render(
    <Parent/>,
    document.querySelector("#root")
)

我们起首来讲一下也许的思绪

  • 在父组件中设置一个要领change,在该要领中设置转变我们指定的变量值的处置惩罚

    change(data) {
        this.setState({
            index: data
        });
    }
  • 将该要领通报给子组件,同时也将我们要要转变的父组件的值通报给子组件

     <Child P_click={this.change} index={this.state.index}/>
  • 在子组件操纵时,比方点击时,挪用我们在父组件中传入的change要领,并转变由父组件发送过来的数据(index),回传给change要领

    <div className="child" onClick={this.click.bind(this,this.props.index)}></div>
    click(i,e) {
        i++;
        this.props.P_click(i)
        e.stopPropagation();
    }
  • change要领被挪用,经由历程this.setState相应的转变了父组件中index值

可以看出来确切很贫苦,由于没有像vue那样供应$emit要领,所以须要我们本身迂回写一系列操纵,包含假如我们想要在同级的组件之间通报数据,我们须要 子组件数据 => 父组件 => 子组件兄弟组件

引荐运用Redux来举行组件之间的数据通报

相应式的更新数据

生命周期

《React》

吸收要求数据安排位置

组件初次衬着时要求的数据处置惩罚应当安排在componentDidMount ,componentDidMount是指第一次插进去DOM终了,不管在同步或许异步的状况下都只会触发一次,而且在16.3以后,react最先异步衬着页面,在异步衬着的状况下,componentWillMount中写的要领能够会被屡次挪用,而且能够会致使内存走漏的题目,而且在官方申明中componentDidMount并没有存在比componentWillMount的慢一点的状况,componentDidMount会马上实行,在实行以后会马上实行render要领对页面举行衬着

下面是一官方关于该题目的诠释

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.

轮回遍历
class HelloWord extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            list: []
        }
        this.add = this.add.bind(this)
    }

    componentDidMount() {
        this.setState({
            list: [1, 2]
        })
    }

    render() {
        return <div>
            <p>列表元素:</p>
            <ul>
                {
                    this.state.list.map((item, index) => (
                        <li>{item}</li>
                    ))
                }
            </ul>
            <button onClick={this.add}>点击增加一个列表元素</button>
        </div>
    }

    add() {
        this.state.list.push(parseInt(Math.random() * 1000))
        this.setState({
            list: this.state.list
        })
    }
}

ReactDOM.render(
    <HelloWord/>,
    document.querySelector("#root")
)
key

在实行上诉代码以后,我们会看到一行报错

react.js:369 Warning: Each child in an array or iterator should have a unique “key” prop.Check the render method of
Lists.

这是React提醒须要在为我们经由历程遍历衬着的li增加key值,采纳以下操纵

<li key={index}>{item}</li>

React是不会去衬着之前已存在的元素,这也是React的高效性的缘由之一,key值可以协助React辨认那些元素发生了变化,那些没有变化,从而使React在衬着时保存那些之前已被衬着的元素

照样上面的代码,我们翻开掌握台,在为第一个li增加一个暂时的color,然后点击增加按钮,可以发明这个li的款式依旧被坚持了,申明React没用从新衬着该元素

《React》

在设置key值得时刻我们可以设置为如数组元素的下标值,然则引荐运用数据的id作为key值,下标值作为key会存在一个题目是假如我们须要对展现的数据从新排序,会致使衬着速率变慢

<li key={item.id}>{item}</li>

表单

关于value

在react中我们写一个以下的代码:

ReactDOM.render(
    <input type="text" value="react"/>,
    document.querySelector("#root")
)

然后我们尝试在输入框中输入笔墨会发明不管输入什么内容,输入框中会依旧坚持是react,这是由于在我们建立input的时刻,value就已被react挟制了

react也会迥殊知心的举行提醒

Failed prop type: You provided a
value prop to a form field without an
onChange handler. This will render a read-only field. If the field should be mutable use
defaultValue. Otherwise, set either
onChange or
readOnly. in input

依据提醒,我们可以发明我们须要设置为以下的花样

ReactDOM.render(
    <input type="text" defaultValue="react" />,
    document.querySelector("#root")
)

这个时刻我们就可以一般的修正表单数据了,一样的会被react挟制的另有一个属性,就是checked,在运用时一样须要转换为React供应的defaultChecked

关于双向数据绑定和单项数据绑定

react中是没有双向绑定这个观点的,现实的react实在可以明白为是一个单向的数据绑定,一切的顶层具有的state做为数据流经由历程props向下通报给子组件,然后在数据转变的时刻从新挪用render,重而从新衬着页面

    原文作者:羊烊羴
    原文地址: https://segmentfault.com/a/1190000016241712
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞