前端基础之《React(10)—JSX语法》
一、理解JSX
1、JSX是JavaScript XML,是一种语法,由Meta公司发布,浏览器是不支持这种语法的
2、在编写React组件视图结构时,JSX是可选的
JSX语法:
function B(props) {
return (
<div>
<h1>你好</h1>
</div>
)
}
不用JSX语法,用React官方API:
function B() {
return React.createElement('div', {}, React.createElement('h1', {}, '你好'))
}
可以使用React.createElement('tag', {}, [])编写视图结构,组件是一定要有视图结构的
3、JSX语法最终会被@babel/preset-react进行编译,编译的结果就是React.createElement()这种语法
4、要随时有能力把JSX语法转换成React.createElement()语法,反之亦然
5、什么是JSX元素:React.createElement()的结果,是变量,也是对象,并且是不可变对象
例子:React.createElement('div', {}, '你好') 等价于 <div>你好</div>
const element1 = <div>你好</div>
console.log('---element1', element1)
const element2 = React.createElement('div', {}, '你好')
console.log('---element2', element2)
控制台打印:

可以看到element1和element2都是react.transitional.element类型
6、为什么JSX元素要设计成不可变对象
因为JSX元组最终会被渲染成真实DOM,所以不能直接操作“原材料”。要改变只能采用声明式操作
7、元素和组件的区别
组件是由class或function定义的东西,叫组件
元素是由JSX语法或React.createElement()返回的结果叫做元素
组件实例化了就是元素
二、JSX语法细节
1、在JSX中可以嵌套表达式,使用{}来嵌套
在JSX视图中,凡是动态的变量(表达式)都使用{}包起来
const hello = '你好'
const title = '标题'
function B() {
return (
<div title={ title }>
<h1>{ hello }</h1>
</div>
)
}
2、当JSX定义视图比较复杂时,建议换行,像HTML那样对齐,换行后建议用()把JSX元素整体包裹起来
const ele = (
<div>
<h1>你好</h1>
</div>
)
3、JSX写法是变量,也是表达式,所以JSX元素可以作为函数的入参,也可以作为函数的返回值,还可以用在if/for循环中
function handle (arg) {
if (arg) {
return <div>{arg}</div>
} else {
return <div>你好</div>
}
}
调用:
handle('你好')
handle(100)
handle(<span>大家好</span>)
如果arg是个JSX,能不能在{}内对它做操作,<div>{arg + 1}</div>?
回答:不能,arg是JSX不要做操作,直接渲染就行了
4、JSX语法有三个HTML属性发生了变化:
(1)className代替class,因为JSX中class是关键字
(2)tabIndex代替tabindex,因为JSX使用小驼峰命名法
(3)htmlFor代替for,因为和for循环的for重复
5、JSX语法中有三个新增的属性
(1)key,用于列表渲染
(2)ref,快捷的DOM访问方式
(3)dangerouslySetInnerHTML,用于渲染一段HTML片段
举例:
我们写了一个变量content,React默认是字符串,不会解析标签,就按照字符串显示
const hello = '你好'
const title = '标题'
function B() {
return (
<div title={ title }>
<h1>{ hello }</h1>
<div>{ content }</div>
</div>
)
}
const content = '<div><a href="https://www.baidu.com">跳转</a></div>'
export default B

使用dangerouslySetInnerHTML属性:
const hello = '你好'
const title = '标题'
function B() {
return (
<div title={ title }>
<h1>{ hello }</h1>
<div dangerouslySetInnerHTML={{ __html: content }}></div>
</div>
)
}
const content = '<div><a href="https://www.baidu.com">跳转</a></div>'
export default B

