React(2-1)- JSX

目录:

  1. 什么是JSX
  2. JSX表达式的特点
  3. JSX元素的不可变性

什么是JSX

// 这就是jsx表达式
const h1 = (<h1>hello user, i am jsx expresion</h1>); 

// 这是复杂一点的jsx表达式
const complexExpresion = (
    <div>
        <header>我是头部</header>
        <div className='content'>
            <p>helloWorld</p>
        </div>
        <footer>我是底部</footer>
    </div>
)

JSX是JS的一种语法扩展,他允许我们在js文件中写html结构并且能够跟js进行直接交互 在语法上有点类似于Vue的模板语法, 但是又不尽相同, 去除了过多的语言魔法(比如Vue中的v-on, v-if等, 但是在JSX中可以直接使用js携带的所有功能, 所以会显得特别的灵活和强大)

JSX表达式的特点

  1. JSX表达式最终会被babel编译成React.createElement
const span = (<span>helloWorld</span>);

// 上面的代码等同于
const span = React.createElement('span', {},'helloWorld');
  1. JSX表达式必须被闭合(遵守xml规范)
// 下面这种写法我们可以看到img标签没有被闭合, 这在最新的html5规范中是支持的, 但是在react中这样会报错
const errorImg = (<img src='https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg'>); 


// 可以写成如下写法

// 1. 单标签闭合
const niceImg = (<img src='https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg' />); 

// 2. 双标签闭合
const niceImg = (<img src='https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg'></img>); 
  1. JSX表达式有且只有一个根节点
// 由于JSX表达式最终会被babel编译成React.createElement

const span = (<span></span>);
// 上方表达式最终会被babel编译成如下格式
const span = React.createElement('span', {},, null); 

// 那么就注定了JSX表达式不能具有多个根元素, 因为假设我们写成如下这样
const span = (<span></span><a></a>);

// 你让babel咋编译, React.createElement第一个参数就只能有一个, 你这搁俩

如果有特殊情况, 某些场景中必须存在两个根节点, 则要使用React.Fragment

const demo = (
    <React.Fragment>
        <span></span>
        <a></a>
    </React.Fragment>
)

// 至于React.Fragment的原理在你学到React高阶组件的时候希望你留意一下组件中的children属性

// 同时React.Fragment还有一个语法糖如下
const demo2 = (
    {/*两个空标签进行包裹*/}
    <>
        <span></span>
        <a></a>        
    </>
)
  1. JSX表达式中的注释必须写成如下形式
const div = (
    <div>
        {/*这是注释*/}
    </div>
)
  1. 在JSX表达式中写属性必须使用小驼峰式命名, 且有些时候属性和关键字重名的话必须改名(比如class)
const h1 = (
    <h1 className='demo' style={{
        backgroundColor: 'red'
        width: '100px';
    }}>helloWorld</h1>
)

// 注意上方的style, style对应的是js中的style对象
// 我们需要写两个大括号, 最外层的大括号代表的是JSX表达式的标识符括号, 而里层的对象表示就是一个style对象, 两个括号的含义不一样
  1. 在JSX中插入表达式
// 在Vue中我们知道插入表达式 要使用插值表达式也就是 {{ }} 这哥们, 而在React中我们使用{}单括号

const a = 10;
const b = 20;

const h1 = (
    <h1>{ a } + { b } = { a + b }</h1>
)


// 这一对大括号中跟Vue能够放置的东西差不多

// 1. 函数执行

function foo() {
    return 'helloWorld';
}

const h1 = (
    <h1>{ foo() }</h1>
)


// 2. 数组(以及所有可迭代数据结构)
const arr = [1, 2, 3]
const h1 = (
    <h1>{ arr }</h1>
)


// 3. null, undefined, false, '' 在页面中在页面中都呈现为空, 但是元素结构会在

const demo = null;
const h1 = (
    <h1>{ demo }</h1>
)


