• ReactJS读书笔记一:深入理解JSX


     

     

    分类: javascript react学习笔记
     

    目录(?)[+]

     
     
    这个系列是读《React 引领未来的用户界面开发框架》的笔记。
     
    JSX语法是react的一大亮点。
    之前很不喜欢在js中写模板,因为js字符串换行很麻烦,所以大家都习惯把模板用script标签写在html中。后来发现这样其实挺坑的,特别是当你的网站是前后端分离的时候,如果改一下模板还要找后端的开发,非常浪费时间。
    JSX的出现比较完美解决了JS中写模板的问题。简单的说就是 JS 和 HTML和混合着写在一起。
     

    一,JSX基本原理

     
    首先我们看一个官方最简单的例子
     
    [css] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. React.render(  
    2. <h1 color="red">Hello, world!</h1>,  
    3. document.getElementById('example')  
    4. );  


     
    然后他编译出来实际上是这样:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. React.render( React.createElement("h1", {color: "red"}, "Hello, world!"), document.getElementById('example') );  


     
    其中最关键的部分就是 html 代码被转换成了 React.createElement。
    这就是JSX的基本原理,他会自动识别html代码,并且全部转换成 React.createElement,于是编译出来的就是原生的JS代码。
    如果你不嫌麻烦,完全可以自己写 React.createElement 来创建模板,这样就不需要JSX了。
     
    JSX区分html代码的方式就是: 前括号之内并且首字母小写的就是html代码。如果首字母大写则就是react组件,后面会说到react组件。
     
    JSX会有详细的语法检查,如果你的标签未闭合会直接报错。而不像浏览器中可能会自动修复或者直接乱掉。
     
    因为JSX是兼容JS语法的,所以在html中如果有JS关键字就不要写,比如 class 要用 className 来代替。for 要用 htmlFor 来代替
     

    二,HTML模板中使用JS

     
    在HTML模板中使用JS非常方便,只需要用大括号把JS代码括起来即可。
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. var names = ['Alice', 'Emily', 'Kate'];  
    2.   
    3. React.render(  
    4. <div>  
    5. {  
    6. names.map(function (name) {  
    7. return <div>Hello, {name}!</div>  
    8. })  
    9. }  
    10. </div>,  
    11. document.getElementById('example')  
    12. );  


     
    编译出来就变成了这样:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. var names = ['Alice', 'Emily', 'Kate'];   
    2. React.render(   
    3.   React.createElement("div", null, names.map(function (name) {  
    4.     return React.createElement("div", null, "Hello, ", name, "!")   
    5.   }) ),  
    6.  document.getElementById('example')  
    7. );  


     
    要注意的是,大括号实际就是一个变量输出表达式,JSX最终就是直接把花括号中的内容作为 React.createElement 的第三个参数直接传入了(没有任何修改直接传入),所以其中只能放一行表达式,并且任何不能直接作为第三个参数的写法都是错的,
     
    那么你这样写就是错的:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. React.render(  
    2. <div>  
    3. {  
    4. var a = 1;  
    5. names.map(function (name) {  
    6. return <div>Hello, {name}!</div>  
    7. })  
    8. }  
    9. </div>,  
    10. document.getElementById('example')  
    11. );  


    因为很明显其中花括号内的内容直接放在第三个参数上,语法不对。
     
    这么写也是错的:
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. React.render(  
    2. <div>  
    3. {  
    4. var a = 1;  
    5.   
    6. }  
    7. </div>,  
    8. document.getElementById('example')  
    9. );  


     
    因为 React.createElement(“div”, null, var a = 1;) 是语法错误。
    那么你也可以理解为什么大括号中的js表达式不能有分号结尾了吧。
     
    需要注意的是,如果你在属性中输出JS变量,是不能加引号的,不然会被当做字符串而不被解析。
    应该是这样:
     
    <a title={title}>链接</a>
     

    三 组件嵌套

     
    JSX支持以XML的语法来嵌套组件:
     
    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <Nav><Profile>click</Profile></Nav>  


     
    实际上生成了:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. React.createElement(Nav,  
    2.   React.createElement(Profile, null, “click")  
    3. );  


     
    你也可以通过 JS 语法来写子节点:
     
    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <Nav>{login ? <Profile>click</Profile> : <Login>login</Login>}</Nav>  


     

    四,延展属性 spread attributes

     
    后面会讲到如何创建React组件:
     
    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. var HelloMessage = React.createClass({  
    2.   render: function() {  
    3.     return <h1>Hello {this.props.name}</h1>;  
    4.   }  
    5. });  
    6.   
    7. React.render(  
    8.   <HelloMessage name="John" />,  
    9.   document.getElementById('example')  
    10. );  


     
    其中 props 可以认为是一个配置接口,在使用 HelloMessage 组件的时候,传入的任何html属性都会保存在 this.props 中
    这个属性不一定是字符串哦,可以是任何JS变量,比如:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. var HelloMessage = React.createClass({  
    2.   render: function() {  
    3.     return <h1>Hello {this.props.name()}</h1>;  
    4.   }  
    5. });  
    6.   
    7. var sayName = function() {  
    8.   return "Lucy";  
    9. }  
    10.   
    11. React.render(  
    12.   <HelloMessage name={sayName} />,  
    13.   document.getElementById('example')  
    14. );  


     
    那么请注意,这个 this.props 应该当做只读变量,不允许对他有任何修改,比如你不能 this.props.name = ‘Lily’。这样是不符合规范的。因为他会导致组件和模板不一致。
     
    另外,有些时候你会需要直接把一个普通JS对象作为 props 传递给 React组件,比如你从数据库中取到了一个人物信息,那么你可以用 延展属性操作符 来做:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. var HelloMessage = React.createClass({  
    2. render: function() {  
    3. return <h1>Hello {this.props.name}</h1>;  
    4. }  
    5. });  
    6.   
    7. var Lucy = {  
    8. name: "Lucy",  
    9. gender: "female"  
    10. }  
    11. React.render(  
    12. <HelloMessage {...Lucy} />,  
    13. document.getElementById('example')  
    14. );  


     
    注意其中的 {…Lucy} 被编译成了:
     
    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. React.__spread({}, Lucy)  


     
    原理是不是很简单,就是一个类似 $.extend 的操作而已。
     

    五 一些需要注意的地方

     
    有几个在写JSX的时候需要注意的点
     
    1. 不要在HTML模板中写JS关键字,所以 class 应该用 className,for 应该用 htmlFor
    2. 所有的DOM标准属性都是驼峰命名,比如 onClick,但是 data-x 和 aria-x 还是用短横线分隔。
    3. style 属性接收的是一个 key-value 的JS对象,而不是字符串。
    4. 所有的事件都是和W3C规范一致的!因为React内部对事件做了封装。
    5. 表单输入属性,例如 value 和 checked,以及 textarea这里有更多相关信息
     
     
    参考:
    1. http://reactjs.cn/react/docs/jsx-in-depth.html
    2. http://www.ruanyifeng.com/blog/2015/03/react.html
     
  • 相关阅读:
    多线程中lock用法
    跨域使用Proxy page或Cross Frame
    new 操作符所做的事情
    跨域使用js文件
    跨域使用window.name
    TFS 映射错误( is already mapped in workspace)解决办法
    跨域使用JSONP
    jquery加载页面中的部分内容
    CQRS架构案例Tiny Library CQRS详解:AOP拦截与异常处理
    面向领域驱动架构的查询实现方式
  • 原文地址:https://www.cnblogs.com/HuiLove/p/4846115.html
Copyright © 2020-2023  润新知