初识JSX以及在react中的应用

什么是JSX(JavaScriptXml):一种js的扩展语法,支持react框架。jsx是react框架的核心,本质上是一种Dom结构的表示。
使用规则:和xml语法规则很类似,区别是可以用{}插入js语法。例如:
例子1:

<div id="mydemo1"></div>
<script type="text/babel">
     ReactDOM.render(
            <p>hello,myDemo1</p>,
       document.getElementById("mydemo1")
    );
</script>
下面写法与上面的一样
<div id="mydemo1"></div>
<script type="text/babel">
const myElement = (<p>hello,myDemo1</p>);
     ReactDOM.render(
            myElement,
       document.getElementById("mydemo1")
    );
</script>

例子2:

<div id="mydemo21"></div>
<script type="text/babel">
    var myArray = [
        <div>111111111</div>,
        <div>222222222</div>
    ];
    ReactDOM.render(
            <div>{myArray}</div>,
        document.getElementById('mydemo21')
    );
</script>
其中,栗子1中的 <p>hello,myDemo1</p>就是使用了jsx语法,即允许html和js混合书写,若要在html语法中插入js,则加{},如栗子2中的<div>{myArray}</div>。
注意script标签中的type属性,当使用jsx语法时,必须要给其加上type="text/babel"属性,因为需要babel解析。

jsx也可以是一个表达式,例如(官网上的例子):

function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

JSX 标签可能包含子元素,例如(官网上的例子):

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

JSX可以根据条件来渲染元素,说白了就是根据if或者条件操作符,来对当前渲染的元素进行判断处理。

<div id="condition"></div>
<script type="text/babel">
    var MyLoginState = React.createClass({
        render() {
            if(this.props.loginState){
                return <div>loginIn</div>
            }
            else {
                return <div>loginOut</div>
            }
        }
    });
    ReactDOM.render(
            <MyLoginState loginState={false}/>,
        document.getElementById('condition')
    );
</script>

JSX 防止注入攻击,在JSX中嵌入用户输入是安全的(官网例子):

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

默认情况下, 在渲染之前, React DOM 会格式化(escapes) JSX中的所有值. 从而保证用户无法注入任何应用之外的代码. 在被渲染之前,所有的数据都被转义成为了字符串处理。 以避免 XSS(跨站脚本) 攻击。
jsx在react中的使用:
ReactDOM.render 是 React 的最基本方法,将模板转为HTML语言,并插入指定的 DOM 节点。要渲染一个 React 元素到一个 根 DOM 节点,把它们传递给 ReactDOM.render() 方法,如上面的例子1和例子2。
React组件:react组件分两种写法,一是函数式组件,通俗来说就是一个返回react元素function,例如:

<div id="demofunction"></div>
<script type="text/babel">
    function Hello(props) {
        return <div>hello,{props.name}</div>
    }
    ReactDOM.render(
        <Hello name="hahaha"/>,
        document.getElementById('demofunction')
    );
</script>

第二种写法是class式组件,有两种写法,例如:
第一种写法

<script type="text/babel">
    var MyElement = React.createClass({
            render: function () {
                return <div >Hello {this.props.name}</div>
            }
        }
    );
    ReactDOM.render(
        <MyElement name="wanwan"/>,
        document.getElementById('democomponent')
    );
</script>

第二种写法

<div id="democomponentclass"></div>
<script type="text/babel">
    class MyComponentDemo extends React.Component {
        render() {
           return <div>I,m, {this.props.colors}</div>
        }
    }

    ReactDOM.render(
            <MyComponentDemo colors="greengreen"/>,
        document.getElementById('democomponentclass')
    );
</script>

注意,1.自定义组件的时候,首字母要大写,以区别xml语法中的标签,若首字母不大写则会报错。
    2.组件只能有一个父节点标签。
class式组件中,所有组件类必须有render方法,return的就是这个组件。
组件整合:组件可以整合,也就是说,输出的组件中,可以套用其他组件,例如:

<div id="componentmerge"></div>
<script type="text/babel">
    function ComponentMerge(props) {
        return <div>Hei,this is ComponentMerge,{props.name}</div>;
    }
    function MyApp() {
        return  <ComponentMerge name="wanwan"></ComponentMerge>;
    }

    ReactDOM.render(<MyApp />,
        document.getElementById('componentmerge')
    );
</script>

可以从小组件开始,整合到最顶层。
注意事项:1.再写jsx的时候,标签中的class属性,要用className代替,因为class是js中的保留字,同理,for 属性需要写成 htmlFor;2.this.props对象的属性与组件的属性一一对应,但是有一个例外,就是this.props.children 属性。它表示组件的所有子节点,this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。官方建议使用React.Children.map来遍历子节点,而不用担心数据类型。下面是this.props.children的一个例子:

<div id="children"></div>
<script type="text/babel">
    var ChildrenDemo = React.createClass({
        render: function (props) {
         var _this = this;
           return (
             <span>
                 {
                  React.Children.map(this.props.children, function (child) {
                   return <span>{child},{_this.props.name}</span>;
                    })
                  }
              </span>
            );
        }
    });
    ReactDOM.render(
            <ChildrenDemo name="wanwan">
                <span>hello</span>
                <span>   hei</span>
            </ChildrenDemo>,
        document.getElementById('children')
    );
</script>

状态state:class式组件特有的属性,与生命周期配合,用来触发组件的更新。例子如下:

<div id="statedemo"></div>
<script type="text/babel">
    class StateDemo extends React.Component {
        constructor(props) {
            super(props);
            this.state = {count: 0};
        }
//        渲染Dom时触发
        componentDidMount() {
            this.timeId =
                setInterval(() => this.countPlus(), 1000);
        }
//          删除Dom时触发
        conmponentWillUnMount() {
          clearInterval(this.timeId);
        }
        countPlus() {
            this.setState(this.setCount());
        }
        setCount(){
            this.state.count++;
        }
        render() {
            return <div>hello,count is {this.state.count}</div>
        }
    }
    ReactDOM.render(
            <StateDemo/>,
        document.getElementById('statedemo')
    );
</script>

首先,给class式组件添加构造函数并初始化state;当组件传入ReactDOM.render时,会调用组件的构造函数,同时就初始化了state;然后react调用了组件的render()函数,使组件得以显示;然后react更新dom,触发了生命周期componentDidMount(),执行生命周期中的内容;最后组件从dom中移除时,调用conmponentWillUnMount()生命周期。所以,一般在componentDidMount()发送网络请求,在setState()方法中进行渲染。
事件:例子如下

<script type="text/babel">
    class MyChange extends React.component{
        constructor(props){
            super(props);
            this.state = {clickState:false};
            // 这个绑定是必要的,使`this`在回调中起作用
            this.handleClick = this.handleClick.bind(this);
        }

        handleClick(){
            this.setState(this.change());
        }

        change(){
            this.state.clickState = !this.state.clickState;
        }

        render(){
            var text = this.state.clickState ? 'true' : 'false';
            return <button onclick={this.handleClick}>state is {text}</button>
        }

    }
  ReacrDom.render(
      <MyChange/>,
      document.getElementById('event')
  );
</script>

在jsx中,要传递一个函数处理事件,而元素处理事件是传递一个字符串;要在初始化函数中bind绑定,否则在传入事件的时候,this会是undefind。
转换列表与keys:列表指的是元素的集合,而列表里,每一个元素都要有个唯一的keys标识,来区别于其他元素,同时,可以使用keys来提取组件。

<div id="listitem"></div>
<script type="text/babel">
    function ListItem(props) {
        // 正确!这里不需要指定 key :
        return <div>{props.value}</div>;
    }
    function NumberList(props) {
        const numbers = props.numbers;
        const listItems = numbers.map((number) =>
            // 正确!key 应该在这里被指定
                <ListItem key={number.toString()}
                          value={number} />
        );
        return (
                <ul>
                    {listItems}
                </ul>
        );
    }
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
            <NumberList numbers={numbers} />,
        document.getElementById('listitem')
    );

</script>

键是React的一个内部映射,但其不会传递给组件的内部。如果你需要在组件中使用相同的值,可以明确使用一个不同名字的 prop 传入。

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);
上面的例子中, Post 组件可以读取 props.id,但是不能读取 props.key 。

表单:在 HTML 中,表单元素通常保持自己的状态,并根据用户输入进行更新。而在 React 中,可变状态一般保存在组件的 state(状态) 属性中,并且只能通过 setState() 更新。

<div id="myform"></div>
<script type="text/babel">
    class NameForm extends React.Component {
        constructor(props) {
            super(props);
            this.state = {value: ''};

            this.handleChange = this.handleChange.bind(this);
            this.handleSubmit = this.handleSubmit.bind(this);
        }

        handleChange(event) {
            this.setState({value: event.target.value});
        }

        handleSubmit(event) {
            alert(this.state.value+' was submitted');
        }

        render() {
            return (
                    <form onSubmit={this.handleSubmit}>
                        <label>
                            Name:
                            <input type="text" value={this.state.value} onChange={this.handleChange} />
                        </label>
                        <input type="submit" value="Submit" />
                    </form>
            );
        }
    }
    ReactDOM.render(<NameForm/>,document.getElementById('myform'));
</script>

当您需要处理多个受控的 input 元素时,您可以为每个元素添加一个 name 属性,并且让处理函数根据 event.target.name 的值来选择要做什么。例子见demo'someinput',因为太长了!
最后:组件可以接受任意的 props(属性) ,包括原始值、React 元素,或者函数。
如果要在组件之间重用非 U I功能,我们建议将其提取到单独的 JavaScript 模块中。组件可以导入它并使用该函数,对象或类,而不扩展它。
更多内容可以去官网仔细了解~

demo的github地址:https://github.com/rosaliefox/reactdemo.git