• [转] ReactJS之JSX语法


    JSX 语法的本质目的是为了使用基于 xml 的方式表达组件的嵌套,保持和 HTML 一致的结构,语法上除了在描述组件上比较特别以外,其它和普通的 Javascript 没有区别。 并且最终所有的 JSX 都会编译为原生 Javascript。

    JSX = JavaScript XML
    JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。

    特点

    • 类XML语法:有固定的标签开启和闭合。这能让复杂的树更易于阅读,优于方法调用和对象字面量的形式。
    • 增强JS语义:不是模板,模板与页面是分离的,是字符串,而JSX是JS语法本身,有更多的扩展
    • 结构清晰
    • 抽象程度高:屏蔽了手动的DOM操作,跨平台-JSX是独立于平台的语法,React在不同的平台提供解释器
    • 代码模块化:MVC是纵向切分,React是横向切分,大项目由众多小项目组成

    HTML组件 与 React组件

    HTML组件和HTML中原生的组件一样,而React组件是自定义的组件
    JSX 中约定以大小写字母开头来区分,组件一般以大写字母开头

    //JSX中支持绝大部分HTML标签
    <label className="lb" htmlfor="uName" style={{color:'red'; font-size:'14px'}}></label>

    // 组件类
    class MyComponent extends React.Component{
    render(){
    return <div>Customer Component:{this.props.name}</div>
    }
    }

    React.render(<MyComponent name="propsText"/>, document.getElementById('d1'))

    由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。

    JSX转换器

    JSX 把类 XML 的语法转成纯粹 JavaScript,XML 元素、属性和子节点被转换成 React.createElement 的参数。

    React.createElement(HTML标签名称/父组件,标签属性,子元素)

    //JSX语法
    <label className="xxx" htmlFor="input">content</label>

    //转换后
    React.createElement('label', {className: 'xxx', htmlFor: 'input'}, 'content')

    命名空间式组件

    如果一个组件拥有多个子组件,可以将子组件做为父组件的属性

    // 命令空间式组件
    class FormRoot extends React.Component{
    render(){
    return(
    <div>
    FromRoot
    {this.props.children}
    </div>
    )
    }
    }

    class Row extends React.Component{
    render(){
    return(
    <div className="box" style={{color:'#3f3', height:'auto'}}>
    Form Row {this.props.children}
    </div>
    )
    }
    }
    class Label extends React.Component{
    render(){
    return <div className="box" style={{color:'#f90'}}> Form Label </div>
    }
    }
    class Input extends React.Component{
    render(){
    return <div className="box" style={{color:'red'}}> Form Input </div>
    }
    }

    FormRoot.Row = Row;
    FormRoot.Label = Label;
    FormRoot.Input = Input;

    class APP extends React.Component{
    render(){
    return (
    <div className="box" style={{height:'auto'}}>
    <FormRoot>
    <FormRoot.Row>
    <FormRoot.Label />
    <FormRoot.Input />
    </FormRoot.Row>
    </FormRoot>
    </div>
    )
    }
    }

    React.render(<APP />, document.getElementById('box1'));

    Javascript表达式

    在JSX语法中,使用{}标识内部是JS表达式
    JSX是HTML和JavaScript混写的语法,当遇到<,JSX就当HTML解析,遇到{就当Javascript解析

    render(){
    return <Person name={window.isLoggedIn ? window.name : ''} />
    }

    属性表达式

    在使用 JS表达式 做为属性时,必须使用 {} 包含在内,不可使用 ""

    render(){
    return <div className={2 > 1 ? 'class-a' : 'class-b'}>content</div>
    }

    子表达式

    组件嵌套中同样可以使用 JS表达式 来处理组件的显示逻辑

    render(){
    return <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>
    }

    注释 (Comments)

    注释作用于源码,对源码做说明,不会出现实在渲染后的DOM中

    var content = (
    <div className="box">
    {/* 一般注释, 用 {} 包围 */}
    <span
    /* 多

    注释 */
    name={2>1 ? '2' : '1'} // 行尾注释
    >{2>1 ? '2' : '1'}</span>
    </div>
    );

    React.render(content, document.getElementById('box1'));

    延展属性(Spread Attributes)

    组件的属性应当在组件初始化时指定,而不应在初始化以后指定,这样会导致 props 对象的修改不可预测, React 也不能帮助检查属性类型。

    //better
    <Component foo={x} bar={y} />

    //bad
    <Component />
    Component.props.foo = x;
    Component.props.bar = y;

    属性延展是将一个对象添加为组件的属性的语法糖
    操作符 ... 是ES6中的延展语法(spread operator),可以将一个对象展开

    var props = { foo: x, bar: y };
    var component = <Component { ...props } foo={'override'}>;

    // 等价于
    var component = <Component foo={x} bar={y} />;

    注意:后面相同的属性覆盖掉前面的属性

    JSX陷阱

    style属性

    style属性是用两个 { 包含的,最外层的 { 表示内部是一个JS表达式,里面的 { 表示是一个JS对象字面量

    render(){
    return (
    <div style={{color:'red'}}>
    xxxxx
    </div>
    )

    }

    HTML转义

    React 默认会转义所有字符串,为了防止各种 XSS 攻击。
    可使用 __html 进行转义

    var content='<strong>content</strong>';

    React.render(
    <div>{content}</div>,
    document.body
    );
    //页面直接输出: <strong>content</strong>


    var content='<strong>content</strong>';

    React.render(
    <div dangerouslySetInnerHTML={{__html: content}}></div>,
    document.body
    );

    //输出加粗后的: content

    标签闭合

    在JSX中,无论是单标签还是成对的双标签,必有闭合符,不然会报错

    render(){
    return(
    <div>
    <img src="xxx.jpg" />
    <button>确认<button/>
    </div>
    )
    }

    根节点

    自定义组件在render()函数中返回的组件内容,必须有一个根节点包含起来

    // bad
    function render() {
    return (<p> .... </p>
    <p> .... </p>)
    }
    // good
    function render() {
    return (<p> .... </p>)
    }

    function render() {
    return (
    <div>
    <p> .... </p>
    <p> .... </p>
    </div>
    )
    }

    循环遍历

    通过循环遍历出生成的组件集合,在循环时一定要加上key


    render(){
    return (
    <p>
    {arr.map(function(it,i) {
    return <span key={i}> {it} </span>
    })}
    </p>
    )
    }

    IF-ELSE

    在JSX中是不可以直接在{}中加入if-else

    • 使用 三元操作符 来替代 if-else,或者将复杂的操作在JSX外面使用JS去处理
    • 使用闭包自执行函数
    //错误的写法
    // var App = (
    // <div>
    // {
    // if(2>1){
    // <p>SUCCESS</p>
    // }else{
    // <p>FAILURE</p>
    // }
    // }
    // </div>
    // );

    var App = (
    <div className="box">
    {
    2>1 ? <p>SUCCESS</p> : <p>FAILURE</p>
    }
    </div>
    );

    React.render(App, document.getElementById('box1'))


    // 或者
    // 将逻辑抽离到JS中执行
    var loginButton;
    if (loggedIn) {
    loginButton = <LogoutButton />;
    } else {
    loginButton = <LoginButton />;
    }

    return (
    <nav>
    <Home />
    {loginButton}
    </nav>
    );

    // 或者
    // 使用闭包自执行函数
    var App = (
    <div className="box">
    {
    (()=>{
    if(2>1){
    return <p>SUCCESS</p>
    }else{
    return <p>FAILURE</p>
    }
    })()
    }
    </div>
    );

    Show-Hide

    class App extends React.Component{
    constructor(){
    super()
    this.state={
    showHide: true
    }
    }
    render(){
    return (
    <div className="box" style={{heigth:'auto'}}>
    <div className={this.props.showHide?"":"hide"}>通过Props可以初始化这段文字的显示隐藏</div>
    <div className={this.state.showHide?"":"hide"}>通过State可以改变这段文字的显示隐藏</div>
    <input type="button"
    value={this.state.showHide ? '隐藏':'显示'}
    onClick={()=>{ this.setState({showHide : !this.state.showHide}) }}
    />
    </div>
    )
    }
    }

    React.render(<App showHide={true} />, document.getElementById('box1'))

    Switch-Case

    return (
    <section>
    <h1>Color</h1>
    <h3>Name</h3>
    <p>{this.state.color || "white"}</p>
    <h3>Hex</h3>
    <p>
    {(() => {
    switch (this.state.color) {
    case "red": return "#FF0000";
    case "green": return "#00FF00";
    case "blue": return "#0000FF";
    default: return "#FFFFFF";
    }
    })()}
    </p>
    </section>
    );

    Loop:循环

    var rows = [];
    for (var i=0; i < numrows; i++) {
    rows.push(<ObjectRow key={i}/>);
    }

    render(){
    return (<tbody>{rows}</tbody>);
    }

    相关示例

  • 相关阅读:
    Activity 横竖屏生命周期
    gradle wrapper, gradle ,gradle plugin 之间的关系
    《构建之法》第八、九章学习总结
    《构建之法》第六、七章学习总结
    《构建之法》第三、四、五章学习总结
    《构建之法》第一、二章学习总结
    SQL练习50题(基于MySQL)后25题
    SQL练习50题(基于MySQL)前25题
    轮播2-css
    轮播1-animate-匀速
  • 原文地址:https://www.cnblogs.com/chris-oil/p/8983104.html
Copyright © 2020-2023  润新知