您的位置:首页 > Web前端 > React

React学习之让组件和属性齐飞(三)

2017-03-15 23:02 204 查看
何为组件?

组件就是让你可以独立于
UI
的控件了,从某种意义上来看,组件的开发有点像
javascript
函数式编程,也就是说组件像是个函数,输入一定的数据,然后处理完输出,将数据展现在视图中。

1.函数式组件(又称功能型组件)和类组件

看标题大家就知道函数式组件是什么鬼了,也就是组件的开发,简单地说就是写一个函数,如下:

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


因为它遵循组件的特性,即输入一个
props
对象作为参数,然后有返回一个
JSX
对象,记住参数一定要为
props
,返回值一定是
JSX
对象哦,不然可不是函数式组件(稍微有点概念性的问题,尴尬)。

当然,重点戏到啦,那就是我们亲爱的
ES6
class
,这个
class
来定义类和我们
ES5
中定义对象其实是一样,只是换了一个方式,让对象创建更加普遍和通俗化,(我想想,后续我再补
ES6
学习系列,简直happy happy)

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


从一定的观点上看,函数式组件和类组件是等价的

接下来我将会用函数式组件来讲解,因为类组件写麻烦一些,但是通过上述的描叙,大家应该可以非常轻松的将函数式组件改装为类组件

2.视图展示组件内容

在我前两篇博客中,我们只知道用
DOM
元素标签来填充
JSX
语句,就是div,img,p,h等等,如下:

const e1 = <div />;
const e2 = <img />;
const e3 = <p />;


如今学了上面两种组件方式后,我们终于可以解放啦,我们可以用组件来填充
JSX语句
,用它来代替我们之前的
DOM
节点,简直满满的幸福:

const el = <We name="tm7" />;


那我们的
React
如何处理组件元素的呢?

React
识别到了一个
JSX
元素为一个已经定义的组件
JSX
,它会通过
JSX
属性将对应的
props
对象传递给组件
JSX
,如下:

function We(props) {
return <h1>Hello, {props.name}</h1>;
}
/**
class We extends React.Component{
render(){
return <h1>hello, {this.props.name}</h1>
}
}
**/
const el = <We name="tm7" />;ReactDOM.render(
el,
document.getElementById('root')
);


上述代码做了如下几件事情:

ReactDOM.render()
函数识别出
JSX
为一个组件元素
<We name="tm7" />


React
识别出组件元素中的
props
对象
{name:"tm7"}
,将
props
对象传入组件元素

我们的组件元素调用响应的视图渲染函数进行处理,如果是类组件则是调用
Render()
,如果是函数式组件则是调用函数本身,而返回值为
<h1>hello,tm7</h1>
,其实返回的是一个
JSX
对象

JSX
会被处理为
DOM
节点,渲染在视图中

问题来啦,也就是说基本组件语法讲了,该注意的问题就需要提醒一下了

组件元素定义的
JSX
必须是大写字母开头,也就是说
<we/>
是错的,
<We/>
才是对的,虽然我没有看过源码,但是就官方网站上的说明来看,
React
识别是
DOM
JSX
还是组件型
JSX
的区别就是开头字母有没有大写,如果大写了,就是组件,
Reac
t就会去当前的作用域中寻找有没有相应的组件可以用。

3.构造复合组件

复合,就是融合多个组件,在一个组件中调用另外一些组件,获得那些组件的输出,然后再输出。

实例如下:

function We(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<We name="tm7" />
<We name="jxy" />
<We name="cxl" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);


知识题记

如果你想在一个已经存在的应用中增加别的组件的话,除了,前一篇文章说的:另选一个根节点可以重新处理(其实这种方式不算是增加到已有应用中)外,所谓的应用其实是一个大型
JSX
组件标签,而所谓的增加额外组件就是在这个
JSX
组件标签中增加其它的组件,从而形成一个应用。

这里还要说的是,每一个
<script>
中都是一个独立的作用域

同时我们组件返回的一定是一个
JSX
元素语句,而不是两个,实例如下:

//true
return (<div>
<h1>tm7</h1>
<h1>jxy</h1>
</div>
);

//false
return (
<h1>tm7</h1>
<h1>jxy</h1>
);


4.尽可能提纯我们的代码

首先我们要有个观念,不是越多的组件越好,也不是组件啥都没有就好了,适当的提取一些
JSX
元素为一个组件元素会提高我们的代码的可读性和易用性。

实例如下:

function View(props) {
return (
<div className="View">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="View-text">
{props.text}
</div>
<div className="View-date">
{props.date}
</div>
</div>
);
}

ReactDOM.render(
<View text="tm7" date="new Date()" author={{name:'aaa',avatarUrl:'bbb'}}/>,
document.getElementById('example')
);


我们可以适当的减少这一段代码,比如进行如下提取:

function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}


代码就变为了

function View(props) {
return (
<div className="View">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="View-text">
{props.text}
</div>
<div className="View-date">
{props.date}
</div>
</div>
);
}


我们接着提取

function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}


代码又简化了

function View(props) {
return (
<div className="View">
<UserInfo user={props.author} />
<div className="View-text">
{props.text}
</div>
<div className="View-date">
{props.date}
</div>
</div>
);
}


提取行为的可用性和必要性

虽然提取过程是繁琐无聊的,但是当我们开发比较大的应用的时候,我们可能会重复大量相同的
UI
,那么提取元素对我们开发大型应用和维护应用有着很大的帮助,同时,即便不是大型应用,当我们写一些较为复杂的组件时,提取也是有必要的,我们要让我们的组件更具可读性和重塑性,同时重复
UI
必然存在,如此提取还是无法避免。

5.属性对象
props
和只读性
Read-Only

不管你是声明的函数式组件还是类组件,只要一定义,属性便不能改变,只能读取,也就是说,当声明一个组件后,对象是无法扩展的,不能对它增加属性。

实例如下:

var a = View({author:{name:'aaa',avatarUrl:'bbb'}});
a.tm = "tm7";


会报错:
object is not extensible
,表示无法扩展。

同时对于
props
的处理,由于
props
是一个对象,大家可以用
javascript
语法对他进行处理,即我们给
JSX
元素进行属性设置时,可以直接看成给
props
对象进行属性赋值。

同时这里涉及一个规范:
javascript
函数式编程,下面是一个标准的简单函数式编程:

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


一般函数式编程评判的标准是,同一组输入,一定会产生同样的结果,不会对输入数据产生影响,这就是我们学数学知道的函数映射
f(x)
,比如:二元一次方程,等等

如下则不是一个函数式编程

function wd(ac, am) {
retac.to -= am;
}


它会影响输入的数据,产生的结果也是不可测的

总的来说,
React
是非常灵活的,但是也是很操蛋的,它有它的一套评判标准和严格的规范约束,官网上也提到过,所有的
React
组件都必须是一个纯的函数,即基于函数式编程的函数,一种输入只会对应一种结果,同时不会影响输入的数据

下一篇博客将说说前一篇博客说到的,每次用
render
函数进行覆盖,多难受啊,放心,
React
肯定给你解决方案啦,安啦,安啦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: