1、JSX简介---可以很好的描述UI应该呈现他应有交互的本质形式。
const element = <h1>Hello.world!</h1>;
为什么使用JSX?------React认为渲染逻辑本质上与其他UI逻辑内在耦合,但是并没有采用将标记与逻辑进行分离到不同文件的分离方式;
而是将两者共同存放在称之为“组件”的松散耦合单位之中,来实现关注点分离;
警告:
因为JSX语法上更接近JavaScript而不是HTML,所以React DOM 使用 camelCase(小驼峰命名)来定义属性名称,而
不使用HTML属性名称的命名约定。
例如: JSX里的class 变成 className ,而tabindex 则变成 tabIndex;
JSX防止注入攻击-----React DOM在渲染所有输入内容之前,默认会进行转义。他可以确保在你的应用中,永远不会
注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成字符串。可以有效防止XSS(cross-site-scripting,跨站脚本)攻击;
Babel会把JSX转义成一个名叫React.createElement()函数调用;
例如: const element = (<h1 className="greeting">hello,world!</h1>);
上面代码等同于
const element = React.createElement('h1',{className:'greeting','hello,world!'});
上面代码创建的一个这样的对象:
const element = {
type: 'h1',
props:{
className: 'greeting',
children:'hello,world'
}
} 该对象被称之为‘React元素’;
2、元素渲染
元素是构成React 应用的最小砖块;与浏览器的DOM元素不同,React元素是创建开销极小的普通对象。React DOM 会负责更新
DOM 来与React 元素保持一致;
React 元素是不可变对象;在实践中,大多数React应用只会调用一次ReactDOM.render();
React只更新它需要更新的部分;
3、组件&Props
3.1) 函数组件
function Welcome(props){
return <h1>Hello,{props.name}<h1/>
}
3.2) class组件
class Welcome extends React.Component {
render(){
return <h1>Hello,{this.props.name}</h1>
}
}
const element = <Welcome name="sara"/>;
当React元素为用户自定义组件时,他会将JSX所接收的属性转换为单个对象传递给组件,这个对象称之为“props”;
如: props = { name: 'sara'};
注意:组件名称必须以大写字母开头;React 会将以小写字母开头的组件视为原生DOM标签。例如:<div/>代表HTML的div标签,
而<Welcome/>则代表一个组件,并且需要在作用域内使用Welcom;
4、State & 生命周期
生命周期 componentDidMount ---代表React元素渲染到DOM中,就会调用该方法;
componentWillUnMount ----当React元素从DOM中移除时,就会调用该方法;
不能直接修改State,而是使用setState();构造函数是唯一可以给this.state赋值的地方;
State的更新可能是异步的----出于性能考虑,React 可能会将多个setState()调用合并成一个调用;
因为this.state和this.props可能会异步更新,所以不要依赖他们的值更新下一个状态;
//Wrong -----解决方案:可以让setState()接收一个函数而不是一个对象
this.setState({
counter: this.state.counter + this.props.increment
})
//Correct
this.setState((state,props)=>({
counter:state.counter + props.increment
}))
5、事件处理
1、在React中你不能通过返回false的方式阻止默认行为,必须显示使用preventDefault。
2、使用React时,你一般不需要使用addEventListener为已创建的DOM元素添加监听器。
仅仅需要在该元素初始渲染的时候添加一个监听器;
例如:
<button onClick={(e)=> this.deleteRow(id,e)}>Delete Row</button>
<button onClick={ this.deleteRow.bind(this,id)}>Delete Row</button>
上述两种方式是等价的,分别通过箭头函数和Function.prototype.bind来实现;
这两种情况下,React的事件对象e会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显示的进行传递;
而通过bind的方式,事件对象以及更多的额参数将会被隐式的进行传递;
6、条件渲染
if ,运算符&&,三目运算符
如何阻止组件渲染? 可以让render方法直接返回null
7、列表&Key
key只是在兄弟节点之间必须唯一;
8、表达
8.1) <input type=‘text’ value={this.state.value} onChange={this.handleChange}/>
8.2) <textarea value={this.state.value} onChange={this.handleChange}/>
8.3) <select value='this.state.value' onChange='{this.handleChange}'>
<option value='grapefruit'></option>
<option value='grapefruit'></option>
<option value='grapefruit'></option>
<option value='grapefruit'></option>
</select>
注意:可以将数组传递到value属性中,以支持在select标签中选择多个选项;
<select multiple={true} value={['B','C']};
9、状态提升
通常,多个组件需要反映相同的变化数据,这时建议将共享状态提升到最近的共同父组件中。
10、组合vs 继承
React有十分强大的组合模式。我们推荐使用组合而非继承来实现组件间的代码重用;
10.1)包含关系
第一种:使用props.children来将他们的子组件传递到渲染结果中;
第二种: 自行约定:将所需内容传入props,并使用相应的prop
{props.left} left={Contacts}
12、React哲学
通过问自己一下三个问题,你可以逐个检查相应数据是否属于state;
1) 该数据是否由父组件通过props传递而来的?如果是,那他应该不是state;
2) 该数据是否随时间的推移而保持不变?如果是,那他应该不是state;
3) 你能否根据其他state或props计算出该数据的值?如果是,那它不是state;
对于应用中的每一个state:
1)找到根据这个state进行渲染的所有组件;
2)找到他们的共同所有者(common owner)组件(在组件层级上高于所有需要该state的组件);
3)该共同所有者组件或者比它层级更高的组件应该拥有state;
4)如果你找不到一个合适的位置来存放该state,就可以直接创建一个新的组件来存放该state,并将这一新组建置于
高于共同所有者组件层级的位置;