// 4. &&, ||, 三元运算符
const h1 = (
    <h1>
        { 1 > 0 ? '你好' : '不太好' }
    </h1>
)


// 5. React元素对象
const li = (<li>helloWorld</li>);

const h1 = (
    <ul>
        { li }
    </ul>
)

// 同时我们也可以渲染复杂数据

const arr = [{name: 'loki'}, {name: 'thor'}];
const reactElementList = arr.map(ele => <li key={ ele.name }>{ ele.name }</li>);

const ul = (
    <ul>
        { reactElementList }
    </ul>
)

// 渲染结果不用多说也知道肯定两个li标签
// 而上面的key值跟Vue中v-for需要提供的key值作用一样, 当我写道react渲染原理的时候会详细说


// 6. 属性中放置JSX表达式
const imgUrl = 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg';

const img = (
    <img src={ imgUrl } />
)

// 其他的暂时想不起来了, 随用随写, JSX表达式过于灵活, 以至于骚操作特别多

关于上面的JSX中放置数组可以放置对象却不可以的问题

跟Vue一样, 从底层来说, 判断一个复合数据能不能在页面中被直接渲染出来的标准是他是否可迭代, 当我们在JSX中直接放置数组或者对象的时候, React会使用for..of来进行迭代, 并将结果展示出来, 而对象不能被for...of操作, 所以对象会报错, 而数组可以被迭代, 同时Map, Set都可以被迭代, 所以Map, Set都可以被展示出来, 而关于React元素, 则是因为React在底层做了一些特殊处理导致React元素对象也可以被渲染出来

const map = new Map([['name', 'loki']])

const h1 = (
    <h1>
        { map }
    </h1>
)

// 所以很多人片面的说在Vue或者React中使用的复合数据结构只有数组的话你就直接扇他

// 只要是具备迭代接口的数据都是可以进行渲染的, 数字字符串亦然, 这个不是什么需要背的东西
// 懂原因就不用记那么多的可被渲染数据结构了, 只需要记住一条: 可迭代可渲染

不过关于map这里也只做个演示, 在实际工作中不要使用Map或者对象直接渲染进页面, 因为React在虚拟dom中可能会对对象或者Map监控失败导致程序出现意外

  1. JSX对于XSS注入攻击的预防
// 1. 自动编码, 除了我们开发者自己编写的代码, 其他通过用户输入得到的数据JSX将会以字符串进行渲染
// 加入下面的context是用户输入的被我们截取到的文本
const context = '<div>helloWorld</div>'
const div = (
    <div>
        {/*context不会被渲染成div, 而是字符串<div>helloWorld</div>*/}
        { context }
    </div>
)


// 2. dangerouslySetInnerHTML, 如果我们执意要将这些React认为不安全的东西当成页面结构来解析
// 那么我们必须使用上面这个属性

const context = '<div>helloWorld</div>'
const div = (
    {/*经过如下的操作, context将会使用innerHTML来编译context*/}
    <div dangerouslySetInnerHTML = {{
        __html: context
    }}>
    </div>
)

JSX元素的不可变性]

每一个我们书写的JSX元素是一个对象, 但是这个对象中的所有属性无法更改, 如果需要更改, 则必须重新创建新的JSX元素出来

这个你了解一下即可, 因为这一时半会也说不清, 随着慢慢的深入你就明白了, 你现在就记着, 你必须重新渲染页面才能够使得JSX元素中的内容进行更改

let context = 'helloWorld';
const h1 = (
    <h1>{ context }</h1>
)

ReactDOM.render(h1, document.querySelector('#app'));

context = 'u r nice';

// 在上方更改了context以后必须重新调用render方法来完成页面更新
ReactDOM.render(h1, document.querySelector('#app'));

// 我知道你会问性能问题, 放心, 虚拟dom让你无惧性能挑战兄弟, 原理部分见, 入门还是别想这么多

猜你喜欢

转载自blog.csdn.net/weixin_44238796/article/details/105792891