以上问题即便本身很清楚,可是否有时却老是道不清,说不明?那么读完本文,就豁然开朗了javascript
JSX添加特定属性
自定义标签拓展了原生HTML标签不具有的能力,最大的一个用处就是属性传值,标签的属性值,能够是字符串,变量对象html
例如:以下所示java
const element = <div divIndex ="0"></div>
固然也可使用下面这种方式,是等价的,用一个大括号{ }将变量包裹起来react
const element = <div divIndex={"0"}></div>
至于更多插值表达式内容,你能够看上一节 React学习(2)-深刻浅出JSX
这里要提一下,在属性中嵌入javascript表达式,不要在双大括号外面加上引号,例如,下面的是错误的web
const element = <div divIndex="{ variable }"></div>
也就是说,对于字符串或者双大括号中的表达式,对于同一属性,不能同时使用这两种符号编程
注意segmentfault
JSX语法是更接近Javascript而不是HTML,只是长得像而已,对于Reat中自定义组件的属性名称,使用 camelCase驼峰式命名来定义属性的名称,例如:定义JSX里的class属性className,而divindex变成 divIndex数组
JSX中的子元素
在原生HTML标签中,要是对于DOM结构树熟悉的话,理解JSX的子元素也是比较容易的微信
原生HTML的标签叫作节点,节点有节点属性,以及节点的内容babel
若是一个标签或者React组件没有内容,你是可使用 />,单标签来闭合的,就像XML语法同样,例如以下所示
const element = <img src={ user.avatarUrl} />
JSX标签里面可以包含不少个子元素
例如:以下所示
const element = ( <div> <h1 title="我是子h1元素属性的内容">我是子h1元素的节点内容</h1> <h2>欢迎关注微信itclanCoder公众号</h2> <h3>川川是全宇宙最帅的小伙子</h3> </div> )
包含在开始和结束标签之间的 JSX 表达式内容将会被做为特定属性 props.children传递给外层组件
其中,有下面几种不一样的方法来传递子元素
你能够将字符串放在开始和结束标签之间,此时 props.children
就只是该字符串,对于内置的HTML元素是颇有用的,但同时要注意怎么接收这个内容
<MyComponent>itclanCoder</MyComponent>
上面的JSX,MyComponent的子元素内容是itclanCoder,能够经过 props.children来获取,它是一个没有转移的字符串 itclanCoder
JSX会移除首尾行以及空行,与标签相邻的空行都会被删除,文本字符串之间的新航都会被压缩一个空格
因此下面的这几种写法都是等价的,可是笔者建议,该换行就换行的
<div>itclanCoder</div> <div> itclanCoder </div> <div> 川川 itclanCoder </div> <div> itclanCoder </div>
在React中,子元素容许由多个JSX元素组成,组件能够嵌套组件,例如:以下所示
<MyContainer> <Header /> <Navigator /> <Aside /> <Footer /> </MyContainer>
在React中,是能够将不一样类型的子元素混合在一块儿的,这跟在之前写HTML是同样的
<div> 七月的天好热 <ul> <li>item1</li> <li>item2</li> <li>item3</li> </ul> </div>
在React组件中,render函数的return的返回值,能够返回一个数组,例如
render() { // return 后面是一个数组 return [ <div key="div1">div1</div>, <div key="div2">div2</div>, <div key='div3'>div3</div> ] } // 固然为了更好的看得舒服些的,最好是定义一个变量的 render() { var aDiv = [ <div key="div1">div1</div>, <div key="div2">div2</div>, <div key='div3'>div3</div> ] return aDiv; }
在插值表达式中,javascript表达式能够被包裹在双大括号 {}中,如下两种写法都是等价的,这跟上面提到的是同样的
<myComponent>川川</myComponent> // 等价于 <myComponent>{'川川'}</myComponent>
至于这种写法的具体实用:对于展现任意长度的列表就很是有用了的,渲染HTML列表
import React from 'react'; import ReactDOM from 'react-dom'; class Item extends React.Component { constructor(props) { super(props); } render() { return ( <ul> <li>{ this.props.message }</li> </ul> ); } } class TodoLIst extends React.Component { constructor(props) { super(props); this.todos = ['起床', '刷牙', '洗脸', '工做']; } render() { return ( <div> { this.todos.map((message) => <Item key = {message} message = { message } />) } </div> ); } } const container = document.getElementById('root'); ReactDOM.render(<TodoLIst />, container);
效果以下所示:
{}插值表达式内能够能够变量,字符串,普通HTML元素,甚至能够是组件,还能够是函数
import React from 'react'; import ReactDOM from 'react-dom'; function Repeat(props){ let items = []; for(let i = 0; i < props.numTimes; i++) { items.push(props.children(i)); } return <div>{ items }</div> } function ListOfTenFun() { return ( <Repeat numTimes={ 10 }> { (index) => <div key={index}>我是列表 { index }</div> } </Repeat> ) } const container = document.getElementById('root'); ReactDOM.render(<ListOfTenFun />, container);
效果以下所示:
上面使用的是两个函数组件,组件里面是能够嵌套另外一组件的,而且属性值能够经过props拿到
也说明了,你是能够将任何东西做为子元素传递给自定义的组件的, 只要该组件渲染以前可以被转换成React理解的对象,它能够用于拓展JSX
自定义的组件必须是大写字母开头
一般来讲,若是在React中小写字母开头的html标签,称为普通元素,它是原生HTML内置的元素(也能够视为为组件),例如: <div><span><a>
会被React转化生成相应的字符串 'div', 'span'
传递给 React.createElement
做为参数
大写字母开头的元素,咱们将它视为自定义的组件,例如 <MyButton />
,其实它最终也会被React.createElement
函数做为转化
使用大写字母开头命名自定义组件,这是一种约定俗成的规定,本质上它就是一构造函数,是为了区别普通函数的,模拟类的功能,但Es6提供了类的语法,之后更多的使用的仍是Es6的class
JSX标签的第一部分指定了React元素的类型
凡是大写字母开头的JSX标签元素,就意味着它们是React组件
若是你定义的一个组件首字母是小写,React就会当作一个普通元素来处理,而原生HTML标签并无把你自定义的元素概括进去,它是会报错的
例如:以下所示
import React from 'react'; import ReactDOM from 'react-dom'; // 如下是定义的函数组件,首字母小写,这个是不正确的 function myButton(props) { return ( <div> <button>{ props.content }</button> </div> ) } function OutButton(){ return ( <myButton content="按钮" /> ); } const container = document.getElementById('root'); ReactDOM.render(<OutButton />, container); // 正确的写法,首字母大写,驼峰式命名 function MyButton(props) { return ( <div> <button>{ props.content }</button> </div> ) } ReactDOM.render(<OutButton />, container);
虽然错误的写法不会报错,它会将 button
认为是一个html普通的标签元素.不会达到预期的效果
注意:
React必须在做用域内,JSX其实就是React.createElement函数的语法糖,React.createElement是更接近底层的API,因此React库也必须包含在JSX代码做用域内
引入React库一部分目的就是为了识别JSX语法的,这也是为何只要你定义一个React组件时,要引入React库的缘由
使用点(.)语法
有时候,在一个模块中须要导出多个React组件时,在JSX中,使用点语法来引用一个React组件就很是方便了的 例如:以下所示
import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; // MyButton组件 class MyButton extends Component { constructor(props){ super(props); } render() { return ( <Fragment> <button>{ this.props.btnContent }</button> </Fragment> ); } } // MyInput组件 class MyInput extends Component{ constructor(props) { super(props); } render() { return ( <Fragment> <input value = { this.props.inputValue } /> </Fragment> ); } } // 搜索部分 class SearchArea extends Component { render() { return ( <Fragment> <FormComponent.MyInput inputValue="我是input组件输入框内容" /> <FormComponent.MyButton btnContent="搜索按钮" /> </Fragment> ); } } let FormComponent = { MyButton: MyButton, MyInput: MyInput } // 或者下面是Es6的一种等价写法 let FormComponent = { MyButton, MyInput } const container = document.getElementById('root'); ReactDOM.render(<SearchArea />, container);
最终结果以下图所示:
上面是把页面中的某一个模块(搜索),把与之相关的组件集中放在一个对象下管理,固然在实际开发中,因人而异了,要是看到别人这么写,也不要以为怪怪的.
拓展运算符,属性展开
对于拓展运算符(...)
,是一个很是有用的语法,若是你已经有了一个props对象,你可使用展开运算符 ...在JSX中传递整个props对象
以下所示:
function PersonA() { return ( <Info name="川川" age="一个靠前排的90后帅小伙" /> ); } // 上面的return后面的等价于 function personA() { const props = { name: "川川", age:"一个靠前排的90后帅小伙"} return ( <Info { ...props } /> ); } function Info(props){ return ( <div>{ props.name }--{ props.age }</div> ); } const container = document.getElementById('root'); ReactDOM.render(<PersonA />, container);
小tips:如何将一对象进行输出?
对于数组对象,能够经过map方法进行输出,然而假如是对象的话,倒是没有这个方法的
具体使用的是Object.keys(对象)这个方法,它会返回一个数组,而且将对象的属性名保存在一个数组中,若是是要获取对象的属性值,则能够先转数组,而后在使用数组的一些方法:例如map方法进行处理一下
var obj = { name: "川川", age: "你猜,小鲜肉一枚" } var getAttr = Object.keys(obj); var getValue = Object.keys(obj).map((item) => obj[item]); console.log(getAttr); // ["name", "age"] console.log(getValue);// ["川川", "你猜,小鲜肉一枚"]
以下真实例子所示
import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; class List extends Component { constructor(props) { super(props); // 下面是为简化代码,绑定this this.content = this.props.content; this.value = this.props.value; } render() { return ( <Fragment> <ul> { <li>{ this.content }-- { this.value }</li> } </ul> </Fragment> ); } } class Person extends Component { constructor(props) { super(props); this.person = { name: "川川", age: "一个靠前排的90后帅小伙", desc: "欢迎关注微信itclanCoder公众号" } } render() { let getPerson = Object.keys(this.person); return ( <Fragment> { getPerson.map((item) => <List key = { item } content = { item } value = { this.person[item]} /> ) } </Fragment> ); } } const container = document.getElementById('root'); ReactDOM.render(<Person />, container);
最终的效果以下所示:
JSX中的props
自定义组件定义的属性称为prop,而属性值称为prop值,因为组件能够定义多个属性,因此能够有多种方式在JSX中指定props
因为JSX会被转换为React.createElement(组件元素, 属性对象, 子元素),例如:以下JSX
const info = { title:"我是一个组件", number: 20 } // 将info对象存储到infoMessage变量属性中,并传给MyComponent组件 <MyComponent infoMessage = { info }>my component</MyComponent> // 最终会被转化为 React.createElement(MyComponent, { infoMessage: info}, 'my component')
对于怎么校验JSX转换为React.createElement()能够去babel在线编译的官网校验的
打开以下网址便可
调用组件处,被称为父组件,而定义组件处,被称为子组件,对应的子组件想要接收父组件的值,用 props去接收
label中的htmlFor
在原生html标签中label与input中的for与id结合使用,增大鼠标的触控范围,起到加强用户体验的做用
for在JSX中应该被写做 htmlFor
<label htmlFor="firstname">First name:</label> <input type="text" name="firstname" id="firstname">
结果以下所示
结语
本文主要讲述在JSX中添加属性的命名方式应是camelCase驼峰式命名来定义属性的名称,JSX中的子元素能够是字符串,能够嵌套,以及js表达式,函数均可以做为子元素
而且在React中组件的定义以及调用处,组件名称首字母必需要大写,当导出多个React组件时,使用点语法来引用一个React组件
使用展开运算符 ...在JSX中传递整个props对象
某些时候,是一个很是有用的语法,另外,当遍历要渲染的是一对象时,对象并无数组的一些方法,经过Object.keys()进行转换,而后在使用.可以获得对象的属性以及属性值
也知道JSX中的何为prop,以及怎么去接收props值
对于label与input使用时,要注意的一些地方.
固然对于JSX的相关知识学习暂且就这么多了,仍然还有不少东西要学习的,编程是一门不断探索的艺术,但愿分享的这些的这些对你有些用