React从入门到精通系列之(12)深入理解JSX
十二、深入理解JSX从根本上讲,JSX就是提供了一个 <MyButton color="blue" shadow={2}> Click Me </MyButton> 经过编译后为: React.createElement( MyButton,{color: 'blue',shadow: 2},'Click Me' ) 如果一个标签没有子元素的话,你可以使用 <div className="sidebar" /> 经过编译后为: React.createElement( 'div',{className: 'sidebar'},null ) 如果你想测试一些特定的JSX是如何转换成JavaScript的话,你可以试试 指定React元素类型JSX标记的第一部分决定了React元素的类型。 首字母大写的类型表示JSX标记指的为React组件。 这些标签被编译为对指定变量的直接引用,因此如果使用JSX React必须在作用域内由于JSX编译的本质是对 import React from 'react'; import ReactDOM from 'react-dom'; function WarningButton(props) { // return React.createElement(CustomButton,{color: 'red'},null); return <CustomButton color="red" /> } 如果不使用JavaScript打包工具并将React通过script标签引入,那么它就会作为一个全局变量 对JSX类型使用『点』表示符您还可以使用JSX中的点表示符来引用React组件。 如果您有一个模块会导出很多React组件的话,使用这种方法就会十分方便。 例如,如果 import React from 'react'; import ReactDOM from 'react-dom'; const MyComponents = { DatePicker(props) { return <div>这里有一个颜色为{props.color}的日期选择器</div> } }; function BlueDataPicker(props) { return <MyComponents.DatePicker color="blue" /> } ReactDOM.render( <BlueDataPicker />,document.getElementById('root') ); 用户自定义组件必须是首字母大写当元素类型以是小写字母开头时,它指向一个内置组件,如 我们建议使用 下面代码不会按预期运行: import React from 'react'; //这是错误的,这个组件应该为首字母大写 function hello(props) { // 这是正确的,因为div是一个有效的html标签 return <div>Hello {props.name}</div>; } function HelloWorld(props) { // 这是错误的,因为它是首字母小写,所以React认为<hello />是一个html标签 return <hello name="zhangyatao" /> } 想要修复上面的问题,我们必须将 import React from 'react'; // 这是正确的 function Hello(props) { return <div>Hello {props.name}</div>; } function HelloWorld(props) { // 这是正确的 return <Hello name="zhangyatao" />; } 在运行的时候选择组件类型不能将常规的javascript表达式用作React元素类型。 如果你想使用一个通用表达式来表示元素的类型,只需将它赋值给一个首字母大写的变量即可。 import React from 'react'; import {Com1,Com2} from './Components'; const components = { myCom1: Com1,myCom2: Com2 } function RunCom(props) { // 这是错误的,JSX的类型不能这么写 return <components[props.comType] type={props.type} />; } 想要解决上面的问题,只需要将它们赋值给一个首字母大写的变量即可: import React from 'react'; import {Com1,Com2} from './Components'; const components = { myCom1: Com1,myCom2: Com2 } function RunCom(props) { // 这是正确的,将它们赋值给一个首字母大写的变量 const MyCom = components[props.comType]; return <MyCom type={props.type} />; } JSX中的Props在JSX中指定Props有以下几种不同的方法。 JavaScript表达式你可以传递任何JavaScript表达式作为Props,用 <MyComponents foo={1 + 2 + 3 + 4} /> 对于
function NumberDescriber(props) { let description; if (props.number % 2 === 0) { description = <strong>偶数</strong> } else { description = <strong>奇数</strong> } return <div>{props.number}是一个{description}.</div>; } 字符串直接量你可以传递一个字符串内容作为props。 这两个JSX表达式是等价的: <MyComponent message="hi zhangyatao" /> <MyComponent message={'hi zhangyatao'} /> 当你传递一个字符串直接量时,它的值是经过html转义的。 所以这两个JSX表达式是等价的: <MyComponent message='<3' /> <MyComponent message={'<3'} /> Props默认值为true如果你没有给Props传入一个值,那么它的默认值为 <MyTextBox autocomplete /> <MyTextBox autocomplete={true} /> 一般来说,我们不建议使用它,因为它可以使用ES6对象的简写 Props传递如果你有一个对象类似的数据作为props,并且想在JSX中传递它,你可以使用 function App() { return <Greeting firstName="yatao" lastName="zhang" />; } function App() { const props = {firstName: 'yatao',lastName: 'zhang'}; return <Greeting {...props} />; } 当创建一个通用容器时, JSX中的子元素和子组件在包含开始标记和结束标记的JSX表达式中,这些标记之间的内容通过一种特殊的prop: 字符串直接量你可以在开始和结束标签之间放一个字符串,那么 function MyComponent(props) { return <div>{props.children}<div>; //=> <div>hello zhangyatao</div> } <MyComponent>Hello zhangyatao</MyComponent> 这是有效的JSX,并且 <div>这是一个html标签 & 同时也是个JSX</div> JSX会删除行的开始和结尾处的空格。 它也会删除中间的空行。 与标签相邻的空行被会被删除; <div>hello zhangyatao</div> <div> hello zhangyatao </div> <div> hello zhangyatao </div> <div> hello zhangyatao </div> JSX子元素你可以使用很多个JSX元素作为子元素。 这对需要嵌套的显示类型组件很有用: <Dialog> <DialogHeader /> <DialogBody /> <DialogFooter /> </Dialog> 你可以将不同类型的子元素混合在一起,因此JSX子元素可以与字符串直接量一起使用。 这是JSX的另一种方式,就像一个HTML一样: <div> 这是一个列表 <ul> <li>item 1</li> <li>item 2</li> </ul> </div> 一个React组件不可能返回多个React元素,但是一个JSX表达式可以包含多个子元素,因此如果你想让一个组件渲染多个东西,你可以将它们统一放置在就像上面那样的div中。 Javascript表达式您可以将任何JavaScript表达式放在 function MyComponent(props) { return <div>{props.children}<div>; //=> <div>hi zhangyatao</div> } <MyComponent>hi zhangyatao</MyComponent> <MyComponent>{'hi zhangyatao'}</MyComponent> 这通常用于渲染任意长度的JSX表达式列表。 例如,这将渲染一个HTML列表: function Item(props) { return <li>{props.message}</li>; } function TodoList(props) { const todos = ['完成文档','出去逛街','打一局dota']; return ( <ul> {todos.map(message => <Item key={message} message={message} />)} </ul> ); } JavaScript表达式可以与其他类型的子元素混合使用。 这通常用于替换字符串模板: function Hello(props) { return <div>Hello {props.name}</div>; } 使用函数作为子元素通常,插入JSX中的JavaScript表达式都最终返回为一个字符串、React元素、一个列表。 当然, import React from 'react'; import ReactDOM from 'react-dom'; function Repeat(props) { let items = []; let callback = props.children; var numTimes = props.numTimes; for(var i = 0 ; i < numTimes ; i++ ){ items.push(callback(i)); } return <div>{items}</div>; } function ListOfTenThings(props) { return ( <Repeat numTimes={10}> {index => <div key={index}>这是列表中的第{index}项</div>} </Repeat> ); } ReactDOM.render( <ListOfTenThings/>,document.getElementById('root') ); 传递给自定义组件的子元素可以是任何东西,只要在React在渲染之前,该组件将它们转换为可以理解的东西即可。 这种用法并不常见,如果你想扩展JSX的其他能力,可以通过这个例子了解下它的工作原理。 布尔值、null、undefined在渲染时会被自动忽略
<div /> <div></div> <div>{false}</div> <div>{null}</div> <div>{true}</div> 这对于有条件地呈现React元素很有用。 如果 <div> {showHeader && <Header />} <Content /> </div> 如果返回一些 <div> {props.messages.length && <Message messages={props.messages} />} </div> 想要修复上面的问题,你要确定这个表达式在&&之前总返回 <div> {props.messages.length > 0 && <Message messages={props.messages} />} </div> 相反,如果你想要一个值如 import React from 'react'; import ReactDOM from 'react-dom'; function MyVariable(props) { const myVariable = false; // 如果这里不把false转换为字符串,这只会输出『我的javascript变量是』 const convertedVar = String(myVariable); return ( <div> 我的javascript变量是{convertedVar} </div> ); } ReactDOM.render( <MyVariable/>,document.getElementById('root') ); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |