react 基本语法

React


## 什么是 *React*

是一个用于构建用户界面的 JavaScript 库。React 主要用于构建 UI,相当于是 MVC 中的 V(视图)

拥有较高的性能,代码逻辑简单

React 特点

  1. 声明式设计:React 采用声明范式,可以轻松描述应用。
  2. 高效:React 通过对 DOM 的模拟,最大限度地减少与 DOM 的交互。
  3. 灵活:React 可以与已知的库或框架很好地配合。
  4. JSXJSXJavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
  5. 组件:通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
  6. 单向响应的数据流:React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

着重点:


单向数据流

  • state:驱动应用的数据源
  • view:以声明方式将 state 映射到视图
  • actions:响应在 view 上的用户输入导致的状态变化

用户访问 ViewView 发出用户交互的 Action,在 Action 里对 State 进行相应更新。State 更新后会触发 View 更新页面的过程。

虚拟 DOMVirtual DOM

React 为了尽可能减少对 DOM 的操作,提供了Virtual DOM

DOM 抽象为虚拟 DOM,虚拟 DOM 其实就是一个对象,用来描述 DOM 应该什么样子、应该如何呈现。然后 React 通过这个 Virtual DOM 去管理并更新真实的 DOM

Diff 算法(虚拟 DOM 的加速器,提升 React 性能的法宝)

通过虚拟 DOM 树构建一个真正的 DOM 树,插入到文档当中。

通过 Diff 算法会将新的虚拟 DOM 树和旧的虚拟 DOM 树进行比较,记录两棵树的差异。最终只把发生变化的部分重新渲染到真实 DOM 树中,由此提高渲染的效率。



React 元素

JSX

一种 JavaScript 的语法扩展。在 React 中推荐使用 JSX 来描述用户界面。

JSX 虽然类似于模板语言,但是并不是HTML,它完全是在 JavaScript 内部实现的。

优点

  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型安全的,在编译过程中就能发现错误。
  • 使用 JSX 编写模板更加简单快速。

在 JSX 中,根元素只能有一个,如果出现多个根元素,React 将不能正常渲染。

const ele = (
     <div>
         <h1>欢迎学习 React</h1>
         <p>在 React 中推荐使用 JSX 来描述用户界面。</p>
         <ul>
             <li>JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。</li>
             <li>它是类型安全的,在编译过程中就能发现错误。</li>
             <li>使用 JSX 编写模板更加简单快速。</li>
          </ul>
         </div>
);
ReactDOM.render(ele , document.getElementById('example'));

注意点:


JavaScript 表达式

JSX 中使用 JavaScript 表达式。表达式写在花括号 {}

不同于 vue vue的表达式是写在 {{}} 中


三元运算

SX 中不能使用 if else 语句,但可以使用 conditional(三元运算)表达式来替代。

        const ele = (
            <div>
                <h1>{age >= 18 ? '你已经成年' : '你还未成年'}</h1>
            </div>
        );

样式

camelCase 语法来设置内联样式。React 会在指定元素数字后添加 px

        const myStyle = {
            fontSize : 44,
            color : 'blue'
        };
        ReactDOM.render(
            <h1 style = {myStyle}>this is a test</h1>,
            document.getElementById('example')
        );
            <h1 style = {{color :'red'}}>this is a test</h1>,

注意:内联样式需要写两个花括号。相当于传入了一个对象


className

JSX实际上是 JavaScript 对象,而在 JavaScript 中拥有 class 关键字,表示类。所以 class 需要替换为 className

        ReactDOM.render(
            <h1 className="test">this is a test</h1>,
            document.getElementById('example')
        );

注释

格式:

{/* 注释内容... */}

规则:

JSX 形式的注释可以写在 script 脚本中,也可以写在 JSX 中。

js 形式的注释只能写在 script 中,如果写在 JSX 中会被渲染出来。


数组

在模板中插入数组,数组会自动展开所有成员

        const arr = [
            <h1>欢迎来到 React</h1>,
            <h2>React 是当经最流行的前端框架!</h2>,
        ];
        const ele = (
            <div>
                { arr }
            </div>
        );
        ReactDOM.render(ele , document.getElementById('example'));

createElement

React 底层,提供了 createElement 方法用于创建并返回指定类型的新 React 元素

书写的 JSX,实际上就会被 Babel 转译器转换为 React.createElement 的方法调用

结构:

React.createElement(type, [props], [...children]);
  • type:创建的 React 元素类型(可选的值有:标签名字符串、React 组件)。
  • props(可选):React 元素的属性。
  • children(可选):React 元素的子元素。
const element = (
    <h1 className="greeting">
    Hello, world!
    </h1>
);
{/* 两者渲染的结果是相同的 */}
const element = React.createElement(
    'h1',
    {className: 'greeting'},
    'Hello, world!'
);



组件


函数式组件

函数中会返回 JSX,最后我们将该组件挂载到了页面上。

        function HelloMessage() {
            return (
                <div>
                    <h1>欢迎学习 React</h1>
                    <p>在 React 中推荐使用 JSX 来描述用户界面。</p>
                </div>
            );
        }
// 将组件渲染到 id 为 example 的 div 中
ReactDOM.render(<HelloMessage />,document.getElementById('example'));

类定义组件

class Welcome extends React.Component {    render() {        return <h1>Hello World!</h1>;    }}        // 将组件渲染到 id 为 example 的 div 中ReactDOM.render(<Welcome />,document.getElementById('example'));

组合组件

可以通过复合组件来构成我们的页面。

        class Welcome3 extends React.Component {
            render() {
                return (
                    <div>
                    <HelloMessage />
                    <Welcome />
                	</div>
                )
            }
        }
ReactDOM.render(<Welcome3/>, document.getElementById("example"));


Fragment

用来表示不可见的包裹元素

        class Welcome extends React.Component {
            render() {
                return (
                    <React.Fragment>
                        <h1>Hello HTML</h1>
                        <h1>Hello CSS</h1>
                    </React.Fragment>
                )
            }
        }



Props

为属性

props 是组件对外的接口,在组件内部,可以通过 props 拿到外部传给组件的参数。

函数的方式来创建的组件

        function HelloMessage(props) {
            return (
                <div>
                    <p>姓名:{props.name}</p>
                    <p>年龄:{props.age}</p>
                </div>
            );
        }
        // 渲染组件时将属性传递到组件里面
ReactDOM.render(<HelloMessage name = "li" age = {18}/>,document.getElementById('example'));

如果是传递数值,需要使用花括号将其扩起来。 如:age = {18}


class 类 的形式来定义的组件

通过“this.props.属性值”来获取参数

        class Welcome extends React.Component {
            constructor(props) {
                super(props);
            }
            render() {
                return (
                    <div>
                        <p>姓名:{this.props.name}</p>
                        <p>年龄:{this.props.age}</p>
                    </div>
                );
            }
        }
ReactDOM.render(<Welcome name = "li" age = {18}/>,document.getElementById('example'));

特殊的属性:childre

当前组件的子组件集合

        class RootContent extends React.Component{
            constructor(props){
                super(props);
            }
            render(){
                return (
                    <div className='divider'>
                        {this.props.children}
                    </div>
                );
            }
        }
                class RootChild extends React.Component{
            constructor(props){
                super(props);
            }
            render(){
                return (
                    <RootContent>
                        <p>Hello, React</p>
                        <p>Hello, Redux</p>
                        <p>Hello, Facebook</p>
                        <p>Hello, Google</p>
                    </RootContent>
                );
            }
        }

defaultprops

当组件没有传递属性时,就是用默认的参数值

// 函数
		// props 为一个对象,接收传递过来的属性
        function HelloMessage(props) {
            const { name,age,gender } = props;
            return (
                <div>
                    <p>姓名:{name}</p>
                    <p>年龄:{age}</p>
                </div>
            );
        }
	// 设置默认的 props 值,当组件没有传值时会使用默认值
        HelloMessage.defaultProps = {
            name : 'li',
            age : 18,
        };
// 类
		class Welcome extends React.Component {
            constructor(props) {
                super(props);
            }
            // 设置默认的 defaultProps 属性值
            static defaultProps = {
                name : "xiejie",
                age : 18,
                gender : 'male' 
            }
            render() {
                return (
                    <div>
                        <p>姓名:{this.props.name}</p>
                        <p>姓名:{this.props.age}</p>
                        <p>姓名:{this.props.gender}</p>
                    </div>
                );
            }
        }



事件处理

面对事件的考究:

如何确认事件,如何传参,如何获取事件对象


为组件绑定事件

采用驼峰命名法,并且对应的值为一个函数,而不是一个字符串

React 中绑定事件的写法

<button onClick={activateLasers}>
    Activate Lasers
</button>

React 中无法通过 return false 来阻止默认行为,所以只有使用 e.preventDefault 的方式来阻止默认行为。

            // 事件处理函数
            eventHandler(e){
                window.alert('Hello');
                e.preventDefault();
            }
            render() {
                return (
                    <a href="https://www.baidu.com/" onClick = {this.eventHandler}>this is a test</a>
                );
            }

this 的指向

存在于类定义组件

在事件中无法定义到this

解决方法:

将事件处理函数修改为箭头函数

            eventHandler = () => {
                console.log(this); 
            }

使用 bind 方法来强制绑定 this 的指向

constructor(){
      super();
      this.eventHandler = this.eventHandler.bind(this); // 强制绑定 this 的指向
}

在绑定时候的时候,以箭头函数的形式进行绑定

render() {
    return (
      <div onClick = {() => this.eventHandler()}>this is a test</div>
    );
}

向事件处理程序传参

通过 bind 方法在绑定 this 指向时向事件处理函数进行传参

render() {
    return (
         // 通过 bind 方法来传递参数,书写 2 个参数:绑定的 this 指向,额外参数
       <div onClick = {this.eventHandler.bind(this,'Hello')}>this is a test</div>
    );
}

通过绑定事件时,通过书写箭头函数的形式来传参

render() {    return (     // 绑定事件时通过书写箭头函数的形式来传参     <div onClick = {(e)=>this.eventHandler('Hello',e)}>this is a test</div>	);}



state

概念:

在组件中,自身的数据也被称为状态,这类组件也被称为有状态组件,在组件中通过 state 来定义组件的数据(状态),state 是一个对象。

有状态组件只能通过类的方式进行定义

        class Welcome extends React.Component {
            constructor(){
                super();
                // 设置组件自身的数据状态
                this.state = {
                    name : 'li',
                    age : 18,
                }
            }
            render() {
                return (
                    <div>
                        <p>姓名:{this.state.name}</p>
                        <p>年龄:{this.state.age}</p>
                    </div>
                );
            }
        }

修改组件状态

state 的作用:

用于组件保存、控制以及修改自己的数据状态

只能在 constructor 中初始化,算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 setState 方法来进行修改

state = {
    num : 1
 }
// 事件函数
eventHandler = () => {
      // 使用 this.setState 方法来设置组件自身的状态数据
     this.setState({
          num: this.state.num + 1
     })
}

注意:

React 会把多次 setState 操作合并成一次,所以 setState 执行的过程是异步的

setState 执行后并没有立刻更新 state 中的数据

解决方法:

1.把计算结果存储下来

 eventHandler = () => {
       let newCount = this.state.num + 1; // 使用一个变量来计算结果存储下来
       this.setState({
            num: newCount
       })
       console.log(newCount); // 期望是 2,实际也是 2
}

2.setState 还有第二个参数,它是一个函数,这个函数会在 state 更新后被调用

            eventHandler = () => {
                this.setState({
                    num: this.state.num + 1
                },()=>{
                    console.log(this.state.num); // 期望是 2,实际也是 2
                })
            }

属性 props 与 状态 state 的区别:

state 是组件自己管理数据,控制自己的状态,可变。

props 是外部传入的数据参数,不可变。

使用函数创建的组件为无状态组件,使用类方式声明的组件为有状态组件。

无状态组件(函数创建的组件)无法定义 state 状态。

多用 props,少用 state。也就是多写无状态组件,这样更方便对数据的统一管理。



条件与循环


条件渲染

render 方法中先进行条件判断,根据当前的 state 值来决定渲染哪一个组件,并且将要渲染的组件赋值给 com。最后,在 return 的时候就直接渲染 com 组件即可。

render() {
    let com = null;
     // 根据组件状态值 whichCom 来觉得 com 的值
    if(this.state.whichCom){
          com = <Com1/>
     } else {
          com = <Com2/>
     }
     return (
     // 为 button 绑定点击事件,更改 whichCom 的值,状态值一改变,页面就会重新渲染
         <div>
          <button onClick = {(e)=>this.changeState(e)}>changeState</button>
          {com}
         </div>
      );
}

可以使用三目运算符直接在 return 中进行判断

<div>
     <button onClick = {(e)=>this.changeState(e)}>changeState</button>
     {this.state.whichCom ? <Com1/> : <Com2/>}
</div>

需要隐藏某些组件,这个时候设置该组件的 render 方法返回 null 即可

function WarningBanner(props) {
if (!props) {
      return null; // 返回 null 表示不渲染
}
}

列表渲染

循环渲染出某些内容

 class Page extends React.Component {            constructor(){                super();                this.data = ['苹果','香蕉','西瓜']; // 列表的数据            }            render() {                return (                    <ul>                        {this.data.map((item,index)=>{                            return (<li key={index}>{item}</li>);                        })}                    </ul>                );            }        }ReactDOM.render(<Page />,document.getElementById('example'));

循环生成时,必须要为列表每一项,生成一个key



表单

表单的组件可以分为受控组件非受控组件

受控组件

用户输入的内容是受控的,我们可以通过事件来对用户输入的信息进行过滤或者限制操作

主要通过事件改变 state 中的value来控制

        class Com extends React.Component {
            state = {
                value1: '',
                value2: ''
            }
            changeHandle = (e) => {
                // 判断 输入框
                if (e.target.name === 'one') {
                    // 为one时,输入的字母转为大写
                    this.setState({
                        value1: e.target.value.toUpperCase()
                    })
                } else {
                    // 为two 时,只能输入数字
                    let str = e.target.value;
                    // 遍历输入的每一个值
                    let arr = str.split('').map((item) => {
                        if (!isNaN(item)) {
                            return item;
                        }
                    })
                    this.setState({
                        value2:arr.join('')
                    })
                }
            }
            render() {
                return (
                    <div>
                        <input type="text" name="one" id="" value={this.state.value1} onChange={this.changeHandle} />
                        <br/>
                        <input type="text" name="two" id="" value={this.state.value2} onChange={this.changeHandle} />
                        <p>你输入的为:{this.state.value1}</p>
                        <p>你输入的为:{this.state.value2}</p>
                    </div>
                )
            }
        }

value 属性

textarea 标签

html 中,textarea 标签是通过子节点来定义它的文本内容

在 React 中,textarea 会用 value 属性来代替

同上不一样,通过onChange,也可设置textarea 的 value 属性

select 标签

在 html 当中,select 会创建一个下拉列表

React 中,在 select 标签上用 value 属性来表示选中项

input type=“text”textareaselect 都十分类似,他们都通过传入一个 value 属性来实现对组件的控制。


非受控组件

如果要让表单数据由 DOM 来进行处理时,替代方案为使用非受控组件。非受控组件中控件值和 state 没有联系,所以需要使用 refDOM 中获取表单值。

            clickHandle = () => {
                console.log(this.refs.nameInput.value)
            }
               

            render() {
                return (
                    <div>
                        <input type="text" name="" id="" ref="nameInput" />
                        <button onClick={this.clickHandle}>click</button>
                    </div>
                )
            }

而在受控组件中,表单数据由 React 组件处理




状态提升

概念:改变父组件的状态,从而改变受父组件控制的所有子组件的状态

React 中是单向数据流的设计,只能父组件给子组件传递数据。

子组件向父组件传递数据的方法:

在父组件中设置一个方法(函数),将其通过 props 传递给子组件,然后在子组件中更新 state 的状态,并调用父组件中传过来的方法,将 state 数据作为参数传递给父组件。

总体来说就是 ,一个子组件向父组件传递数据,通过回调的方式来实现

        // 子组件向父组件传参,通过回调的方式进行传递
        class Parent extends React.Component {
            constructor(props) {
                super(props);
                this.state={content:'123'}
            }
            // 打印出从子组件传递过来的数据
            cbHandler=(item)=>{
                this.setState({content:item})
            }
            render() {
                return (
                    <div>
                        <h1>子组件向父组件传参:{this.state.content}</h1>
                        <Children cb={this.cbHandler}/>
                    </div>
                );
            }
        }
        class Children extends React.Component {
            constructor(props) {
                super(props);
                this.state={ test:'456' }
            }
            clickHandle =()=>{
                this.props.cb(this.state.test)
            }
            render() {
                return (
                    // 触发父组件传递过来的事件,并且传递了参数过去
                    <button onClick={this.clickHandle}>点击</button>
                );
            }
        }




组件的生命周期

组件从创建到销毁的过程

只有有状态组件才拥有生命周期的钩子函数

分为三个阶段 :

装载时(创建时/挂载时)

constructor
static getDerivedStateFromProps
render
componentDidMount

运行时(更新时)

static getDerivedStateFromProps
shouldComponentUpdate
render
GetSnapshotBeforeUpdate
componentDidUpdate

卸载时

componentWillUnmount

常用生命周期方法

render 方法

class 组件中唯一一个必须实现的方法

render 被调用时,内存中的虚拟 DOM 节点会全部重新渲染

constructor 方法

在将组件挂载到 DOM 之前会调用 constructor 方法。通常,会在 constructor 方法中初始化 state 和绑定事件处理程序

        class MyComponent extends React.Component {
            constructor(props) {
                super(props); 
                this.state = {
                    points: 0
                }  
                console.log('组件已经初始化完毕!');
            } 
        }

componentDidMount 方法

调用 render 后,组件被挂载到 DOM,并调用 componentDidMount 方法

在将组件被挂载到 DOM 之后会立即调用这个函数

            componentDidMount(){
                console.log('组件已经渲染完成!');
            }

componentDidUpdate 方法

render 完成后触发

componentDidUpdate(prevProps, prevState) 方法接收两个参数,前者表示的是更新前的 props,后者则表示更新前的 state

            componentDidUpdate(preProps,preState){
                console.log(preProps);
                console.log(preState);
                console.log('组件已经更新完毕!');
            }

componentWillUnmount 方法

在组件卸载之前调用

该函数可以在组件销毁之前进行一些必要的清理工作,如清除计时器、解绑自定义事件等

写在被销毁的组件里

PureComponent 组件

React 中 setState 方法每一次的执行都会导致 render 方法的重新调用,不管 state 有没有真正的发生改变

shouldComponentUpdate 方法

shouldComponentUpdate 方法的返回值(true/false)可以决定 render 方法是否执行

shouldComponentUpdate(nextProps, nextState) { }

通过对 this.statenextStatethis.propsnextProps)的比较来控制 render 方法的执行

            shouldComponentUpdate(nextProps, nextState) {
                if(this.state.count === nextState.count) {
                    return false;
                }
                return true;
            }

PureComponent

React 中提供了 PureComponent 来帮我们完成这个 shouldComponentUpdate 的处理过程

class Counter extends React.PureComponent {
    
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值