今天我们来聊聊复用和组合。先看看啥是复用?这是码农专用词汇(也许别的农也用),没啥神秘的,就是重复使用的意思。重复使用啥?重复使用代码啊!一段20行的代码需要重复使用100次,咋整?拷贝粘贴大法是恒古至今不变的真理,然而使用函数是从码农成为码神之路上最重要的利器,没有之一!
别废话了,直接上代码:
<div id="rootElement"></div>
<script src="https://unpkg.com/react@16.8.3/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
const rootElement = document.getElementById('rootElement')
/*创建一个div,这是一个用jsx写的组件,下面要复用它*/
const du1dume = <div>du1dume</div>
/*
1.这里的小括号是为了让代码看起来更有条理,不加也行
2.container也是一个用jsx写的组件。现在我们要在container组件中复用我们之前创建的du1dume组件。
3.我们通过之前的文章得知,du1dume在运行时被翻译成js代码,我们又得知,在jsx中使用js代码要用大括号括起来。
4.为啥在两个du1dume组件外面要再加个div,不加不就是纯js代码了吗?也就不是jsx组件了,好好想想。
*/
const container = (
<div className="container">
{du1dume}
{du1dume}
</div>
)
ReactDOM.render(container, rootElement)
</script>
我们想改du1dume组件中的文字咋办?总不能再创建一个新文字内容的组件吧,那连码农都当不了了。
文章开头提到了,复用的关键是函数。函数把要重复使用的代码包裹起来,函数的参数就是要改变的东西,是输入,执行完函数的结果,或者说是输出,就是你最终要的东西。在这里,我们要复用du1dume组件,那么把它包裹进一个函数里,我们想改变文字的内容,那么文字的内容就是这个函数的参数,输出还是这个du1dume组件。还不明白?看代码吧。
<div id="rootElement"></div>
<script src="https://unpkg.com/react@16.8.3/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
const rootElement = document.getElementById('rootElement')
/*
1.du1dume变成了一个函数,函数的参数是文字内容,执行完函数的结果是jsx组件。这里使用的是箭头函数。
2.这里的函数参数,我们用的是一个对象,如其名,里面存放的是该jsx组件的属性配置信息。这里用txtContent属性存放了文字内容。
*/
const du1dume = props => <div>{props.txtContent}</div>
/*
1.container是jsx组件。
2.du1dume是个js函数。
3.在jsx组件中运行js函数,用大括号括起来;传入函数的参数是个对象,对象的txtContent属性存放文字内容,可以动态改变。
*/
const container = (
<div className="container">
{du1dume({txtContent: 'du1dume1'})}
{du1dume({txtContent: 'du1dume2'})}
</div>
)
ReactDOM.render(container, rootElement)
</script>
接下来我们再看看组合。组合就像俄罗斯套娃,你套我来我套你,最后从小娃变成一个大娃。HTML
是个中高手,那么JSX
肯定也是如此。现在我们就来想办法把函数变成JSX
。
之前提到过const du1dume = <div>du1dume</div>
,du1dume
是个JSX
组件,会被Babel
翻译为React.createElement
方法调用。通过查阅官方文档,我们发现React.createElement
方法的第一个参数不仅可以接收一个标签的字符串形式(例如:'div'),还可以接收一个函数作为参数,并且会把props对象传给这个函数,然后这个函数会根据props返回一个新的JSX
组件。说起来有点绕,看代码:
<div id="rootElement"></div>
<script src="https://unpkg.com/react@16.8.3/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
const rootElement = document.getElementById('rootElement')
/*注意,这是个函数*/
const du1dume = props => <div>{props.txtContent}</div>
/*传给createElement方法的第一个参数是一个函数(du1dume),第二个参数会传递给第一个参数,也就是du1dume函数作为参数,名字为props*/
const container = (
<div className="container">
{React.createElement(du1dume, {txtContent: 'du1dume1'})}
{React.createElement(du1dume, {txtContent: 'du1dume2'})}
</div>
)
ReactDOM.render(container, rootElement)
</script>
既然我们可以用createElement
创建组件,就可以转换为JSX
的形式。我们来试着做一下:
<div id="rootElement"></div>
<script src="https://unpkg.com/react@16.8.3/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
const rootElement = document.getElementById('rootElement')
/*注意,这是个函数*/
const du1dume = props => <div>{props.txtContent}</div>
/*传给createElement方法的第一个参数是一个函数(du1dume),第二个参数会传递给第一个参数,也就是du1dume函数作为参数,名字为props*/
const container = (
<div className="container">
<du1dume txtContent="du1dume1" />
{React.createElement(du1dume, {txtContent: 'du1dume2'})}
</div>
)
ReactDOM.render(container, rootElement)
</script>
我们发现第一个组件没有被渲染出来,看下图1到底发生了什么?
图1原来du1dume
被当做字符串而不是函数传递给了createElement
方法。再次经过查阅官方文档得知,React
对任何以小写字母开头的标签都当做DOM
标签,以大写字母开头的标签才当做JSX
。让我们再次修改代码:
<div id="rootElement"></div>
<script src="https://unpkg.com/react@16.8.3/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
const rootElement = document.getElementById('rootElement')
/*注意第一个字母大写*/
const Du1dume = props => <div>{props.txtContent}</div>
const container = (
<div className="container">
<Du1dume children="du1dume1" />
{React.createElement(Du1dume, {txtContent: 'du1dume2'})}
</div>
)
ReactDOM.render(container, rootElement)
</script>
现在,两个组件都正确渲染出来了,现在我们终于可以做套娃了。
<div id="rootElement"></div>
<script src="https://unpkg.com/react@16.8.3/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
const rootElement = document.getElementById('rootElement')
/*注意,这次我们用的是children属性,也就是props里的默认属性之一,这样我们就可以像使用DOM标签一样,在开闭标签之间书写要显示的内容,见下面使用案例。*/
const Du1dume = props => <div>{props.children}</div>
const container = (
<div className="container">
<Du1dume>
我是大娃
<Du1dume>我是小娃</Du1dume>
</Du1dume>
</div>
)
ReactDOM.render(container, rootElement)
</script>
网友评论