React写进{}内的东西,不允许被当作代码块解析,是为了防止xss攻击和代码注入
6、JSX中,不仅自定义组件可以使用单闭合,任何html标签都可以用单闭合
7、JSX中,内联style的语法,<div style={{cssKey1:'cssValue1', cssKey2:'cssValue2'}} />
8、className语法:<div className='box' className={cc}></div>
box是字符串,cc是变量或表达式
9、在JSX中,使用{}渲染后端接口数据,默认支持防注入攻击(XSS)
10、JSX是对象,因为Babel将JSX编译成React.createElement()调用的返回值,这个返回值是对象结构,所以jSX是对象。这种JSX对象就是“Fiber单元”,Fiber树就是由这些单元串联起来的,是一个双向链表结构
三、深入JSX
1、从本质上讲,JSX只是React.createElement()函数提供的语法糖
2、如果节点不存在子节点,可以使用自闭合格式的标签
3、如果你希望测试某些特别的JSX是如何被转换成JavaScript的,可以尝试使用在线Babel编译器
4、一个JSX标签的开始部分决定了React元素的类型
所有的React组件(由class或function定义)的组件名称,都必须以大写字母开头。比如<A />、<MyButton />
// 这是普通的函数声明,不是JSX语法支持的组件,用法:b()
function b () {
return (
<div>你好</div>
)
}
// 这才是真正的React组件,支持JSX语法,用法:<B />
function B () {
return (
<div>你好</div>
)
}
5、因为JSX被编译为React.createElement的调用,所以React库必须在你JSX代码的作用域中
6、JSX支持“点语法”调用组件,比如React.Component、<B.Button />
const QQ = {
Button () {
return (<button>点击</button>)
},
Model: function () {
return (<div>弹框</div>)
}
}
使用:
<QQ.Button />
<QQ.Model />
7、不能使用一个普通表达式作为React元素类型,表达式要赋值给一个以大写字母开头的变量
例如:App是父组件,B是子组件
import PropTypes from 'prop-types';
function PhotoList (props) {
return <h1>照片列表 { props.num } 条</h1>;
}
function VideoList (props) {
return <h1>视频列表 { props.num } 条</h1>;
}
const pv = {
photo: PhotoList,
video: VideoList
};
function B(props) {
const MediaList = pv[props.type||'photo'];
return (
<div>
<MediaList num = {5} />
</div>
);
}
// 添加 PropTypes 验证
B.propTypes = {
type: PropTypes.string
};
PhotoList.propTypes = {
num: PropTypes.number
};
VideoList.propTypes = {
num: PropTypes.number
};
export default B;
在return里不能直接用pv变量,要把pv变量赋值给一个以大写字母开头的变量
效果:![]()
8、props属性
(1)对自定组件来讲,props是自定义属性
(2)用{}包裹的JavaScript表达式可以作为props属性
例子:<MediaList num = {1 + 2 + 2} />
(3)props里不能写if语句、for循环、switch语句
(4)可以接收函数调用的返回值
例子:<MediaList num = Math.random() />
(5)可以传入一个字符串字面量作为一个props属性
<MyComponent message="hello" />
等价于
<MyComponent message = {'hello'} />
(6)如果没有给props属性传值,那么它默认为true
9、属性展开语法
如果有个变量包含了props的内容,想传入整个对象,可以用扩展操作符...传入
function Child(props) {
const { name, age, addr } = props;
return (
<div>{name} : {age} : {addr}</div>
);
}
function B(props) {
const childProps = {
name: '张三',
age: 18,
addr: '北京'
};
return (
<div>
<Child {...childProps} />
</div>
);
}
效果:
10、什么是props.children,组件嵌套的内容
当我们在使用自定义组件时,那些被自定义组件所嵌套的内容,在子组件中使用props.children来接收
function Child(props) {
const { name, age, addr, children } = props;
// 处理children渲染问题
let childrenResult = null;
if (typeof children === 'function') {
childrenResult = children();
} else if (children) {
childrenResult = children;
}
return (
<div>
<div>{name} : {age} : {addr}</div>
<div>{childrenResult}</div>
</div>
);
}
function B(props) {
const childProps = {
name: '张三',
age: 18,
addr: '北京'
};
return (
<div>
<Child {...childProps} >
{ ()=>("子组件内容") }
</Child>
</div>
);
}
效果:
11、props.children可以是任何类型的数据,比如基本数据类型、引用数据类型、也可以是函数、null、undefined
12、在JSX语法中,默认就支持对数组的直接渲染
<div>{ [ <div key={1} style={{color:'red'}}>数组内容</div>, true, null, 100, JSON.stringify({a:1,b:2}), [1,2,3] ] }</div>
效果:
13、在JSX中,使用{}渲染Boolean、null、undefined,都会被忽略,也就是说不生成文本节点
14、React组件也可以返回一个元素数组
在React中,封装组件时,无论是类组件render的返回值,还是函数式组件的返回值,还可以是数组
function MyList() {
return [
<>
<div key={1}>数组内容1</div>
<div key={2}>数组内容2</div>
<div key={3}>数组内容3</div>
</>
]
}
效果:
更多推荐

所有评论(0)