什么是jsx
JSX是一种JavaScript的语法扩展(eXtension),也在很多地方称之为JavaScript XML,因为看起来就是一段XML语法; JSX其实是嵌入到JavaScript中的一种结构语法,在javaScript中以一定的结构实现。
React认为渲染逻辑本质上与UI逻辑存在内在耦合
比如UI需要绑定事件(button、a原生等等);比如UI中需要展示数据状态,在某些状态发生改变时,又需要改变UI; 所以事件和结构是可以放在一起的。 他们之间是密不可分,所以React没有讲标记分离到不同的文件中,而是将它们组合到了一起,这个地方就是组件 (Component);
JSX的书写规范
JSX的顶层只能有一个根元素,我们很多时候会在最外层包裹一个div(后续React推出了不占据Dom结构的Fragment) 为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写; JSX中的标签可以使单标签,也可以是双标签,如果是单标签,必须以/>结尾
JSX中的注释
单行注释和多行注释,都需要在大括号{}中编写 { //我是单行注释 } {/我是一段注释/}
JSX中嵌入变量
当变量是Number、String、Array类型时,可以直接显示; 当变量是null、undefined、Boolean类型时,内容显示为空(如果想让其展示可以将其转换为字符串进行展示); 对象类型不能作为变量嵌入('not valid as a React child')
{ // 1.在{}中可以正常显示显示的内容 name: "lanzhou", // String age: 20, // Number names: ["abc", "cba", "nba"], // Array
// 2.在{}中不能显示(忽略)
test1: null, // null
test2: undefined, // undefined
test3: true, // Boolean
// 3.对象不能作为jsx的子类
friend: {
name: "lanzhou",
age: 20
}
}
JSX嵌入表达式
运算表达式 三元运算符 执行一个函数
render() { const {firstName, lastName, isLogin} = this.state; return (
{ firstName + " " + lastName }
{20* 50}
{/2.三元表达式/}{ isLogin ? "欢迎回来~": "请先登录~" }
{/3.进行函数调用/}{this.sayHello()}
JSX绑定属性
JSX绑定普通属性 JSX绑定class JSX绑定style render() { const { title, imgUrl, link, active } = this.state; return (
我是标题
<img src={getSizeImage(imgUrl, 140)} alt=""/> 百度一下 {/* 2.绑定class */}
<div className="box title">我是div元素</div>
<div className={"box title " + (active ? "active": "")}>我也是div元素</div>
{/* 3.绑定style */}
<div style={{color: "red", fontSize: "50px"}}>我是div,绑定style属性</div>
</div>
)
JSX绑定事件
JSX中绑定事件类似在HTML原生中绑定事件,只不过React中事件命名采用小驼峰(camelCase),而不是纯小写; 但是我们会发现在我们绑定的回调事件中访问我们对应的this会是undefined,这是因为对应的回调函数是React内部帮我们去进行调用的,React无法确定对应的this所以采用的是callback.apply(undefined,[])方式调用,改变了this的指向为undefined。但是我们往往需要访问到的this是我们React组件对象。解决方法有以下三种:
increment = () => { console.log(this); } render() { return (
{/* 2.方案二: 定义函数时, 使用箭头函数 */}
<button onClick={this.increment}>+1</button>
{/* 2.方案三(推荐): 直接传入一个箭头函数, 在箭头函数中调用需要执行的函数*/}
<button onClick={() => { this.decrement(666) }}>-1</button>
</div>
)
}
绑定事件参数的传递,推荐采用绑定this的方案三,既方便的传递我们想要传递的参数,还可以非常简单的获取到事件对象event
render() { return (
-
{
this.state.movies.map((item, index, arr) => {
return (
<li className="item"
onClick={ e => { this.liClick(item, index, e) }}
title="li">
{item}
)
})
}
JSX条件渲染
某些情况下,页面会根据不同的条件展示不同的内容,或者决定是否渲染某部分内容。 在Vue中给我们提供了对应的v-if、v-show指令,然而React中实现条件渲染的方式有那些呢?
条件判断语句 三元运算符 与运算符 && v-show效果(主要是控制html标签的display属性是否为none)
render() { const { isLogin } = this.state;
// 1.方案一:通过if判断: 逻辑代码非常多的情况
let welcome = null;
let btnText = null;
if (isLogin) {
welcome = <h2>欢迎回来~</h2>
btnText = "退出";
} else {
welcome = <h2>请先登录~</h2>
btnText = "登录";
}
return (
<div>
{welcome}
{/* 2.方案二: 三元运算符 */}
<button onClick={e => this.loginClick()}>{isLogin ? "退出" : "登录"}</button>
<h2>{isLogin ? "你好啊, 666": null}</h2>
{/* 3.方案三: 逻辑与&& */}
{/* 逻辑与: 一个条件不成立, 后面的条件都不会进行判断了 */}
<h2>{ isLogin && "你好啊, 666" }</h2>
{ isLogin && <h2>你好啊, 666</h2> }
</div>
)
}
{/* 4.方案四: 根据一个状态动态更改对应标签的display属性的值为block或none */} render() { const { isLogin} = this.state; const titleDisplayValue = isLogin ? "block": "none"; return (
JSX列表渲染
在React中列表生成及展示运用最多的是js中高阶函数,当然我们也可以运用for循环来进行列表的生成及展示。 render() { return (
名字列表
-
{
this.state.names.map(item => {
return
- {item} }) }
<h2>数字列表(过滤1)</h2>
<ul>
{
this.state.numbers.filter(item => {
return item >= 50;
}).map(item => {
return <li>{item}</li>
})
}
</ul>
<h2>数字列表(过滤2)</h2>
<ul>
{
this.state.numbers.filter(item => item >= 50).map(item => <li>{item}</li>)
}
</ul>
<h2>数字列表(截取)</h2>
<ul>
{
this.state.numbers.slice(0, 4).map(item => {
return <li>{item}</li>
})
}
</ul>
</div>
)
}
JSX本质浅析
JSX实际上仅仅是React.createElement(type, config, children)方法的语法糖,该方法接收三个参数: type,当前ReactElement的类型,如果是标签元素,那么使用字符串表示“div”,如果是组件元素直接使用组件的名称就可以。 config,我们在JSX中绑定的属性会在config对象中以键值对的形式存在。 children,存放标签中的内容,以children数组的形式存储 我们知道JSX是通过babel进行解析的,我们编写JSX需要依赖babel。
如果我们直接使用React.createElement()来编写代码,就不需要以来bable进行解析也可以正常的渲染显示。
我们通过React.createElement()方法最后返回得到的是一个ReactElement对象,这个ReactElement对象作用是什么?其实React利用ReactElement对象组成了一个JavaScript对象树,这个对象树就是我们经常讲的一个概念--虚拟DOM
流程大概如下: 首先是我们编写的JSX代码经过bable编译解析成对应的React.createElement()方法形式,经过React.createElement()方法调用返回我们对应的ReactElement对象树(虚拟DOM树),对应的ReactElement对象树经过ReactDOM.render()方法转换为真正的DOM在我们的浏览器进行渲染。
为什么采用虚拟DOM呢?
很难跟踪状态发生的改变:原有的开发模式,我们很难跟踪到状态发生的改变,不方便针对我们应用程序进行调试; 操作真实DOM性能较低:传统的开发模式会进行频繁的DOM操作,而这一的做法性能非常的低; DOM操作非常耗费性能: document.createElement本身创建出来的就是一个非常复杂的对象 link.juejin.cn/?target=htt… DOM操作会引起浏览器的回流和重绘,所以在开发中应该避免频繁的DOM操作