在Jq,原生javascript时期,在写页面时,每每强调的是内容结构,层叠样式,行为动做要分离,三者之间分工明确,不要耦合在一块儿javascript
然而在React出现后,一切皆js,对于在JS里面写HTML代码,刚开始是很是反感的,甚至有违背当初的原则前端
可是,对于原先那种仅仅是把三种语言技术放在了三种不一样文件位置里进行分开管理了,实际上,它并无实现逻辑上的分离java
既然前端UI显示就是HTML,CSS,javascript,那么把实现一个功能的全部代码放在一个文件里管理,也是一种宏观上代码的封装,模块化处理.react
使用JSX并非倒退,它只是一个语法糖而已,虽然在React中,不强制要求使用JSX,可是官方却推荐使用.android
由于在javascript代码中将JSX和UI放在一块儿在视觉上有辅助做用,另外,它还可使React显示跟过有用的错误和警告信息数组
下面就一块儿来学习下JSX吧,当你习惯它以后呢,并不会嗤之以鼻,反而会引觉得爱的!浏览器
正文从这里开始~微信
JSX是什么?
全称: javascript and XMLbabel
定义: 可拓展(自定义)标记性语言,基于javascript,融入了XML,咱们能够在js中书写xml,使用JSX能够很好的描述UI在页面中应该呈现它应有的交互形式cookie
相似下面的这种,非官方提供的普通标签,而是本身定义具备必定含义的特殊标签
<person> <name></name> <age></age> <height></height> <weight></weight> </person>
其实,你可把这些自定义的标签,称为组件,页面中的某一部分,具备独立的功能和逻辑. 实现组件化的好处,不言而喻,下面来看看React的JSX是怎么样的
当你用create-react-app
脚手架,初始化一个react应用后,在入口文件index.js中最后一行代码,ReactDOM.render()
函数调用的第一个实参数的写法<App />
import React from 'react'; // 引入react.js库,并用import关键字定义实例化了一个React对象 import ReactDOM from 'react-dom'; // 引入react-dom.js,同上,实例化了ReactDOM对象 ReactDOM.render(<App />, document.getElementById('root')) // 将App组件经过ReactDOM.render()函数,挂载到root根节点上,插入到页面中去
为了更好的理解,你能够在index.js中,将代码更改为以下
const element = <App />; const container = documnent.getElementById("root"); ReactDOM.render(element, container);
其中ReactDOM是react-dom的一个实例对象,它是用来将虚拟dom转换为真实DOM的,ReactDOM实例化对象下的一个render方法,接收两个实际参数,第一个实参数,是要渲染的组件,第二个实参数,是该组件的挂载点,将该组件渲染到什么位置上,上面是渲染到根节点root上
ReactDOM.render(要渲染的组件, 组件要挂载的位置);
其中相似这种JSX:
const element = <h1 title="h1标签">Hello,itclanCoder</h1> // 等价于 var element = React.createElement('h1',{title:"h1标签"}, "hello, itclanCoder" ); // React.createElement() 会预先执行一些检查,以帮助你建立了这么一个对象,可是在实际中不要这么写,它是会报错的 var element = { type: 'h1', props: { title: "h1标签", children: "hello,itclanCoder" } }
这些对象被称为 “React 元素”。它们描述了你但愿在屏幕上看到的内容。React经过读取这些对象,而后使用它们来构建 DOM 以及保持随时更新
注意:
Fragment
(也叫占位符)这个内置组件将你写的JSX子元素给包裹起来,能够包含子节点 ,也支持插值表达式 {表达式}以下代码所示:
import React from "react"; import ReactDOM from "react-dom"; class Acomponent extends React.Component { render() { // return 后面带着一个圆括号,只是为了换行显示,根节点最顶层只能是一个元素 return ( <div> <h1 title="我是川川">一个靠前排的90后帅小伙</h1> <h2>欢迎关注微信itclanCoder公众号</h2> </div> ) } } // 或者使用React提供的Fragement占位符组件也能够,可是先引入 import React, { Componnet, Fragment } from "react"; import ReactDOM from "react-dom"; class Acomponent extends Component { render() { return ( <Fragment> <h1 title="我是川川">一个靠前排的90后帅小伙</h1> <h2>欢迎关注微信itclanCoder公众号</h2> </Fragment> ) } }
下面来具体来看看JSX是如何使用的
JSX的具体使用
双大括号内能够是变量,字符串,数组,函数调用, 可是不能够是对象,也不支持 if,for语句
例如:你在插值表达式里写对象:它是会报错的
{ {name: "川川", age: "一个靠前排的90后帅小伙"} }
错误以下所示:
Objects are not valid as a React child (found: object with keys {name, age}). If you meant to render a collection of children, use an array instead
该错误的意思是:对象无效做为React子对象(找到:具备键{name,age}的对象)。若是您要渲染子集合,请使用数组
固然若是是数组的话,它会自动的给拼接起来,本质上是经过数组中的join("")方法处理后的结果
{ ["川川", "全宇宙最帅"]} //川川全宇宙最帅
固然对于在JSX里面写if,for语句也是会报错的
<li> { if(this.isBtn) { <Button /> } </li>
其实,JSX 也是一个表达式,它虽然不支持if,for语句,可是它在if,for循环的代码块中是可使用JSX的,将JSX赋值给变量,把JSX看成参数传入,以及从函数中返回JSX
function getMessage(user) { if (user) { return <h1>Hello, { formatName(user) }!</h1>; } return <h1>Hello, itClanCoder.</h1>; }
注意:布尔类型、Null 以及 Undefined 将会被忽略,false, null, undefined, true是合法的子元素。但它们并不会被渲染。如下的 JSX 表达式渲染结果都是相同的
<div /> <div></div> <div>{ false }</div> <div>{ null }</div> <div>{ undefined }</div> <div>{ true }</div>
具体做用: 这有助于在特定条件来渲染其余的 React 元素。例如,在如下 JSX 中,仅当 isBtn 为 true 时,才会渲染 <Button />
<div> { isBtn && <Button /> } <Content /> </div>
有一点须要注意的是:有一些false值,例如:数字0,仍然会被React渲染,例如:以下所示
<div> { this.aBtns.length && <Button content="我是按钮" /> } </div>
要解决这个问题,确保 && 以前的表达式老是布尔值,就能够了
反之,若是你想渲染 false、true、null、undefined 等值,你须要先将它们转换为字符串:
转换字符串有以下三种方法
<div> <p>对象.toString(){ myVariable.toString() }</p> <p>用空字符串拼接{ myVariable + '' }</p> <p>用String(variable){ String(myVariable) }</p> </div>
固然,插值表达式中变量也能够用Es6中的反引号
hello, { `${String(false)}` } // false
介绍了那么多,依然仍是不够的,下面来看看JSX的原理,理解了这个,你将会知道一个JSX到底是怎么工做,以及怎么渲染到页面上去的
JSX原理
页面中的DOM元素结构均可以用javascript对象来描述,包括的信息有,标签名,属性,子元素,事件对象
在JS里面,一切皆对象,对象的特色就是,含有属性或者方法,,其实任何东西,均可以用对象去描述
例如:以下的JSX结构
<div class="input-wrap"> <input type="text" autocomplete="off" value="" id="mq" class="input" title="请输入搜索文字" /> <button>搜索</button> </div>
假如用对象来描述一下上面的信息
{ tagName: 'div', attribute: { className: 'input-wrap'}, children: [ { tagName: 'input', attribute: { type: "text", autocomplete:"off", value:"", id:"mq", class:"input", title:"请输入搜索文字" } }, { tagName: "button", attribute: null, children: '搜索' } ] }
当直接把这个HTML段代码写在React中,它背后实际上是经过React.createElement()方法进行建立的,建立相似这样的
{ type: 'div', props: {className: 'input-wrap' }, children: [ { type: 'input', props: { type:'text', autocomplete:"off", value:"",id:"mq", class:"input", title:"请输入搜索文字" }, { type: 'button', props: null, children: '搜索' } ] }
你能够联想一下原生javascript的document.createElement()与JQ中的$("")建立一个js对象与jQ对象的,而在React中,React就是一个实例化对象,更深层次探讨的话,React也是基于原型对象构建出来的
尽管React与前二者不一样,可是笔者仍然以为有相似,殊途同归之妙,例如React下面的createElement方法,仍然与原生document文档对象下面的建立元素方法相同
若是原生javascript扎实的话,便不难理解React在这作了一层转化
既然js对象描述的UI(DOM)信息与HTML所展现的结构信息是同样的,那为何不用Js对象来代替呢,由于用对象字面量写的方式太繁琐了,又臭又长的,结构又不清晰,若是用HTML来展现UI信息,那么就简单多了
React.js 就把js语法扩展了一下,让 Js语言可以支持这种直接在Js代码里面编写相似 HTML 标签结构的语法,这样写起来就方便不少了。编译的过程会把相似 HTML 的 JSX 结构转换成 JavaScript 的对象结构
上面的代码:
import React from 'react' import ReactDOM from 'react-dom' class Search extends React.Component { render () { return ( <div class="input-wrap"> <input type="text" autocomplete="off" value="" id="mq" class="input" title="请输入搜索文字" /> <button>搜索</button> </div> ) } } ReactDOM.render( <Search />, document.getElementById('root') )
通过babel编译,Babel 会把 JSX 转译成一个名为 React.createElement()
函数调用
以下所示
import React from 'react' import ReactDOM from 'react-dom' class Search extends React.Component { render () { return ( React.createElement( "div", {className: 'input-wrap'}, React.createElement( "input", { type:'text', autocomplete:"off", value:"", id:"mq", class:"input", title:"请输入搜索文字" } ), React.createElement( 'button', null, "搜索" ) ) ) } } ReactDOM.render( React.createElement(Search, null), document.getElementById('root') );
换言之,若是你自定义的一个组件:例如:<ElButton bgColor="green">绿色按钮</ElButton>
import React from 'react'; import ReactDOM from 'react-dom' class ElButton extends React.Component { constructor(props){ super(props); } render() { return ( <button style={ {color: this.props.bgColor} }>{ this.props.children }</button> ) } } ReactDOM.render(<ElButton bgColor="green">绿色按钮</ElButton>, document.getElementById('roo
通过Babel的转化后
React.createElement( ElButton, { bgColor: green}, children: "绿色按钮" )
最终渲染到浏览器上,结果以下所示
在编译以后,JSX 表达式会被转为普通 JavaScript 函数调用,而且对其取值后获得 JavaScript 对象
React.createELmenet会构建一个js对象来描述你的HTML结构信息,包括标签名,属性,子元素以及事件对象等
使用React必定要引入React库,引入这个是为了解析识别JSX语法糖(React.createElement()函数的替代)
固然另外一方面也是为了建立虚拟DOM(所谓虚拟DOM,它就是一个JS对象,是用它来描述真实的DOM,上面的例子,已经很明白了)
而引入react-dom的缘由就是,为了将虚拟DOM转换为真实DOM,而后把这个DOM元素插入到页面中,这正是ReactDOM.render()
作的事情,把组件渲染而且构造 DOM 树,而后插入到页面上某个特定的元素上
因此在你编写一个组件的时候,一开始就要引入react.js和react-dom这两个文件的
当使用JSX到最终展示页面结构到浏览器上:经历了以下过程:若是你在代码中进行断言一下,就很是清晰这一过程了
因此概括一下:JSX其实就是javascript对象,是用来描述UI结构信息的,JSX语法并非真实的DOM, 使用JSX是为了方便开发人员写代码更简单,简洁
固然实际开发中,咱们并不会去用React.createElement()去建立元素,不是说它不能完成需求,只是由于它写起来比较鸡肋,代码维护起来很是麻烦,可读性差
相比于写JS,写HTML仍是比较容易吧,但也是不简单的哦,由于写JS比较烧脑,容易掉头发呀,HTML自己是不具有逻辑可言的
然而,到手的人民币的高低,更多的是取决于你的JS水平...,这个的确是滴,JS水平高,真的是能够直接喊高价的
小结
JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML,但并非 HTML,附加了原生HTML标签不具有的能力,例如:自定义属性,以及后续的组件传值
UI界面显示什么样,取决于JSX对象结构,换句话说,取决于render()函数里面的return关键字后面返回的JSX结构
引入React.js库是为了解析识别JSX语法,同时建立虚拟DOM,而引入react-dom是为了渲染组件,将组件挂载到特定的位置上,同时将虚拟DOM转换为真实DOM,插入到页面中
总结
本文主要讲述了JSX是什么?以及JSX的一些注意事项,JSX的具体使用,嵌入表达式,最重要的是JSX的原理,在使用JSX中,react是如何将jsx语法糖装换为真实DOM,并渲染到页面中的,固然,JSX仍然还有一些注意事项,边边角角的知识的,限于篇幅,贪多嚼不烂,咱们下次再继续了