Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React JSX语法 #12

Open
Wscats opened this issue Oct 16, 2017 · 0 comments
Open

React JSX语法 #12

Wscats opened this issue Oct 16, 2017 · 0 comments

Comments

@Wscats
Copy link
Owner

Wscats commented Oct 16, 2017

JSX

JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面,界面组件之间可以互相嵌套。可以理解为在JS中编写与XML类似的语言,一种定义带属性树结构(DOM结构)的语法,它的目的不是要在浏览器或者引擎中实现,它的目的是通过各种编译器将这些标记编译成标准的JS语言。

虽然你可以完全不使用JSX语法,只使用JS语法,但还是推荐使用JSX,可以定义包含属性的树状结构的语法,类似HTML标签那样的使用,而且更便于代码的阅读。

使用JSX语法后,你必须要引入babel的JSX解析器,把JSX转化成JS语法,这个工作会由babel自动完成。同时引入babel后,你就可以使用新的es6语法,babel会帮你把es6语法转化成es5语法,兼容更多的浏览器。

import React from 'react';
class PageB extends React.Component {
  constructor(props) {
    super(props);
    // 设置 initial state
    this.state = {
    };
  }
  componentDidMount() {
  }
  render() {
    return (
      <div>
      	<p>PageB</p>
      </div>
    )
  }
}
export default PageB;

在这个简单的例子中,看不出来有任何jsx语法的地方,当其中<div><p>PageB</p></div>就是使用到了jsx语法。HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写。

组件

  1. 在react中通常约定组件类的第一个字母必须大写,html标签都是小写。
  2. 组件类只能包含一个顶层标签,否则会报错

详情请参阅 React组件

样式

class属性需要写成 className,for属性需要写成 htmlFor,这是因为classfor是JavaScript的保留字

pageB.jsx

import React from 'react';
//引入外部样式
import './pageB.css';
// React component
class PageB extends React.Component {
  constructor(props) {
    super(props);
    // 设置 initial state
    this.state = {
    };
  }
  componentDidMount() {
  }
  render() {
    return (
      <div>
      	<p className="pageb-p">PageB</p>
      </div>
    )
  }
}

export default PageB;

pageB.css

.pageb-p{
	font-size: 40px;
}

直接在标签上使用style属性时,要写成style={{}}是两个大括号,外层大括号是告知jsx这里是js语法,和真实DOM不同的是,属性值不能是字符串而必须为对象,需要注意的是属性名同样需要驼峰命名法。即margin-top要写成marginTop

比如以下这个render

render() {
  return(
	<div style={{border: '1px solid blue', padding: '20px', marginBottom: '20px'}}>
	{/* 样式通过style={{}}的方法定义,里面的对象的属性值要用驼峰的写法 */}
	<p>{this.state.text}</p>
	<p>{this.props.name}</p>
        <input onChange={this.handleSubmit} />
     	</div>
  )
}

state和props

  1. 组件免不了要与用户互动,React 将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。
  2. getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。

由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。

ES5设置state和props

var HelloMessage = React.createClass({
  getDefaultProps: function() {
    return {
      name: 'Wscats'
    };
  },
  getInitialState: function() {
    return {
      skill: 'PS'
    }
  },
  render: function() {
    return <h1>Hello {this.props.name}{this.state.skill}</h1>;
  }
});
ReactDOM.render(
  <HelloMessage />,
  document.getElementById('example')
);

ES6设置state和props

class HelloMessage extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      skill: 'PS'
    }
  }
  render(){
    return <h1>Hello {this.props.name}{this.state.skill}</h1>
  }
}
HelloMessage.defaultProps = {
   name: 'Wscats'  
}
class Hello extends React.Component {
    this.state = this.getInitialState();
    getInitialState() {
        return {name: "Wscats"};
    } 
    render() {
        return <div>Hello {this.state.name}</div>;
    }
}

获取真实的DOM节点

