乐趣区

关于react.js:一文读透react精髓

学和应用 react 有一年多了,最近想在梳理一下 react 基础知识, 夯实根底,激流勇进~
对于 reacr-router,redux,redux-saga 后续都会缓缓输入,心愿各位看官老爷继续关注~~ 要是能给个赞激励一下就更 了~

react 基础知识速览

1、什么是 JSX?

一个 JSX 语法的示例,如下所示

const element = <h1>Hello, world!</h1>;

这种语法模式,既不是 HTML,也不是字符串,而是称之为 JSX,是 React 里用来形容 UI 和款式的语法,JSX 最终会被编译为非法的 JS 语句调用(编译器在遇到 { 时采纳 JS 语法进行解析,遇到 < 就采纳 HTML 规定进行解析)

2、嵌入表达式

JSX 中,能够应用花括号 {} 嵌入任意的 JavaScript 非法表达式,如:2 + 2user.firstNameformatName(user)都是非法的。示例如:

const user = {
    firstName: 'Zhang',
    lastName : 'Busong'
};

const elem = (<h1>Hello, {formatName(user)}</h1>
);
/* 这里的(),实际上是可选的,然而 React 举荐退出(),这样子就会被视为一个表达式,而不会导致主动插入分号的问题 */

ReactDOM.render(
    element,
    document.getElementById('app')
)

React 实战视频解说:进入学习

3、JSX 也是一种表达式

JSX 自身也是一种表达式,所以它能够像其余表达式一样,用于给一个变量赋值、作为函数实参、作为函数返回值,等等。如:

function getGreeting(user) {if (user) {return <h1>Hello, {formatName(user)}</h1>
    }
    return <h1>Hello, Guest!</h1>;
}

留神: 1、在 JSX 中,申明属性时不要应用引号,如果申明属性的时候应用引号,那么将被作为字符串解析,而不会被作为一个表达式解析,如:

<div firstName="{user.firstName}" lastName={user.lastName}></div>

解析后,能够失去:

<div firstName="{user.firstName}" lastName="Lau"></div>

因而,当咱们须要应用一个字符串字面量的时候,能够应用引号,然而如果要作为表达式解析的时候,则不该当应用引号
2、在 JSX 中,有些属性名称须要进行非凡解决。如class 应该用 className 代替,tabindex则用 tabIndex 代替。这是因为 JSX 实质上更靠近于 JavaScript,而 class 是 JavaScript 中的保留字。同时,应该应用 camelCase 来命名一个属性,而不是应用 HTML 的属性命名形式
3、JSX 自身曾经做了防注入解决,对于那些不是明确编写的 HTML 代码,是不会被解析为 HTML DOM 的,ReactDOM 会将他们一律视为字符串,在渲染实现前就转化为字符串,所以能够避免 XSS 攻打
4、如果 JSX 标签是闭合的,那么结尾须要用/>,另外,JSX 标签是能够相互嵌套的,这和 HTML 里是一样的

4、JSX 本质

JSX 通过 babel 编译,而 babel 实际上把 JSX 编译给 React.createElement() 调用。如下 JSX 代码:

const element = (
    <h1 className="greeting">
        Hello, world!
    </h1>
);

是等同于以下的语句的:

const elem = React.createElement(
    'h1',
    {className: 'greeting'},
    'Hello, world!'
);

React.createElement()办法会首先进行一些防止 BUG 的查看,而后返回相似以下例子的对象:

const element = {
    type: 'h1',
    props: {
        className: 'greeting',
        children: 'Hello, world'
    }
}

这样的对象,则称为React 元素,代表所有出现在屏幕上的货色。React 正是通过读取这些对象来构建 DOM,并且保持数据和 UI 同步的

5、元素渲染

元素(elements)是形成 React 利用的最小单元,元素形容了想要在屏幕中看到的内容,如:

const element = <h1>Hello, world</h1>;

和 DOM 元素不同的是,React 元素是纯对象,创立的代价低。并且 React 会进行优化解决,只把有必要的变动更新到 DOM 上。此外,元素和组件的概念,是不一样的,组件是由元素组成的。

6、将元素渲染进 DOM

在 React 中,应用 ReactDOM.render() 办法来将 React 元素渲染进一个 DOM 中。如:

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

React 元素是不可变的,所以一旦一个元素创立实现后,咱们是无奈扭转其内容或者属性的。一个元素就像是动画里的一帧,它代表 UI 在某一时间点的样子。如果非要应用元素来形成可变动的 UI 界面,就须要应用 setInterval 了,如:

function tick() {
    const element = (<div>Now is {new Date().toLocaleTimeString()}</div>
    );
    ReactDOM.render(
        element,
        document.getElementById('root')
    );
}
setInterval(tick, 1000);

在理论开发中,大多数 React 利用只会调用一次 ReactDOM.render(),所以更好的形式是应用 有状态组件

7、组件和 Props

组件(component)可能将 UI 划分为独立的、可复用的局部,这样咱们就只需专一于构建每一个独自的部件。
从概念上看,组件就像是函数:承受任意的输出(称为属性,Props),返回 React 元素。React 中有两种定义组件的形式:函数定义 类定义

1、函数定义组件

这种形式是最简略的定义组件的形式,就像写一个 JS 函数一样,如:

function Welcome (props) {return <h1>Hello, {props.name}</h1>;;
}

2、类定义组件

还能够应用 ES6 里的类来定义一个组件,如下所示:

class Welcome extends React.Component {render () {return <h1>Hello, {this.props.name}<h1>;
    }
}

这种形式比起 函数定义 形式则更加灵便

3、组件渲染

先前,咱们遇到的 React 元素只是出现一个 DOM 标签,如:

const element = <div />

然而,React 元素也能够是用户自定义的 组件,如:

const element = <Welcome name="Tom" />

Welcome 组件中申明了一个属性 name="Tom",而这个属性,将以props.name 的形式传递给组件,如下形式:

function Welcome (props) {return <h1>Hello, {props.name}</h1>;
}

此时,对于以下的代码:

ReactDOM.render(
    <Welcome name="张不怂" />,
    document.getElementById('root')
)

最终就会以 <h1>Hello, 张不怂 </h1> 的形式出现。在这个过程中,产生了如下的事件:

  • <Welcome name="张不怂" /> 元素调用了 ReactDOM.render() 丰盛
  • React 将 {name: '张不怂'} 作为 props 实参来调用 Welcome 组件
  • Welcome 实现渲染,返回 <h1>Hello, 张不怂 </h1> 元素
  • ReactDOM 计算最小更新代价,而后更新 DOM

4、组合组件

组件是能够组合的。即组件外部能够援用其余组件,如:

function Welcome (props) {return <h1>Hello, {props.name}</h1>;
}

function App () {
    return (
        <div>
            <Welcome name="Tom" />
            <Welcome name="Jack" />
            <Welcome name="Mike" />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
)

留神: 在 React 中,组件必须返回 繁多 的根元素,这也是为什么 App 组件中须要用 <div> 标签包裹的起因。如以下的形式,是谬误的(因为它有 3 个根元素):

function App () {
    return (
        <Welcome name="Tom" />
        <Welcome name="Jack" />
        <Welcome name="Mike" />
    )
}

5、属性是只读的

思考以下这种状况:

function sum (a, b) {return a + b;}

这种函数称为 纯函数 :它不扭转本人的输出值,且总是对雷同的输出返回雷同的后果。
与之对抗的,则是 非纯函数,如:

function withdraw (account, amount) {account.total -= amount;}

非纯函数 在函数内扭转了输出的参数。在 React 中,无论是通过 function 还是 class 申明组件,咱们都不应该批改它本身的属性(props)。尽管 React 相当灵便,然而它也有一个严格的规定:所有的 React 组件都必须像纯函数那样来应用它们的 props

8、State 与生命周期

应用 类定义组件 有一些额定的益处,如领有 本地状态 这一个性。
以下是一个 类定义组件

class Clock extends React.Component {render () {
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>Now is {this.props.date.toLocaleTimeString()}</h2>
            </div>
        );
    }
}

须要留神的有:

  • 类名 即为 组件名(无论是函数定义组件还是类定义组件,组件名称的首字母都必须大写,并且继承自React.Component
  • 应用 render() 办法,用来返回须要出现的内容

1、在类中退出 state

state 是属于一个组件本身的。咱们能够在类的构造函数 constructor 中来初始化状态,如:

constructor (props) {super(props)
    this.state = {date: new Date()
    }
}

如此一来,咱们就能够在 render() 函数中应用 this.state.xxx 来援用一个状态

2、生命周期

在利用里,往往都会有许许多多的组件。在组件销毁后,回收和开释它们所占据的资源十分重要。
时钟利用 的例子里,咱们须要在第一次渲染到 DOM 的时候设置一个定时器,并且须要在相应的 DOM 销毁后,革除这个定时器。那么,这种状况下,React 为咱们提供了生命周期的钩子函数,不便咱们进行应用。在 React 中,生命周期分为:
1)Mount 已插入实在 DOM
2)Update 正在从新渲染
3)Unmount 已移出实在 DOM
而相应的,生命周期钩子函数有:

  • componentWillMount
  • componentDidMount
  • componentWillUpdate(newProps, nextState)
  • componentDidUpdate(prevProps, prevState)
  • componentWillUnmount()

此外,还有两种非凡状态的处理函数:

  • componentWillReceiveProps(nextProps) 已加载的组件收到新的参数时调动
  • shouldComponentUpdate(nextProps, nextState) 组件判断是否从新渲染时调用

因而,基于生命周期钩子函数,咱们能够实现一个时钟利用如下:

class Clock extends React.Component {constructor (props) {super(props);
        this.state = {date: new Date()
        }
    }
    tick () {
        this.setState({date: new Date()
        });
    }
    componentDidMount () {this.timerId = setInterval(() => {this.tick()
        }, 1000);
    }
    componentWillUnmount () {clearInterval(this.timerId);
    }
    render () {
        return (<div>Now is {this.state.date.toLocaleTimeString()}</div>
        );
    }
}

须要留神的是:
1)render()里用不到的 state,不应该申明在state
2)不能间接应用 this.state.xxx = xxx 的形式来扭转一个 state 的值,应该应用this.setState()。如:

setName () {
    this.setState({name: '张不怂'})
}

this.setState()会主动笼罩 this.state 里相应的属性,并触发 render() 从新渲染。
3)状态更新可能是异步的 React 能够将多个setState() 调用合并成一个调用来晋升性能。且因为 this.propsthis.state可能是异步更新的,所以不应该依附它们的值来计算下一个状态。这种状况下,能够给 setState 传入一个函数,如:

this.setState((prevState, props) => ({counter: prevState.counter + props.increment}));

9、事件处理

React 元素的事件与 DOM 元素相似,不过也有一些区别,如:
1)React 事件应用 camelCase 命名(onClick),而不是全小写的模式(onclick
2)应用 JSX,传入的是事件的句柄,而不是一个字符串
如以下的 HTML:

<button onclick="increment()">ADD</button>

应用 React 的形式形容如:

<button onClick={increment}>ADD</button>

还有一个不同在于,在原生 DOM 中,咱们能够通过返回 false 来阻止默认行为,然而这在 React 中是行不通的,在 React 中须要明确应用 preventDefault() 来阻止默认行为。如:

function ActionLink () {function handleClick (e) {e.preventDefault();
        alert('Hello, world!');
    }

    return (<a href="#" onClick={handleClick}>Click Me</a>
    );
}

这里,事件回调函数里的 event 是通过 React 非凡解决过的(遵循 W3C 规范),所以咱们能够释怀地应用它,而不必放心跨浏览器的兼容性问题。留神: 在应用事件回调函数的时候,咱们须要特地留神 this 的指向问题,因为在 React 里,除了构造函数和生命周期钩子函数里会主动绑定 this 为以后组件外,其余的都不会主动绑定 this 的指向为以后组件 ,因而须要咱们本人留神好 this 的绑定问题,
通常而言,在一个类形式申明的组件里应用事件回调,咱们需 要在组件的 constructor 里绑定回调办法的 this 指向,如:

class Counter extends React.Component {constructor (props) {super(props);
        this.state = {counter: 0}
        // 在这里绑定指向
        this.increment = this.increment.bind(this);
    }
    increment () {
        this.setState({counter: this.state.counter + 1});
    }
    render () {
        return (
            <div>
                The counter now is: {this.state.counter}
                <button onClick={this.increment}>+1</button>
            </div>
        );
    }
}

当然,咱们还有另外一种办法来应用 箭头函数 绑定指向,就是应用 实验性 的属性初始化语法,如:

class Counter extends React.Component {increment: () => {
        this.setState({counter: this.state.counter + 1});
    }
    // ...
}

3)像事件处理程序传递参数
咱们能够为事件处理程序传递额定的参数,形式有以下两种:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

须要留神的是,应用箭头函数的状况下,参数 e 要显式传递,而应用 bind 的状况下,则无需显式传递(参数 e 会作为最初一个参数传递给事件处理程序)

10、条件渲染

在 React 里,咱们能够创立不同的组件来封装咱们须要的性能。咱们也能够依据组件的状态,只渲染组件中的一部分内容,而条件渲染就是为此而筹备的。在 React 中,咱们能够像在 JavaScript 中写条件语句一样地写条件渲染语句,如:

function Greet(props) {
    const isLogined = props.isLogined;
    if (isLogined) {return <div>Hello !</div>;}
    return <div>Please sign in</div>;
}

ReactDOM.render(<Greet isLogined={true} />,
    document.getElementById('root')
);

这将渲染出:

<div>Hello !</div>

1、应用变量来存储元素

咱们也能够应用变量来存储元素,如:

function LogBtn(props) {
    var button;
    const isLogined = props.isLogined;
    if (isLogined) {button = <button> 退出 </button>} else {button = <button> 登陆 </button>}
    return <div>You can {button}</div>;
}

ReactDOM.render(<LogBtn isLogined={false} />,
    document.getElementById('root')
);

2、应用 && 运算符进行渲染

因为 JavaScript 语法看待 && 运算符的性质,咱们也能够应用 && 运算符来实现条件渲染,如:

function LogBtn(props) {
    var button;
    const isLogined = props.isLogined;
    return (<div>Hello        {!isLogined && (            <button> 请登陆 </button>)}        </div>
    )
}

props.isLogined 为 false 的时候,就会渲染出:

<div>Hello <button> 请登录 </button></div>

3、应用三目运算符进行渲染

咱们可能曾经发现了,其实 JSX 能够像一个表达式那样子灵便应用,所以,咱们天然也能够应用三目运算符进行渲染,如:

function LogBtn (props) {
    const isLogined = props.isLogined;
    return (<div>You can             <button>{isLogined ? '退出' : '登陆'}</button>
        </div>
    )
}

4、阻止整个组件的渲染

有时候,咱们心愿是整个组件都不渲染,而不仅仅是部分不渲染,那么这种状况下,咱们就能够在 render() 函数里返回一个null,来实现咱们想要的成果,如:

function LogBtn (props) {
    const isLogined = props.isLogined;
    const isShow = props.isShow;
    if (isShow) {
        return (<div>You can                 <button>{isLogined ? '退出' : '登陆'}</button>
            </div>
        )
    }
    return null;
}

留神: 组件里返回 null 不会影响组件生命周期的触发,如 componentWillUpdatecomponentDidUpdate依然会被调用

11、列表渲染与 keys

在 JavaScript 中,咱们能够应用 map() 函数来对一个数组列表进行操作,如:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(number => number*2);
console.log(doubled); // 失去[2, 4, 6, 8, 10]

同样的,在 React 里,咱们也能够应用 map() 来进行列表渲染,如:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map(number => {
    return (<li>{number}</li>
    )
});

ReactDOM.render(<ul>{listItems}</ul>,
    document.getElementById('root')
)

这将失去:

<ul><li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>

当然,咱们还能够进行更好的封装,如:

function NumberList (props) {
    const numbers = props.numbers;
    const listItems = numbers.map(number => {
        return (<li>{number}</li>
        )
    });

    return <ul>{listItems}</ul>
}

当咱们运行以上的代码的时候,会发现控制台提醒:Each child in an array or iterator should have a unique "key" prop,因而,咱们须要为列表项的每一个项调配一个key,来解决这个问题,通常而言,咱们能够应用以下几种形式来提供key

  • 应用数据项本身的 ID,如<li key={item.itemId}>
  • 应用索引下标(index),如:
const listItems = numbers.map((number, index) => {<li key={index}>{number}</li>
});

然而 React 不举荐在须要从新排序的列表里应用索引下标,因为会导致变得很慢。

留神: 只有在一个项的同胞里辨别彼此的时候,才须要应用到 key,key 不须要全局惟一,只须要在一个数组外部辨别彼此时惟一便可。key 的作用是给 React 一个提醒,而不会传递给组件。如果咱们在组件内须要同样的一个值,能够换个名字传递,如:

const content = posts.map(post => (<Post key={post.id} id={post.id} title={post.title} />
));

12、表单

表单和其余的 React 中的 DOM 元素有所不同,因为表单元素生来就是为了保留一些外部状态。在 React 中,表单和 HTML 中的表单略有不同

1、受控组件

HTML 中,<input><textarea><select>这类表单元素会维持本身状态,并依据用户输出进行更新。不过 React 中,可变的状态通常保留在组件的 this.state 中,且只能用 setState() 办法进行更新,如:

class NameForm extends React.Component {constructor (props) {super(props);
        this.state = {value: ''}
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange (event) {
        this.setState({value: event.target.value});
    }
    handleSubmit (event) {alert('Your name is'+this.state.value);
        event.preventDefault();} 
    render () {
        return (<form onSubmit={this.handleSubmit}>
            Name: <input type="text" value={this.state.value} onChange={this.handleChange} />
            <input type="submit" value="Submit" />
            </form>
        )
    }
}

和 HTML 中不同的是,React 中的 textarea 并不需要写成 <textarea></textarea> 的模式,而是写成 <textarea value="" ... /> 的模式便可。而对于 HTML 中的 select 标签,通常做法是:

<select>
    <option value="A">A</option>
    <option value="B" selected>B</option>
    <option value="C">C</option>
</select>

然而 React 中,不须要在须要选中的 option 处退出selected,而只须要传入一个 value,就会主动依据 value 来选中相应的选项,如:

<select value="C">
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
</select>

那么如上述例子,C 所在的这个 option 就会被选中

2、多个输出的解决办法

通常一个表单都有多个输出,如果咱们为每一个输出增加处理事件,那么将会十分繁琐。好的一个解决办法是,应用 name,而后依据 event.target.name 来抉择做什么。如:

class Form extends React.Component {constructor (props) {super(props);
        this.state = {
            name: '',
            gender: '男',
            attend: false,
            profile: ''
        };
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleInputChange (event) {
        const target = event.target;
        const value = target.type==='checkbox' ? target.checked : target.value;
        const name = target.name;
        this.setState({[name]: value
        });
    }
    handleSubmit (event) {
        this.setState({profile: ` 姓名:${this.state.name},${this.state.gender},${this.state.attend ? '加入' : '不加入'}流动 `
        });
        event.preventDefault();} 
    render () {
        return (
            <form>
            <p> 姓名:<input name="name" value={this.state.name} onChange={this.handleInputChange} /></p>
            <p> 性别:<select name="gender" value={this.state.gender} onChange={this.handleInputChange}>
                    <option value="男"> 男 </option>
                    <option value="女"> 女 </option>
                </select>
            </p>
            <p> 是否加入:<input name="attend" type="checkbox" onChange={this.handleInputChange} checked={this.state.attend} /></p>
            <input type="submit" value="Submit" onClick={this.handleSubmit} />
            <p> 您的报名信息:{this.state.profile}</p>
            </form>
        )
    }
}

3、非受控组件

大多数状况下,应用 受控组件 实现表单是首选,在受控组件中,表单数据是交由 React 组件解决的。如果想要让表单数据由 DOM 解决(即数据不保留在 React 的状态里,而是保留在 DOM 中),那么能够应用 非受控组件 ,应用 非受控组件 ,能够无需为每个状态更新编写事件处理程序,应用ref 即可实现,如:

class NameForm extends React.Component {constrcutor(props) {super(props)
    }
    handleSubmit(event) {console.log('A name was submitted:', this.input.value)
        event.preventDefault()}
    render() {
        return (<form onSubmit={this.handleSubmit}>
                <label>
                Name: <input type="text" ref={input => this.input = input} />                </label>
                <input type="submit" value="submit" />
            </form>
        )
    }
}

对于 非受控组件,如果要指定默认值,那么能够应用defaultValue,如:

<input type="text" defaultValue="Hello" ref={input => this.input = input} />

相应的,type="checkbox"type="radio",则应用defaultChecked

13、状态晋升

当须要几个组件共用状态数据的时候,能够应用状态晋升技术。核心思想在于:把数据抽离到最近的独特父组件,父组件治理状态(state),而后通过属性(props)传递给子组件。如实现一个货币转换的组件,能够如下:

1、首先定义转换函数

function USD2RMB (amount) {return amount * 6.7925;}

function RMB2USD (amount) {return amount * 0.1472;}

function convert (amount, typeFn) {return typeFn(amount);
}

2、定义组件

咱们心愿在 RMB 的输出表单上上输出的时候,USD 的输出表单上的数值也同步更新,这种状况下,如果 RMB 组件本人治理本人的状态,是很难以实现的,因而,咱们须要让这个状态晋升自父组件进行治理。如下:

class CurrencyInput extends React.Component {constructor (props) {super(props)
        this.handleChange = this.handleChange.bind(this)
    }
    handleChange (event) {this.props.onInputChange(event.target.value)
    }
    render () {
        const value = this.props.value
        const type = this.props.type
        return (<p>{type}: <input type="text" value={value} onChange={this.handleChange} /></p>
        );
    }
}

最初定义一个独特的父组件,如下:

class CurrencyConvert extends Component {constructor (props) {super(props);
        this.state = {
            type: 'RMB',
            amount: 0
        }
        this.handleRMBChange = this.handleRMBChange.bind(this);
        this.handleUSDChange = this.handleUSDChange.bind(this);
    }
    handleRMBChange (amount) {
        this.setState({
            type: 'RMB',
            amount
        });
    }
    handleUSDChange (amount) {
        this.setState({
            type: 'USD',
            amount
        });
    }
    render () {
        const type = this.state.type;
        const amount = this.state.amount;
        const RMB = type==='RMB' ? amount : convert(amount, USB2RMB);
        const USD = type==='USD' ? amount : convert(amount, RMB2USB);
        return (
            <div>
                <p>Please Input:</p>
                <CurrencyInput type="RMB" value={RMB} onInputChange={this.handleRMBChange} />
                <CurrencyInput type="USD" value={USD} onInputChange={this.handleUSDChange} />
            </div>
        );
    }
}

14、组合 vs 继承

React 推崇更多的是应用组合,而非应用继承。对于一些应用场景,React 给出的倡议如下:

1、蕴含关系

当父组件不晓得子组件可能的内容是什么的时候,能够应用props.children,如:

function Article (props) {
    return (
        <section>
            <aside> 侧边栏 </aside>
            <article>{props.children}</article>
        </section>
    );
}

function App () {
    return (<Article> 这是一篇文章 </Article>);
}

这将渲染失去:

<section>
    <aside> 侧边栏 </aside>
    <article> 这是一篇文章 </article>
</section>

咱们还能够自定义名称,因为 JSX 实际上会被转化为非法的 JS 表达式,所以,还能够有:

function Article (props) {
    return (
        <section>
            <aside>{props.aside}</aside>
            <article>{props.children}</article>
        </section>
    );
}

function App () {
    return (
        <Article aside={<h1> 这是一个侧栏 </h1>}> 这是一篇文章 </Article>
    );
}

这将渲染失去:

<section>
    <aside><h1> 这是一个侧栏 </h1></aside>
    <article> 这是一篇文章 </article>
</section>

2、何时应用继承?

在 Facebook 的网站上,应用了数以千计的组件,然而实践证明还没有发现须要应用继承能力解决的状况。
属性和组合为咱们提供了清晰的、平安的形式来自定义组件的款式和行为,组件能够承受任意元素,包含:根本数据类型、React 元素、函数。
如果要在组件之间复用 UI 无关的性能,那么应该将其提取到独自的 JavaScript 模块中,这样子能够在不对组件进行扩大的前提下导入并应用函数、对象、类

退出移动版