1.样式
(1)React 推荐使用内联样式。我们可以使用 camelCase 语法来设置内联样式. React 会在指定元素数字后自动添加 px 。以下实例演示了为 h1 元素添加 myStyle 内联样式:
注意,在添加属性时, class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
var myStyle = {
fontSize: 100,
color: '#FF0000'
};
ReactDOM.render(
<h1 style = {myStyle}>菜鸟</h1>,
document.getElementById('example')
);
或者
ReactDOM.render(
<h1 style = {{fontSize:12}}>菜鸟</h1>,
document.getElementById('example')
);
注意样式属性要用驼峰命名法表示,如: backgroundColor 而不是 background-color,fontSize 而不是 font-size:
<input type="text" style={{"backgroundColor":"yellow","color":"red"}} value={value}/>
(2)vue我们可以用 v-bind 来设置样式属性。Vue.js v-bind 在处理 class 和 style 时, 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组。
使用 camelCase 语法来设置内联样式. Vue需要在指定元素数字后添加 px 。
<div v-bind:class="[activeClass, errorClass]"></div>
<div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
<div id="app">
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟</div>
</div>
2.JSX
ReactDOM.render 是 React 的最基本方法用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
ReactDOM.render(template,targetDOM) 方法接收两个参数:
第一个是创建的模板,多个 dom 元素外层需使用一个标签进行包裹,如 <div>
;
第二个参数是插入该模板的目标位置。
3.组件被定义为一个类
es6方式扩展 React.Component --React 16.4 实例
创建一个名称扩展为 React.Component 的 ES6 类,在 render() 方法中使用 this.state 来修改当前的时间[return方法返回HTML元素]。
添加一个类构造函数来初始化状态 this.state,类组件应始终使用 props 调用基础构造函数。
constructor类构造函数 初始化 this.state
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>现在是 {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('example')
);
React 15.4 实例
var title = "123";
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
ReactDOM.render(
<MyTitle title={title} />,
document.getElementById('example')
);
4.Props 验证
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
你可以通过组件类的 defaultProps 属性 为 props 设置默认值
5.父子模块互相传递参数
class CptBody extends React.Component{
constructor(){
super();
this.state = {username : 1}; //可以传json等很多格式(这个是初始化赋值)
}
//click事件函数
changeAge(){
this.setState({username:1+this.state.username})
}
//change事件函数
changeUsername(event){
//event.target指向<input type="text"/>
this.setState({username:parseInt(event.target.value)})
}
render(){
return(
<div>
<h1>父组件</h1>
<p>{this.state.username}</p>
<input type="button" value="点击改变username" onClick={()=>this.changeAge()}/>
<BodyChild changeUsername={this.changeUsername.bind(this)} getname={this.state.username}/>
</div>
)
}
}
class BodyChild extends React.Component{
render(){
return(
<div>
<p>子组件输入:<input type='text' value={this.props.getname} onChange={this.props.changeUsername} /></p>
</div>
)
}
}
ReactDOM.render(
<CptBody />,
document.getElementById('example')
);
BodyChild 组件的 render 函数返回值 jsx 中 <p>
的 value 是从父组件获取的 getname 这个变量值,onChange 获取的是 changeUsername 这个函数,所以如果文本框中的值改变了,改变值这个事件会触发 changeUsername 这个函数,这个函数会获得事件的值,即我们文本框修改后的值,并将其赋值给父组件的 state.username 这个变量。而父组件的这个变量改变后,state 随之改变,这时候,render 会重新启动,所以我们会看到修改后的值。
父组件的 jsx 中有一个箭头函数,有一个 bind 函数,这两者有什么区别吗?经验证,这两者是可以互换的。
onClick={this.changeAge.bind(this)} 和 onClick={()=>this.changeAge()} 可以互换。
箭头函数指向父级作用域。
6.React中this问题
你必须谨慎对待 JSX 回调函数中的 this,类的方法默认是不会绑定 this 的。如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候 this 的值会是 undefined。默认的this指向的是全局,全局中没有你定义在组件里面的函数。bind后的this指向的是上下文,也就是这个组件,这个组件才有你所需要的方法。
class LikeButton extends React.Component {
constructor() {
super();
this.state = {
liked: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({liked: !this.state.liked});
}
render() {
const text = this.state.liked ? 'liked' : 'haven\'t liked';
return (
<div onClick={this.handleClick}>
You {text} this. Click to toggle.
</div>
);
}
}
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
上面的demo中有大量this的使用,在 class LikeButton extends React.Component 中我们是声明该class,因为this具体是由其上下文决定的,因此在类定义中我们无法得知this用法。 相当于是new了上面定义的类,首先调用 constructor() 函数, this.state 的this上下文就是该实例对象;同理,render() 函数中 this.state.liked 的this上下文也是该对象。问题在于 onClick={this.handleClick} ,获取该函数引用是没有问题,这里的this上下文就是该对象。
这时问题来了,在原来 React.createClass 中, handleClick() 在onClick事件触发的时候,会自动绑定到LikeButton实例上,这时候该函数的this的上下文就是该实例。不过在ES6的class的写法中,Facebook取消了自动绑定,实例化LikeButton后,handleClick()的上下文是div的支撑实例( backing instance ),而 handleClick() 原本要绑定的上下文是LikeButton的实例。对于该问题,我们有多种解决方案。
我们通常建议在构造函数中绑定或使用属性初始化器语法来避免这类性能问题。
第一种:在ES6中可以在构造函数中,直接将当前组件(或者叫类)的实例与函数绑定。
在构造函数 constructor 内绑定this,好处是仅需要绑定一次,避免每次渲染时都要重新绑定,函数在别处复用时也无需再次绑定。
import React, {Component} from 'react'
class Test extends React.Component {
constructor (props) {
super(props)
this.state = {message: 'Allo!'}
//将类中this的指向指向类本身,否则,this指向undefined。
this.handleClick = this.handleClick.bind(this)
}
handleClick (e) {
console.log(this.state.message)
}
render () {
return (
<div>
<button onClick={ this.handleClick }>Say Hello</button>
</div>
)
}
}
如this.handleClick = this.handleClick.bind(this);
<script type="text/babel">
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 这边绑定是必要的,这样 `this` 才能在回调函数中使用
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this);
this.setState({isToggleOn: !this.state.isToggleOn})
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('example')
);
</script>
第二种:在方法编写结尾的时候绑定this,bind(this),即方法定义的时候。
handleClick = function() {
this.setState({
isToggleOn: !this.state.isToggleOn
));
}.bind(this);
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {opacity: 1.0};
}
componentDidMount() { //在第一次渲染后调用
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 3000);
}
render () {
return (
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
}
ReactDOM.render(
<Hello name="world"/>,
document.body
);
第三种:在方法调用的时候绑定this,如onClick={this.handleClick.bind(this)}。
值得注意的是,通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面,例如:
class Popper extends React.Component{
constructor(){
super();
this.state = {name:'Hello world!'};
}
preventPop(name, e){ //事件对象e要放在最后
//在 React 中你不能使用返回 false 的方式阻止默认行为, 你必须明确的使用 preventDefault。
e.preventDefault();
alert(name);
}
render(){
return (
<div>
<p>hello</p>
{/* 通过 bind() 方法传递参数。 */}
<a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
</div>
);
}
}
class Hello extends React.Component{
constructor(){
super()
this.state = {
content:true
}
}
change(obj){
this.setState({
content:!obj.content
})
console.log(obj)
}
render(){
return (
<div>
<h1>{this.state.content ? '1':'2'}</h1>
<h2>{this.props.name}</h2>
<button onClick={this.change.bind(this,this.state)}>
点击
</button>
</div>
)
}
}
ReactDOM.render(
<Hello name="Hello"/>,
document.getElementById('example')
)
第四种:箭头函数,ES6中的写法
如果你正在使用实验性的属性初始化器语法,你可以使用属性初始化器来正确的绑定回调函数:
class LoggingButton extends React.Component {
// 这个语法确保了 `this` 绑定在 handleClick 中
// 这里只是一个测试
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
如果你没有使用属性初始化器语法,你可以在回调函数中使用 箭头函数:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 这个语法确保了 `this` 绑定在 handleClick 中
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
回调函数中使用箭头函数不传参:
class Hello extends React.Component{
constructor(){
super()
this.state = {
content:true
}
}
change(){
this.setState({
content:!this.state.content
})
}
render(){
return (
<div>
<h1>{this.state.content ? '1':'2'}</h1>
<h2>{this.props.name}</h2>
<button onClick={()=>{this.change()}}>
点击
</button>
</div>
)
}
}
ReactDOM.render(
<Hello name="Hello"/>,
document.getElementById('example')
)
回调函数中使用箭头函数传参:
class Hello extends React.Component{
constructor(){
super()
this.state = {
content:true
}
}
change(obj){
this.setState({
content:!this.state.content
})
console.log(obj)
}
render(){
return (
<div>
<h1>{this.state.content ? '1':'2'}</h1>
<h2>{this.props.name}</h2>
<button onClick={()=>{this.change(this.state.content)}}>
点击
</button>
</div>
)
}
}
ReactDOM.render(
<Hello name="Hello"/>,
document.getElementById('example')
)
参考:
https://blog.csdn.net/qlin_11/article/details/91126275 React中this问题
https://www.jianshu.com/p/004b7f8452af React中this绑定四种方式
https://www.jianshu.com/p/d80c30cb4d71 属性初始化器的定义
7.React中条件渲染
&&
在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。
因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
您有 {unreadMessages.length} 条未读信息。
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('example')
);
condition ? true : false
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
setState()
setState() 可以接收一个函数,这个函数接受两个参数,第一个参数表示上一个状态值,第二个参数表示当前的 props:
this.setState((prevState, props) => ({
//do something here
}));