组件并不是真实的DOM节点,而是存在于内存之中的一种数据结构,叫做虚拟DOM(virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。
有时需要从组件获取真实DOM的节点,这时就要用到ref属性。

import React from 'react';
class PageB extends React.Component {
  constructor(props) {
    super(props);
    // 设置 initial state
    this.state = {
    };
  }
  componentDidMount() {
  	//等到虚拟DOM插入文档以后,即componentDidMount生命周期后才能使用这个属性
  	this.refs.nihao.style.color = "red"
  }
  render() {
    return (
      <div>
      	{/*通过ref来获取真是DOM节点*/}
      	<p >PageC</p>
      	<p ref="nihao">{(function(){
      		return "你好"
      	})()}</p>
      </div>
    )
  }
}
export default PageB;

为了获取真是DOM节点,html元素必须有一个ref属性,然后this.refs.[refName]就会返回这个真实的 DOM节点。需要注意的是,由于this.refs.[refName]属性获取的是真实DOM,所以必须等到虚拟DOM插入文档以后,才能使用这个属性,否则会报错。

求值表达式

要使用JavaScript表达式作为属性值,只需把这个表达式用一对大括号( { } )包起来,不要用引号 ( " " )。
在编写JSX时,在{ }中不能使用语句(if语句、for语句等等),但可以使用求值表达式,这本身与JSX没有多大关系,是JS中的特性,它是会返回值的表达式。我们不能直接使用语句,但可以把语句包裹在函数求值表达式中运用。

条件判断的写法

你没法在JSX中使用if-else语句,因为JSX只是函数调用和对象创建的语法糖。在{ }中使用,是不合法的JS代码,不过可以采用三元操作表达式

可以使用比较运算符“ || ”来书写,如果左边的值为真,则直接返回左边的值,否则返回右边的值,与if的效果相同。

import React from 'react';
import './pageB.css';
class PageB extends React.Component {
  constructor(props) {
    super(props);
    // 设置 initial state
    this.state = {
    	name:""
    };
  }
  componentDidMount() {
  	var self = this;
  	setTimeout(function(){
  		self.setState({
  			name:"我是谁,我在哪里?"
  		})
  	},1000)
  }
  render() {
    return (
      <div>
      	<p>PageB</p>
      	{/*三元操作表达式*/}
      	<p className="pageb-p">1.三元操作</p>
      	<p>{this.state.name?this.state.name:"加载中"}</p>
      	{/*运算符||*/}
      	<p className="pageb-p">2.运算符||</p>
      	<p>{this.state.name||"加载中"}</p>
      </div>
    )
  }
}
export default PageB;

函数表达式

函数的语法可以这样,注意要用自执行,并且要传入this,和return出结果

<p>{(function(){
      	return "Wscats"
})()}</p>
<p>{(function(self){
      	console.log(self.state.name)
      	return self.state.name;
})(this)}</p>
<p>{(function(self){
      	{/*v-if*/}
      	if(self.state.bool){
      		return "假";
      	}else{
      		return "真";
      	}
})(this)}</p>
<p>
      	{/*过滤器*/}
      	{this.ed(this.state.name)}
</p>

过滤器的函数,接受this.state.name数据并处理再输出

//记得在this.state改变this.ed = this.ed.bind(this);
ed(data) {
	//模拟过滤器
	console.log(data)
	return data + "ed"
}

组件的生命周期

  • Mounting:已插入真实 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真实 DOM

详情请参阅 React组件生命周期

注释

JSX里添加注释很容易;它们只是 JS 表达式而已。你只需要在一个标签的子节点内(非最外层)小心地用{}包围要注释的部分。

{/* 一般注释, 用 {} 包围 */}

注意:

  1. 在标签内部的注释需要花括号
  2. 在标签外的的注释不能使用花括号
ReactDOM.render(
    /*注释 */
    <h1>Wscars{/*注释*/}</h1>,
    document.getElementById('example')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant